welcome to shifter 0.4.2!
what is shifter?
The purpose of this project is to replace YUI's use of our old ant Builder.
We have out grown our old builder, so it was time to build a new one!
installation and usage
- download and install node.js
- run
npm -g install shifter
- run
shifter
from inside the of a module inside the yui3 git repo or the yui3-gallery repo.
command line arguments
below is a simple list of commands that shifter
supports.
$ shifter -h
blazingly fast builds with shifter@0.4.2
pass no arguments and shifter will build the module from the current directory
-v/--version show version
-h/--help show this stuff
-m/--modules [module] limit the modules to build (array: -m foo -m bar)
--lint [preferred|defaults|strict] (preferred is the default) lint mode: https://github.com/yui/yui-lint
--strict add "use strict" to module wrapper
-c/--config [file] specify a config file name
--ant parse the ant files and create a build.json but do not build
--list List the builds and rollups from the build.json file
--no-exec Do not run pre/postbuild or pre/post execs
--walk Walk the current directory and shift all builds. (cd yui3/src && shifter --walk)
-m/--modules also supported here for filtering
--no-progress to show the dots instead of the progress bar
--watch Watch the current module and rebuild on file change (if meta file, a loader build will launch)
--quiet to mute stdout from sub build
all other build options accepted here: (--strict, --lint, etc)
--jsstamp/--no-jsstamp Should it stamp the JS with the YUI.add wrapper, defaults to --stamp
--istanbul Use Istanbul code coverage instead of YUITest for coverage build
Experimental Options:
--semi Toggle on the strict semicolon checking in Uglify
--cache/--no-cache Cache the results of the build and bail if building for no reason, defaults to --no-cache
--cache-file <path> File to store build cache, defaults to $CWD/.shifter_meta
--fail Fail the build if lint fails
--compressor Use YUI Compressor instead of uglify
--no-lint Skip JSlint, you better know what you are doing!
More information about experimental options.
what does it do?
shifter
will parse your current *.properties
files and convert them into a build.json
file that
it can process. It only imports the relevant settings required to build the module.
It does not import module meta-data (see the meta-data for more information
Instead, shifter parses the meta-data from the modules meta/*.json
files and uses that instead.
So you don't have to declare your meta-data in more than one place now.
migrating to shifter
shifter
is designed to work side by side with our current builder (for now) so you don't have to
switch over to using it fully if it doesn't work properly for you. Just don't delete your *.properties
files until you are sure that Shifter builds your module properly. If it doesn't, file a ticket and
we'll get it fixed up ASAP.
shifter
will read a build.json
file if it exists, if one doesn't and it finds a *.properties
file
it will generate the build.json
from them. So if you have issues with the build, just delete the build.json
file and have Shifter regenerate it after your issue is fixed.
watching and building
shifter
can watch your module for changes and build for you. It will only watch files in the
./js
, ./css
, ./assets
and ./meta
directories. If a file is changed, it will rebuild the current
module. If a meta file is changes, Loader
will also be built (requires latest YUI source code).
skin handling
shifter
will attempt to process skins the way the old builder used to do them, but with the same
side-effect/bug of creating skins for all submodules even if they don't have a skin.
shifter
now supports a valid way to handle this, if you "namespace" your assets under a "module"
directory below assets
, shifter will do the right thing.
Here is an example directory structure, it's easier to read than to explain.
Code Coverage
When shifter
builds a module, it auto generates a -coverage
file generated with YUITest Code Coverage
If you pass the --istanbul
option, shifter
will use the new Istanbul Code Coverage tool.
meta-data
One of the goals of shifter
was to remove the need for duplicating Loader
meta-data. This includes:
component.requires=classnamemanager, pjax-base component.use=foo,bar,baz component.skinnable=true
These properties were also being redefined in the modules meta/<module>.json
file to be included when Loader
was built.
When shifter
parses the build.json
file, it will attempt to gather Loader
meta-data from the corresponding meta/*.json
files and munge them together into the data it needs to properly build the module.
You can add your own to the build file if you do not have a meta
file to parse:
{ "name": "foobar", "builds": { "module": { "jsfiles": [ "./js/foo.js" ], "config": { "use": [ "yui-base", "get", "features", "intl-base", "yui-log", "yui-later", "loader-base", "loader-rollup", "loader-yui3" ] } } } }
Note: If you provide a config
object and you have Loader
meta-data, shifter
will attempt to
merge them together, so your results may vary on this.
build.json
reference
For an object reference jump to the table below
Simple build.json
example
{ "name": "yql", "builds": { "yql": { "jsfiles": [ "yql.js" ] } } }
A more complex build.json
file (a truncated version of the yui/build.json file)
{ "name": "yui", "prebuilds": [ "get", "loader" ], "postbuilds": [ "simpleyui" ], "exec": [ "./scripts/build.js" ], "builds": { "yui-log": { "jsfiles": [ "yui-log.js" ] }, "yui-core": { "name": "yui-base", "replace": { "@YUI_CORE@": "['intl-base']" }, "prependfiles": [ "js/yui.js" ], "jsfiles": [ "yui-base.js", "yui-object.js", "yui-ua.js", "alias.js" ] } }, "rollups": { "yui-base": { "name": "yui", "replace": { "@YUI_CORE@": "['get', 'features', 'intl-base', 'yui-log', 'yui-later']" }, "config": { "use": [ "yui-log", "yui-later" ] }, "files": [ "yui-base", "yui-log", "yui-later" ], "build": { "prependfiles": [ "js/yui.js" ], "jsfiles": [ "yui-base.js", "yui-lang.js", "alias.js" ] } } } }
build.json
object reference
root properties
key | value |
---|---|
name |
String the name of this module |
shifter |
Object containing default shifter options: CLI options will override these.
"shifter": { "jsstamp": false, "coverage": false, "lint": "defaults" } |
prebuilds* |
Array of modules that you want to build before this build (CWD ../ module ) "prebuilds" [ "foo", "bar" ]` |
postbuilds* |
Array same as prebuilds only executes after the build is complete. |
exec* |
Array of scripts to execute before the build |
postexec* |
Array of scripts to execute after the build |
builds |
Object describes the module builds to perform |
rollups |
Object describes the module rollups to perform after the build |
*
denotes that these properties can also be added to an individual build
as well as globally.
global config file
shifter
will walk up the working directory and search for the first .shifter.json
file that it finds.
It will then apply any configuration settings found in that config to the current shifter
config. (described above).
Below is an example .shifter.json
:
{ "replace-yuiglobalvar": "FOO", "replace-yuivar": "F", "replace-version": "1.2.3.4", "lint": false, "coverage": false, "regex": "^.*?(?:logger|Y.log).*?(?:;|\\).*;|(?:\\r?\\n.*?)*?\\).*;).*;?.*?\\r?\\n|^.*?(?:\/\\*@DBG\\*\/).*\\r?\\n" }
You can force shifter
to ignore this file with the --no-global-config
option to the cli. CLI options will override the options in the config
builds
properties
Properties available on the builds
property.
key | value |
---|---|
jsfiles |
Array of files under the js directory to concat (in this order) |
cssfiles |
Array of files under the css directory to concat (in this order) |
skinnable |
Boolean should a skin be built |
regex |
String A regex to apply to the build to remove Y.log statements, the default is:/^.*?(?:logger|Y.log).*?(?:;|\).*;|(?:\r?\n.*?)*?\).*;).*;?.*?\r?\n/mg This string overrides the one defined in .shifter.json An empty string here disable this behavior for that specific build. |
prependfiles |
Array list of files to include before the concatted jsfiles|cssfiles |
appendfiles |
Array same as prependfiles only after the concatted files |
replace |
Object search the build for Object.key and replace with Object.value |
config |
Object see meta-data |
copy |
Array of Array 's containig from and to :"copy": [ [ "./foo", "./bar" ], [ "./foobar", "./barfoo" ] ] |
rollups
properties
Properties available on the rollups
property.
Note: The logic behind rollups changed in shifter
, in the previous builder
a rollup performed a full build on the files before rolling them up. This wasted valuable time
and needed to be changed.
With shifter
a default rollup is nothing more than stitching a few pre-built
modules together before stamping them with a module stamp.
key | value |
---|---|
replace |
Same as on builds |
config |
Same as on builds |
files |
Array of modules to rollup: "files": [ "foo", "bar" ] will look for build/foo/foo-debug.js and build/bar/bar-debug.js and roll them up |
build |
Object perform this build first, then proceed with the rollup (same as a property under builds ) |
experimental options
From time to time I will add experimental options to shifter to allow for developers to test new features prior to turning them on.
build file caching
You can turn on build time caching with the --cache
config option. This will write a cache file out with the MD5's of the build. If
the MD5 matches one in the meta file, the build will abort and skip the remaining tasks (compressor, coverage, etc
) to speed up development.
You can also use --cache-file [path]
to specify a cache file instead of using a per module one. Defaults to $CWD/.shifter_meta
.
failing build from lint issues
Pass --fail
to fail the build if any lint errors occur.
strict semicolon checking in Uglify
The default is to not require strict semi colons with UglifyJS, for example:
var foo = {}; foo.bar = function () { }
That last }
should be };
, in strict mode Uglify will throw without that semi colon.
skipping jslint
Some developers do not agree with JSLint, so this option is there for them to use whatever lint program they choose to use. As long as they use one!
using YUI Compressor
As of version 0.1.0
Shifter defaults to using UglifyJS as it's default compression utility.
If there is an issue with compressing your module with Uglify, you can revert to using YUI Compressor with the --compressor
flag.
Forcing lint to stderr
By default, lint warnings/errors are printed to stdout
. But in the case that you want to trap that in logs or in a CI system,
I've added a --lint-stderr
config option which forces all lint output to stderr
.
CLI Replacers
You can pass --replace-??=??
and shifter
will attempt to replace these strings during the build.
You MUST use the = to tell nopt that you want to assign the value to the dynamic option.
Examples:
--replace-version=1.2.3 will replace @VERSION@ with 1.2.3 --replace-foo=bar will replace @FOO@ with bar --replace-baz=bog will replace @BAZ@ with bog
Recursive Building
Adding --recursive
to the --walk
command will tell shifter
to walk the directories recursively looking for build.json
files.