Awesome
Montage Optimizer (aka mop)
for Montage ~0.14.6 and Mr ~0.15.0, ~0.14.2 and ~0.13.0.
Optimizes Montage applications for production by minifying, to reduce file size, and creating bundles, to reduce the number of requests.
Install Mop globally with NPM.
npm install -g mop
Mop can be run in any directory containing a Montage application.
$ ls
index.html node_modules/ package.json ui/
$ ls node_modules/
montage/
$ mop
# performs reading, processing and bundling steps
$ ls builds/
my-app my-app@f7e7db2/
Features
- writes whole packages into an incrementally updated builds directory, giving each package a consistent hash
- optionally generates AppCache manifest files for every package
- performs optimizing transformations on whole packages, whole files,
and parts of files
- JavaScript minification using UglifyJS (including script blocks)
- HTML minification using JSDOM
- CSS using CSSOM (including style blocks)
- JSON files
- Montage serialization minification (and precompilation is a
goal) (including
text/montage-serialization
script blocks) - rewrites inter-package URL’s in HTML and CSS to use relative URL’s among the build products, regardless of where the dependencies are installed in development
- converts all modules into scripts, suitable for script injection, particularly for cross-origin dependencies and Content Security Policies.
- optionally bundles and shards applications
- aggregates the bootstrapping files and the transitive
dependencies of each HTML file that has a
montage.js
bootstrapping script into a single script that gets loaded instead ofmontage.js
- can produce a sequence of preloading bundles, to start loading after the main application starts. Each phase of the preload sequence can be optionally split into parallel downloads or "shards".
- aggregates the bootstrapping files and the transitive
dependencies of each HTML file that has a
- optionally, lints whole applications
- using JSHint for JavaScript in individual files and script blocks
- checks for broken links in HTML
- checks for unnecessary script block attributes
- checks for JavaScript parse errors in files and script blocks
- checks for JSON parse errors in files and script block, (planning to also check Montage serialization format)
- checks for copyright notices in HTML, CSS, and JavaScript
- operates holistically on a package and all of its dependencies
Usage
Creates a builds
directory from one or more applications, packages,
and all their dependencies. The builds
directory will be created in
your current working directory.
Usage:
mop [-lfc] [-d @] [--target <build-dir>] <source-package>
e.g,
$ mop calculator
$ mop -t builds calculator
-t
or --target
changes the default target build directory.
The default is builds
relative to the current working directory.
-o 0
or --optimize 0
disables optimizating transforms.
-l
or --lint
provides per-file warnings if packaged files do
not pass JSLint or various other sanity checks like script MIME types
and known JSON schemas.
-d
or --delimiter
allows you to override the symbol used between
package names and package hashes in the builds directory, which is @
by default.
--no-css
allows you to disable CSS transforms. CSSOM cannot handle
some modern CSS.
Your project will be assembled in the builds directory.
Notes
The bootstrap bundle Mop creates is usually large, as it contains the
bootrapping code and the initial modules and all their dependencies. To
avoid the download of this file blocking the rendering of your page make
sure to include the async
attribute in the bootstrap script tag:
<!-- Mr -->
<script src="node_modules/mr/bootstrap.js" data-module="index" async></script>
<!-- Montage -->
<script src="node_modules/montage/montage.js" async></script>
API
var optimize = require("mop");
optimize(process.cwd()).then(function () {
console.log("Optimization done.");
});
optimize(location, [config])
Optimize the package at the given location.
- location
string
An absolute path to a directory containing an app to optimize. - [config]
Object
Configuration for optimization.- [buildLocation="builds"]
string
An absolute or relative path for a directory to generate the optimized files in. - [minify=true]
boolean
Whether to minify the files. - [lint=false]
boolean
Whether to lint the files and output warnings. - [noCss=true]
boolean
Whether to optimize CSS. Cannot handle some modern CSS, and so disabled by default. - [delimiter="@"]
string
Symbol to use between the package name and the package hash, e.g.my-app@f7e7db2
- [out=spinner]
Object
An object to use for logging.- [log]
Function
Variadic function that outputs a normal message. - [warn]
Function
Variadic function that outputs a warning. - [status]
Function
Variadic function that outputs a status message. These messages are temporary, high volume and should not be permanently displayed. If called with no arguments it should clear the displayed status.
- [log]
- [buildLocation="builds"]
Package JSON
The build system uses package.json
files to discover dependencies.
These dependencies must always be packages themselves.
For a comprehensive view of what can be in a package.json
, see the
UncommonJS specification.
For the purpose of the build system, the following properties are important:
-
dependencies
: In the presence of adependencies
property, the build system assumes that the package was designed for NPM and that its dependencies were locally installed by NPM. That means that they can be found by searching thenode_modules
directory of the package.dependencies
are internally transformed intomappings
, assuming that the package is innode_modules
. -
mappings
: A more flexible dependency management block. The local module identifier can be different than the registered package name. The dependency can havelocation
,name
,version
, andhash
properties. If the dependency is a string, it is coerced to an object with a location property.If a mapping has the same name as a dependency, the mapping overrides the dependency at run-time, but NPM will only use the
dependencies
block to install.{ "mappings": { "montage": "../montage/" } }
-
bundle
: For application packages, configures how the optimizer will bundle modules so that they can be downloaded by the browser with HTTP requests.-
An array turns on bundling as above, but also sets up a prioritized preloading sequence. Each element of the array corresponds to a preloading phase. Between each phase, the run-time has an opportunity to use the newly loaded modules, while subsequent phases download in the background.
Each element of the array can be a single module identifier or an array of module identifiers. Each loading phase will include all of these modules and their transitive dependencies, but will exclude any modules that would already be loaded in a prior phase or the initial bundle.
The run-time supresses all lazy loading until preloading has been finished to avoid issuing multiple requests for the same modules. However, as a consequence, applications should plan to finish preloading before being provoked by the user to load modules on demand.
For the purpose of bundling, Montage Optimizer has a broader view of what constitutes a dependency than the Montage run-time in development mode.
-
For a JavaScript module, as with the Montage run-time in development, all modules mentioned in
require("")
calls with a string argument. -
Additionally, for an HTML file, dependencies include:
- The referenced serialization of a
<link rel="text/montage-serialization">
tag. - The modules refered to in a
<script type="text/montage-serialization">
as defined by serialization dependencies.
- The referenced serialization of a
-
For a serialization, dependencies include every module mentioned in the serialization objects through the "prototype" property (or deprecated "module" property), unless the "lazy" property is true.
-
For the eponymous JavaScript module in a Reel, like
main.reel/main.js
, the corresponding HTML template file, if it exists, such asmain.reel/main.html
. -
A File can only be bundled if the file name is hyphenated lowercase. For example:
my-text-component.reel
will be bundled, butmyTextComponent.reel
will not.my-model-object.mjson
will be bundled, butmyModelObject.mjson
will not.
-
-
shard
: In conjunction with bundling and preloading, "shard" specifies a maximum number of TCP connections to dedicate to downloading module bundles in parallel at run-time. Without sharding, each phase of preloading is downloaded from a single bundle file with some number of modules. With sharding, that bundle is divided into smaller files and the optimizer uses a heuristic packing algorithm to evenly distribute the modules among these bundles. -
appcache
: For application packages, instructs the optimizer to generate an appcache manifest. The manifest will contain all of the resources in an all used packages except those explicitly excluded in each package. Theappcache
property can be eithertrue
or an object with additional configuration for manifests.fallback
is an object that causes the browser to redirect from a network URL to a cached URL when the browser is offline. These get incorporated in the generated HTML5 appcache manifest under theFALLBACK:
section.
-
exclude
: A list of glob patterns for files and directory trees in the package, relative to the package root, that must not be included in a production build and its appcache manifest. These exclusions may include*
for zero or more wild card characters in a file name,?
for a single wild card character in a file name, or**
for recursive directory traversal.{ "exclude": [ "**/tests", "benchmarks", "examples", "docs" ] }