static-pipeline v0.4.7
Static Pipeline
Static Pipeline is not another build system or task runner. It is a static assets processing framework and template helper. You can use whatever assets preprocessor you want.
Usage
- Create a
Staticfile.jsin your root directory. In
Staticfile.js, define tasks by exporting an configuration function:var sass = require('node-sass'); module.exports = function(config) { config.tasks = { scss: { files: [{ src: 'source/app.scss', dest: 'public/app.css', }], process: function(pipeline) { sass.render({ file: pipeline.src, success: function(results) { pipeline.done(results.css); } }); } } }; };Run
static-pipelinecommand line.
Why Use Static Pipeline instead of Gulp or Grunt?
- Build tools and task runners like Gulp and Grunt all depend on their plugins. Plugins prevents you from using the real power of original assets processing tools, e.g. node-sass or browserify. Why bother learning browserify plugin instead of the browserify itself?
- For static assets to bust browser cache, we often append a hash to the asset's url. The process of hashing assets then render template with hashed url is hard to maintain and inflexible.
- Static Pipeline is a framework with which you can use whatever processor you want. It will also save each hash assets url. So you can use them with template helper to provide correct assets' urls.
Install
npm install -g static-pipelineAPI
module.exports = function(config) {
config.tasks = {
scss: {
files: [{
src: 'source/app.scss',
dest: 'public/app.css',
}],
process: function(pipeline) {
// We are using node-sass to render scss files to css
sass.render({
file: pipeline.src,
success: function(results) {
// Call done with string to save the string to destination path
pipeline.done(results.css);
}
});
}
}
};
};Tasks
Assign config.tasks property with an object. In the example above, scss is the task name.
files|Object[]: is an array of glob definitions. Each glob definition is an object with:src: path to input file, relative toStaticfile.js.dest: relative path to output file.base: (optional) relative base path forsrc. If defined,srccan be a globing pattern (details see node-glob) appended afterbase, anddestmust be a directory. Details see globing example.ext: (optional) a new extension to replace the input file's extension. Ignored ifbaseis not defined.
process|function: will be called withpipelineobject as argument for everysrcfile globed infilesdefinition.depends|string[]: (optional) names of other tasks that should run before current one.
pipeline object
pipeline has following properties/methods. They essentially are just helpers to complete the build process.
pipeline.src|string: absolve path of input file.pipeline.dest|string: absolve path of output file.pipeline.done|function([path, ][content]): call this function to indicate process is finished. The first argument is the path of output file, if ignored it will use thepipeline.destas the output path. If called with content string, content will be saved topathso you don't have to save output file manually.pipeline.write|function(path, content): writecontenttopath. Similar topipeline.done, but doesn't indicate current task is finished.pipeline.hash|function(string) -> Object: call with the content ofdest. It return an object. The object hashashedDestproperty that is new destination path with MD5 hash appended before file extension, andhashproperty that is the MD5 hash string.pipeline.gitHash|function([string|Array, ]callback): seegithashhelper.pipeline.setAsset|function(dest, hashedDest): see assets template helper.pipeline.assets|function([url]): seesetAsset.
File Globing Examples
Only src and dest
Assume current project root is /home.
{
src: 'source/app.scss',
dest: 'public/app.css'
}Will generate
src->/home/source/app.scss,dest->/home/public/app.css.
Define base and src glob
Assume source directory has file1.scss, file2.scss and partial/file3.scss.
{
base: 'source',
src: '**/*.scss',
dest: 'public'
}src->/home/source/file1.scss,dest->/home/public/file1.scsssrc->/home/source/file2.scss,dest->/home/public/file2.scsssrc->/home/source/partial/file3.scss,dest->/home/public/partial/file3.scss
Use ext
Assume source directory has file1.scss, file2.scss and partial/file3.scss.
{
base: 'source',
src: '**/*.scss',
dest: 'public',
ext: 'css'
}src->/home/source/file1.scss,dest->/home/public/file1.csssrc->/home/source/file2.scss,dest->/home/public/file2.csssrc->/home/source/partial/file3.scss,dest->/home/public/partial/file3.css
gitHash helper
Git hash is an alternative to MD5 hash. This helper will obtain the git commit hash for specified file. If an array of files are provided, it will select the lastest git commit hash among provided files.
Signature: function([string|Array, ]callback)
- If called with only
callback, it will use currentsrcfile to get git commit hash. - With single path, will use provided path to get git commit hash.
- With array of paths, will get git hash for all the files in array, then select the lastest commit.
- Callback signature
function(Error, Object): error will occur if one of the paths has changes that are not committed. Format of object is the same as the return value ofpipeline.hashfunction, which returns an object withhashandhashedDestproperty.
Assets Template Helper
assets helper
assets only works with absolute urls
The assets helper maps dest to hashedDest when you render template so you when you update your static assets, browser cache is busted.
In your template you can use:
head
//- Will map `/css/app.css` to `/css/app-202cb962ac59075b964b07152d234b70.css`
link(rel='stylesheet' href=assets('/css/app.css'))
//- Will do the same thing for `index.js`
script(src=assets('/js/index.js'))
body
.img-container
//- Can also work on images
img(src=assets('/img/logo.svg'))In order to use assets function in template, you have to pass it as locals. For example, if you are using Jade:
var jade = require('jade');
module.exports = function(config) {
config.tasks = {
jade: {
files: [{
src: 'source/index.jade',
dest: 'public/index.html',
}],
process: function(pipeline) {
var html = jade.renderFile(pipeline.src, {
assets: pipeline.assets
});
pipeline.done(html);
}
}
};
};If assets was called directly without any argument. It will return the assetsMap object contains all mappings.
setAsset
Put dest and hashedDest pair into assets map, so next time assets see the url relative to dest it will auto matically translate it into url relative to hashedDest.
Assets Helper Configuration
module.exports = function(config) {
config.options = {
assets: {
useMap: true,
forceMap: false,
publicDir: 'public' // required if want to use `assets` helper
baseUrl: 'http://my-cdn.com'
// `public/js/index.js` will become
// `http://my-cdn.com/js/index.js`
//
// If baseUrl is not defined, it will become
// `/js/index.js`
}
};
};useMap|boolean: defaulttrue, iffalse,assetswon't translate any url into hashed url.forceMap|boolean: defaultfalse, iftrue, whenassetscannot pair url with a hashed url, it will throwAssetNotFoundError. Iffalse, it will return the same url that passed in.publicDir|string: required if you want to useassetsin your template. When usesetAsset, thepublicDirportion ofdestwill be replaced withbaseUrl.baseUrl|string: default''.
Other Config
module.exports = function(config) {
config.options = {
// Used in development, if true, all hash function will not return hash but
// the original file name instead
disableHash: false
};
};Express.js Template Helper
var assetMap = require('./assets.json');
var assets = require('static-pipeline/helper-factory')(assetMap, options);
// http://expressjs.com/4x/api.html#app.locals
app.locals.assets = assets;static-pipeline/helper accepts two arguments.
assetMapobject contains url to hashed url mapoptionsoptions.strict=trueWhen true, throw error if url cannot be found inassetMapoptions.disable=falseIf true, will return passed in url directlyoptions.baseUrl=''A string prepended before all hashed url