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.
-
Create a
Staticfile.js
in 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-pipeline
command line.
- 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.
npm install -g static-pipeline
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);
}
});
}
}
};
};
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,src
can be a globing pattern (details see node-glob) appended afterbase
, anddest
must be a directory. Details see globing example.ext
: (optional) a new extension to replace the input file's extension. Ignored ifbase
is not defined.
process
|function
: will be called withpipeline
object as argument for everysrc
file globed infiles
definition.depends
|string[]
: (optional) names of other tasks that should run before current one.
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.dest
as the output path. If called with content string, content will be saved topath
so you don't have to save output file manually.pipeline.write
|function(path, content)
: writecontent
topath
. 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 hashashedDest
property that is new destination path with MD5 hash appended before file extension, andhash
property that is the MD5 hash string.pipeline.gitHash
|function([string|Array, ]callback)
: seegithash
helper.pipeline.setAsset
|function(dest, hashedDest)
: see assets template helper.pipeline.assets
|function([url])
: seesetAsset
.
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
.
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.scss
src
->/home/source/file2.scss
,dest
->/home/public/file2.scss
src
->/home/source/partial/file3.scss
,dest
->/home/public/partial/file3.scss
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.css
src
->/home/source/file2.scss
,dest
->/home/public/file2.css
src
->/home/source/partial/file3.scss
,dest
->/home/public/partial/file3.css
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 currentsrc
file 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.hash
function, which returns an object withhash
andhashedDest
property.
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.
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
.
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
,assets
won't translate any url into hashed url.forceMap
|boolean
: defaultfalse
, iftrue
, whenassets
cannot 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 useassets
in your template. When usesetAsset
, thepublicDir
portion ofdest
will be replaced withbaseUrl
.baseUrl
|string
: default''
.
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
};
};
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.
assetMap
object contains url to hashed url mapoptions
options.strict=true
When true, throw error if url cannot be found inassetMap
options.disable=false
If true, will return passed in url directlyoptions.baseUrl=''
A string prepended before all hashed url