2
0
Fork 0
Old nodejs assets
Go to file
2015-03-14 16:16:31 +01:00
example switch example to ejs (for multi content type) 2015-03-09 20:31:31 +01:00
lib added regex filtering support 2015-03-14 16:16:31 +01:00
test fix bugs, more tests 2015-02-27 21:50:19 +01:00
.gitignore added example 2015-02-27 15:20:01 +01:00
.jshintignore fix bugs, more tests 2015-02-27 21:50:19 +01:00
.jshintrc redone with objects 2015-02-27 01:25:57 +01:00
.project Doc update 2015-02-24 14:10:50 +01:00
package.json fix bugs, more tests 2015-02-27 21:50:19 +01:00
README.md fix bugs, more tests 2015-02-27 21:50:19 +01:00

node-ff-assets

A Node.js library providing automatic site assets aggregation.

Installation

npm install node-ff-assets --save

Example Application

There is a fully working bootstrap with angularjs example in the example folder.

Usage

// note1: www_static/[js/css]/lib is version ignored.
// note2: server routes;
//   app.use('/static',                  express.static(path.join(__dirname,'www_static')));
//   app.use('/static/module/flot',      express.static(path.join(__dirname,'node_modules/flot/dist')));
//   app.use('/static/module/bootstrap', express.static(path.join(__dirname,'node_modules/bootstrap/dist')));

var assets   = require('node-ff-assets');

var assetsConfig = {
	// Map from uri paths to file systems paths.
	linkMapping : {
		'/static/module/bootstrap/': 'node_modules/bootstrap/dist/',
		'/static/module/flot/':      'node_modules/flot/',
		'/static/':                  'www_static/',
	},
	// Site sources in html page.
	linkSourcesCss : [
		'/static/module/bootstrap/css/bootstrap.css',
	],
	linkSourcesJs : [
		'/static/js/lib/jquery-2.1.3/jquery.js@http://code.jquery.com/jquery-2.1.3.js',
		'/static/module/bootstrap/js/bootstrap.js',
		'/static/module/flot/jquery.flot.js',
		'/static/module/flot/jquery.flot.resize.js',
		'/static/module/flot/jquery.flot.pie.js',
		'/static/js/lib/angularjs-1.4.0-b4/angular.js@https://code.angularjs.org/1.4.0-beta.4/angular.js',
		'/static/js/lib/angularjs-1.4.0-b4/angular-route.js@https://code.angularjs.org/1.4.0-beta.4/angular-route.js',
		'/static/js/lib/angularjs-1.4.0-b4/angular-resource.js@https://code.angularjs.org/1.4.0-beta.4/angular-resource.js',
		'/static/js/lib/angularjs-1.4.0-b4/angular-touch.js@https://code.angularjs.org/1.4.0-beta.4/angular-touch.js',
	],
};

// callback helper to return an assembler config per asset type
function createBuildConfig(type) {
	return function(callback) {
		// Override rendered result from command line
		var singleResult = 'false' != process.env.DEV_ASSETS_SINGLE_RESULT;
		if (type == 'css') {
			callback(null,{
				linkMapping: assetsConfig.linkMapping,
				linkTargetSingleResult: singleResult,
				linkTarget: '/static/css/lib/assets.css',
				linkSources: assetsConfig.linkSourcesCss,
				assetType: type,
			});
		} else {
			callback(null, {
				linkTargetSingleResult: singleResult,
				linkMapping: assetsConfig.linkMapping,
				linkTarget: '/static/js/lib/assets.js',
				linkSources: assetsConfig.linkSourcesJs,
				assetType: type,
			});
		}
	}
}

function buildAssets(server,callbackDone) {
	assets.build({
		assets: {
			js: {
				configCreate: createBuildConfig('js'),
				configFill: function (config, callback) {
					async.series([
						assets.factory.lib.async.pushLinkSources(config,  '/static/js/',             'www_static/js/'),
						assets.factory.lib.async.pushLinkSources(config,  '/static/js/controller/',  'www_static/js/controller/'),
					],callback);
				},
			},
			css: {
				configCreate: createBuildConfig('css'),
				configFill: function (config, callback) {
					async.series([
						assets.factory.lib.async.pushLinkSources(config, '/static/css/',            'www_static/css/'),
					],callback);
					
				},
				assemblerCreate: function (assemblerConfig, callback) {
					callback(null,new assets.AssetAssembler(assemblerConfig,assets.factory.assembler.constructor.readFileMinify()));
				},
			},
		},
		assemblerFill: function (assembler, callback) {
			var serverResultKey = 'ff_assets_'+assembler.config.assetType;
			assembler.on ('log',    assets.factory.assembler.event.log.console(assembler.config.assetType));
			assembler.on ('result', assets.factory.assembler.event.result.objectSet(server,serverResultKey));
			callback();
		},
	},callbackDone);
}

exports.build = function(server) {
	buildAssets(server,function(err) {
		if (err) {
			throw err;
		}
		console.log('Server init done.');
		// init other stuff...
	});
}

Config options

The config option of the objects are filled from config templates with defaults.

Builder Config

Only configCreate if required to set in root and/or in asset.

var template = {
	buildOrder: ['css','js'],
	
	configCreate:    null,
	configFill:      factory.builder.configCreate.nop(),
	assemblerCreate: factory.builder.assemblerCreate.readFile(),
	assemblerFill:   factory.builder.configCreate.nop(),
	
	assets: {
		js: {
			configCreate: null,
			configFill: null,
			assemblerCreate: null,
			assemblerFill: null,
		},
		css: {
			configCreate: null,
			configFill: null,
			assemblerCreate: null,
			assemblerFill: null,
		},
	},
};

Assembler Config

required: assetType,linkTarget,linkSources and linkMapping.

var name = 'node-ff-assets';
var downloadTimeout  = (1000*10)   * 6;  // 1min
var downloadMaxSize  = (1024*1024) * 10; // 10mb

var template = {
	downloadStartDelay: null,
	downloadForce: false,
	downloadOptions: {
		timeout: downloadTimeout,
		maxResponseLength: downloadMaxSize,
		agent: name+' remote fetcher',
	},
	
	linkTargetSingleResult: true,
	linkTarget: null,
	linkSources: [],
	linkMapping: [],
	
	assetType: null,
	assetHeader: '\n/* '+name+': begin */\n\n',
	assetFooter: '\n/* '+name+': end */\n\n',
	assetSeperator: '\n/* '+name+': next */\n',
};

Assembler Download Force

Sometimes its needed for have forces downloads of a resource. This can be done by adding an extra @ sign.

linkSources: ['/static/js/lib/dynamic-generated.js@@http://localhost:8080/example-ui/include-js/generateModels'];

note: if using localhost to download use the downloadStartDelay option so server is really up.

The downloadForce option will redownload all resources of asset group.

Target/Source locations

The asset target file location is a derived value.

Its created by mapping the assemblerConfig.linkTarget in the assemblerConfig.linkMapping keys to get a prefix for the local file system location.

The same is also true for the assemblerConfig.linkSources list which are url paths which need to be mapped to the file system files by the assemblerConfig.linkMapping data.

linkTarget: '/static/js/ffa/assets.js',
linkMapping: ['/static/':'www_static/',],
linkSources: ['/static/js/site.js','/static/js/ffa/jquery-2.1.3/jquery.js@http://code.jquery.com/jquery-2.1.3.js'],

Result;

public js  file: http://localhost:8080/static/js/site.js
public js  file: http://localhost:8080/static/js/ffa/assets.js
public js  file: http://localhost:8080/static/js/ffa/jquery-2.1.3/jquery.js
filesystem file: www_static/js/site.js
filesystem file: www_static/js/ffa/assets.js
filesystem file: www_static/js/ffa/jquery-2.1.3/jquery.js
.gitignore line: www_static/js/ffa

if buildConfig.linkTargetSingleResult = true then result
  static/js/ffa/assets.js
else
  static/js/site.js
  static/js/ffa/jquery-2.1.3/jquery.js

Objects

For some use cases the assets.build(config,callback) is flexable enough. Then there are two objects which may provide the needed options.

Object AssetsBuilder

var assets = require('node-ff-assets');
var builderConfig = {...};

// Create builder
var assetsBuilderA = new assets.AssetsBuilder(builderConfig);

// Run all
assetsBuilderB.runAll(function(err) {
	//done
});

// Run singles
async.series([
	assetsBuilderC.runAsset('css'),
	assetsBuilderD.runAsset('js'),
],function(err) {
	//done
});

Object AssetAssembler

var assets = require('node-ff-assets');
var assemblerConfig = {...};

// Create default assembler.
var assetAssemblerA = new assets.AssetAssembler(assemblerConfig);

// Same as default, plain inclusion of content.
var assetAssemblerB = new assets.AssetAssembler(assemblerConfig,assets.factory.assembler.constructor.readFile());

// Minify content, with optional Minify config options.
var assetAssemblerC = new assets.AssetAssembler(assemblerConfig,assets.factory.assembler.constructor.readFileMinify());
var assetAssemblerD = new assets.AssetAssembler(assemblerConfig,assets.factory.assembler.constructor.readFileMinify(minifyOptions));

// Third party content modifiers, with readFile function
var assetAssemblerE = new assets.AssetAssembler(buildConfig,function(file,callback) {
	// should return file data to callback(err,data);
);

// Registrate events (note: may change a bit)
assetAssemblerA.on('begin',               function() { });
assetAssemblerA.on('end',                 function() { });
assetAssemblerA.on('log',                 function(logLevel, logMessage) { });
assetAssemblerA.on('result',              function(resultValue) { });
assetAssemblerA.on('file-download-pre',   function(remoteUrl) { });
assetAssemblerA.on('file-download-post',  function(localFile) { });
assetAssemblerA.on('file-read-pre',       function(localFile) { });
assetAssemblerA.on('file-read-post',      function(localFile) { });
assetAssemblerA.on('file-write-pre',      function(targetFile) { });
assetAssemblerA.on('file-write-post',     function(targetFile) { });

// Use build in event functions
assetAssemblerB.on('log',     assets.factory.assembler.event.log.console('css'));
assetAssemblerB.on('result',  assets.factory.assembler.event.result.objectSet(server,'includeCssFiles'));

// Run builder
assetAssemblerC.run(function(err) {
	//done
});

Rendering

In these examples I use the server (app/express) object to store the results in for displaying. Which the index page renderer will get and inject in page context.

function renderIndex(app) {
	return function (req, res, next) {
		res.render('index', {
			includeCssFiles:    server.get('ff_assets_css'),
			includeJsFiles:     server.get('ff_assets_js'),
		});
	}
};
app.get('/',renderIndex(app));

// Template
index.jade
	doctype html
	html(lang='en',ng-app='ffUI')
	  head
	    base(href='/ui')
	    title='Index'
	    meta(charset='UTF-8')
	    meta(http-equiv='X-UA-Compatible' content='IE=edge')
	    meta(name='viewport' content='width=device-width, initial-scale=1')
	    meta(name='keywords' content='keywords')
	    each cssFile in includeCssFiles
	      link(rel='stylesheet' href='#{cssFile}')
	  body
	    div(id='wrapper')
	      div(ng-include='\'/ui/include/html/layout/header\'')
	      div(id='page-wrapper')
	        div(id='container-fluid')
	          div(ng-view)
	    div(ng-include='\'/ui/include/html/layout/footer\'')
	    each jsFile in includeJsFiles
	      script(src='#{jsFile}')

Example log output

// Result First run
info: node-ff-assets-css build begin for: /static/css/lib/assets.css
debug: node-ff-assets-css readFile: node_modules/bootstrap/dist/css/bootstrap.css size: 285496
debug: node-ff-assets-css readFile: www_static/css/boot.css size: 1606
debug: node-ff-assets-css readFile: www_static/css/flot.css size: 82
debug: node-ff-assets-css readFile: www_static/css/panel.css size: 545
debug: node-ff-assets-css readFile: www_static/css/style.css size: 10419
debug: node-ff-assets-css target size: 298318
info: node-ff-assets-css build result size: 1 from: 5
info: node-ff-assets-css build done in: 33 ms.
info: node-ff-assets-js build begin for: /static/js/lib/assets.js
debug: node-ff-assets-js downloadFile: http://code.jquery.com/jquery-2.1.3.js
debug: node-ff-assets-js downloadFile: https://code.angularjs.org/1.4.0-beta.4/angular.js
debug: node-ff-assets-js downloadFile: https://code.angularjs.org/1.4.0-beta.4/angular-route.js
debug: node-ff-assets-js downloadFile: https://code.angularjs.org/1.4.0-beta.4/angular-resource.js
debug: node-ff-assets-js downloadFile: https://code.angularjs.org/1.4.0-beta.4/angular-touch.js
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test1
GET /ui/include/js/controller/test1 200 7.931 ms - -
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test2
GET /ui/include/js/controller/test2 200 5.215 ms - -
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test3
GET /ui/include/js/controller/test3 200 1.583 ms - -
debug: node-ff-assets-js readFile: www_static/js/lib/jquery-2.1.3/jquery.js size: 247387
debug: node-ff-assets-js readFile: node_modules/bootstrap/dist/js/bootstrap.js size: 66732
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.js size: 110008
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.resize.js size: 2504
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.pie.js size: 23405
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular.js size: 988198
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-route.js size: 35796
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-resource.js size: 26780
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-touch.js size: 22887
debug: node-ff-assets-js readFile: www_static/js/app-directives.js size: 185
debug: node-ff-assets-js readFile: www_static/js/app-filters.js size: 202
debug: node-ff-assets-js readFile: www_static/js/app-services.js size: 80
debug: node-ff-assets-js readFile: www_static/js/app.js size: 766
debug: node-ff-assets-js readFile: www_static/js/controller/page-about.js size: 364
debug: node-ff-assets-js readFile: www_static/js/controller/page-foobar.js size: 361
debug: node-ff-assets-js readFile: www_static/js/controller/page-index.js size: 351
debug: node-ff-assets-js readFile: www_static/js/controller/page-help.js size: 376
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test1.js size: 2010
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test2.js size: 2138
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test3.js size: 2218
debug: node-ff-assets-js target size: 1540945
info: node-ff-assets-js build result size: 1 from: 24
info: node-ff-assets-js build done in: 3497 ms.
info: Server init done.

// Result Next runs
info: node-ff-assets-css build begin for: /static/css/lib/assets.css
debug: node-ff-assets-css readFile: node_modules/bootstrap/dist/css/bootstrap.css size: 285496
debug: node-ff-assets-css readFile: www_static/css/boot.css size: 1606
debug: node-ff-assets-css readFile: www_static/css/flot.css size: 82
debug: node-ff-assets-css readFile: www_static/css/panel.css size: 545
debug: node-ff-assets-css readFile: www_static/css/style.css size: 10419
debug: node-ff-assets-css target size: 298318
info: node-ff-assets-css build result size: 1 from: 5
info: node-ff-assets-css build done in: 36 ms.
info: node-ff-assets-js build begin for: /static/js/lib/assets.js
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test1
GET /ui/include/js/controller/test1 200 7.931 ms - -
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test2
GET /ui/include/js/controller/test2 200 5.215 ms - -
debug: node-ff-assets-js downloadFile: http://localhost:8008/ui/include/js/controller/test3
GET /ui/include/js/controller/test3 200 1.583 ms - -
debug: node-ff-assets-js readFile: www_static/js/lib/jquery-2.1.3/jquery.js size: 247387
debug: node-ff-assets-js readFile: node_modules/bootstrap/dist/js/bootstrap.js size: 66732
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.js size: 110008
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.resize.js size: 2504
debug: node-ff-assets-js readFile: node_modules/flot/jquery.flot.pie.js size: 23405
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular.js size: 988198
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-route.js size: 35796
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-resource.js size: 26780
debug: node-ff-assets-js readFile: www_static/js/lib/angularjs-1.4.0-b4/angular-touch.js size: 22887
debug: node-ff-assets-js readFile: www_static/js/app-directives.js size: 185
debug: node-ff-assets-js readFile: www_static/js/app-filters.js size: 202
debug: node-ff-assets-js readFile: www_static/js/app-services.js size: 80
debug: node-ff-assets-js readFile: www_static/js/app.js size: 766
debug: node-ff-assets-js readFile: www_static/js/controller/page-about.js size: 364
debug: node-ff-assets-js readFile: www_static/js/controller/page-foobar.js size: 361
debug: node-ff-assets-js readFile: www_static/js/controller/page-index.js size: 351
debug: node-ff-assets-js readFile: www_static/js/controller/page-help.js size: 376
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test1.js size: 2010
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test2.js size: 2138
debug: node-ff-assets-js readFile: www_static/js/lib/xcrud/test3.js size: 2218
debug: node-ff-assets-js target size: 1540945
info: node-ff-assets-js build result size: 1 from: 24
info: node-ff-assets-js build done in: 105 ms.
info: Server init done.

Tests

npm test

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.

Release History

0.2.2

  • Fixed error to callback
  • Fixed 404 error
  • Removed error event
  • Added log event to builder
  • Added builder tests
  • Made example jslint pass

0.2.1

  • Added example application
  • Fixed buid callback
  • Fixed buildOrder default
  • Updated doc

0.2.0

  • Redone objs
  • Added tests
  • Made jslint pass

0.1.x

  • Added objectAdd
  • Doc updates
  • Initial release