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.
- Introducing the Frontend Builds Article Series
- Frontend Builds 1: Getting Started
- Frontend Builds 2: Readable and Pluggable Gulpfiles
- Frontend Builds 3: Cross-Platform Desktop Builds
- Frontend Builds 4: Building Cross-Platform Mobile Apps
- Frontend Builds 5: Build as a Service (BaaS)
- 👉🏻 Frontend Builds 6: Configurable builds
- Frontend Builds 7: Conditional Build Tasks
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-files
’init
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.