The Frontend Builds article series

Welcome to the sixth part of this article series. If you didn’t read the other parts, check them out now.

Idea

BaaS is fine so far if you’re building your projects on the same structure I did for building x-note. However, right now, we’re using Build as a Service, so it’s time to make everything configurable.

Dumping all the default config values

BaaS should run successfully without any give user-config. That said, we need some defaults. I’ve added a new JavaScript file to xplatform-build at src/defaults.js. It exposes all default config values as you can see below.

The script below is stripped to increase readability. See the entire file here in the repo

(function(module){
  function exportDefaultConfig(){
    var path = require('path');
        
    var cacheDir = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE, '.cache'),
        buildDir = path.join(process.cwd(), "desktop-build");
    return {
        folders: {
            mobile: {
                root: 'mobile',
                backlinkToProjectRoot: '..'
            },
            dist:{
                root: 'dist',
                styles: 'dist/styles',
                scripts: 'dist/scripts'
            },
            temp:{
                root: ".temp"
            }
        },
        filenames: {
            appScripts: 'app.js',
            appStyles: 'app.min.css',
            vendorStyles: 'vendor.min.css',
            vendorScripts: 'vendor.min.js',
            injectTargets: ['src/index.html']
        },
        sources: {
            // stripped to increase readability
        },
        options: {
            // stripped to increase readability
        }
    };
}

  module.exports = exportDefaultConfig();

})(module);

All defaults where exported using the familiar module.exports mechanism.

Refactor gulp-task-files

Next, I refactored, of course, all gulp-task-files, again go and check out all the changes over here. In summary, the method signature must accept another parameter and all

(function(module) {
    'use strict';
    function RegisterTasks(gulp, tasks, config) {
    
      gulp.task('private:build', function(done) {
        tasks.inSequence(
            'private:clean',
            'private:app:templates', [
                'private:vendor:css',
                'private:vendor:js',
                'private:app:css',
                'private:app:js'
            ],
            'private:app:html',
            done
        );
      });
      
      gulp.task('private:clean', function(done) {
          // replace all strings with config properties
          tasks.del.sync(config.sources.del, config.options.del);
          done();
      });
      
      /*
      * stripped to ensure readability
      */
    }

    module.exports = {
        init: RegisterTasks,
        docs: [
        // stripped to ensure readability
        ]
    };
})(module);

Refactor the gulpfile

Last but not least the src/gulpfile.js has to be updated. A few things are going on here.

  • add the possibility to pass config to the gulpfile.js
  • load the default config
  • override default config with user-config
  • pass merged config to gulp-task-filesinit method

See the entire gulpfile.js here.

(function(module){
    
  function XplatformBuild(userConfig){
      var gulp = require('gulp');
      
      var tasks = {
          del: require('del'),
          concat: require('gulp-concat'),
          inject: require('gulp-inject'),
          cssmin: require('gulp-cssmin'),
          ngAnnotate: require('gulp-ng-annotate'),
          ngTemplateCache: require('gulp-angular-templatecache'),
          rename: require('gulp-rename'),
          shelljs: require('shelljs'),
          uglify: require('gulp-uglify'),
          path: require('path'),
          NwBuilder: require('nw-builder'),
          inSequence: require('run-sequence')
      };

      var override = function(original, uConfig){
          for(var p in uConfig){
              if(typeof(uConfig[p]) !== 'object' || Array.isArray(uConfig[p])){
                  original[p] = uConfig[p]
              }else{
                  override(original[p], uConfig[p]);
              }
          }
          
      };
        
      var config = require('./defaults.js');
      override(config, userConfig);
      
      var customGulpTasks = require('require-dir')('./gulptasks');
      
      for (var gulpTask in customGulpTasks) {
          customGulpTasks[gulpTask].init(gulp, tasks, config);
      }
      
      gulp.task('help', function() {
          console.log('Execute one of the following commands\n');
          for (var gulpTask in customGulpTasks) {
              if (!customGulpTasks[gulpTask].hasOwnProperty('docs')) {
                  continue;
              }
              customGulpTasks[gulpTask].docs.map(function(doc) {
                  console.log("gulp " + doc.task + " - (" + doc.description + ")");
              });
          }
          console.log('\n');
      });
  }

module.exports = XplatformBuild;

})(module);

Refactor the usage in x-note

After refactoring your BaaS (here xplatform-build), of course, the application itself has to be refactored. This is the easy part; there is just a small updated for the gulpfile.js. See the () behind the require call

require('xplatform-build')();

If you’d like to provide a custom user-config just pass it as json object to the call like shown below.

// USE THIS SNIPPET ONLY IF YOU'D LIKE TO OVERRIDE 
// DEFAULT SETTINGS
require('xplatform-build')({
    options: {
        cordova: {
            runCommands: [
               'cordova run ios', 
               'cordova run android', 
               'cordova run windows'
            ]
        }
    }
});

Again, see xplatform-build here and the BaaS branch of x-note over here

Go ahead …

.. so read the next article in the “Frontend Build” article series.