1 | # AssetGraph-builder
|
2 |
|
3 | [![NPM version](https://badge.fury.io/js/assetgraph-builder.svg)](http://badge.fury.io/js/assetgraph-builder)
|
4 | [![Build Status](https://travis-ci.org/assetgraph/assetgraph-builder.svg?branch=master)](https://travis-ci.org/assetgraph/assetgraph-builder)
|
5 | [![Coverage Status](https://coveralls.io/repos/assetgraph/assetgraph-builder/badge.svg)](https://coveralls.io/r/assetgraph/assetgraph-builder)
|
6 | [![Dependency Status](https://david-dm.org/assetgraph/assetgraph-builder.svg)](https://david-dm.org/assetgraph/assetgraph-builder)
|
7 |
|
8 | AssetGraph-based build system (mostly) for single-page web
|
9 | applications.
|
10 |
|
11 | Looking for a Grunt integration? Try [grunt-reduce](https://github.com/Munter/grunt-reduce)
|
12 |
|
13 | ## Quick start
|
14 |
|
15 | # Conventional
|
16 |
|
17 | ```
|
18 | npm install -g assetgraph-builder
|
19 | buildProduction path/to/your/index.html -o path/to/output/directory
|
20 | ```
|
21 |
|
22 | # [Docker](https://www.docker.com/)
|
23 |
|
24 | ```
|
25 | docker run --rm -it -v "$(pwd)":/app/ -w /app/ assetgraph/assetgraph-builder path/to/your/index.html -o path/to/output/directory
|
26 | ```
|
27 |
|
28 | Congratulations, you just optimized your web page!
|
29 |
|
30 | ## Features
|
31 |
|
32 | - Requires no build manifest. All information about your project is
|
33 | gathered from the HTML/CSS/JavaScript itself. Just tell it where to
|
34 | find your HTML file(s), and it will find the referenced JavaScript,
|
35 | CSS, etc.
|
36 | - Reads your web application from one directory, manipulates and
|
37 | optimizes it, then writes the resulting build to a separate
|
38 | directory with everything included.
|
39 | - Supports a multitude of asset/relation types, even shortcut icons,
|
40 | `AlphaImageLoader` images, conditional comments, fonts linked via
|
41 | `@font-face { src: url(...) }`, .htc files linked via CSS
|
42 | `behavior` properties.
|
43 | - Bundles JavaScript and CSS.
|
44 | - Discovers and optimizes Web Workers and Service Workers.
|
45 | - Removes duplicate images, JavaScript, CSS, etc.
|
46 | - Supports automatic optimization and custom processing of images using
|
47 | pngquant, pngcrush, optipng, jpegtran, <a href="https://github.com/lovell/sharp">sharp</a>, and GraphicsMagick.
|
48 | - Minifies/packs JavaScript, CSS, and HTML (uses <a
|
49 | href="https://github.com/mishoo/UglifyJS">UglifyJS</a>, <a
|
50 | href="https://github.com/ben-eb/cssnano">cssnano</a>, <a
|
51 | href="https://github.com/tmpvar/jsdom">jsdom</a>,
|
52 | and <a href="https://github.com/kangax/html-minifier">html-minifier</a>).
|
53 | - Supports the <a
|
54 | href="http://requirejs.org/docs/optimization.html">the require.js
|
55 | optimizer</a> and <a href="https://github.com/systemjs/builder">systemjs-builder</a>.
|
56 | - Sprites background images (see <a
|
57 | href="https://github.com/One-com/assetgraph-sprite">assetgraph-sprite</a>).
|
58 | - Inlines CSS `background-image`s less than 8192 bytes and provides an
|
59 | alternative stylesheet for older IE versions via conditional comments.
|
60 | - Inlines CSS and JavaScript with total size less than 4096 bytes to reduce HTTP requests.
|
61 | - Adds a cache manifest to each HTML page if `--manifest` is
|
62 | specified.
|
63 | - Renames JavaScript, CSS, images etc. to a 10-char MD5 prefix + the
|
64 | original extension so they can be served with a far-future expiry time.
|
65 | - Helps getting your static assets on a CDN by rewriting the
|
66 | references to them (controlled by the `--cdnroot` switch).
|
67 | - Updates an existing Content-Security-Policy meta tag to reflect the
|
68 | changes that happened during the build procedure, including hashing
|
69 | of inline scripts and stylesheets.
|
70 | - Very customizable, the entire build script is only around 100 lines
|
71 | of code due to the reliance on high level <a
|
72 | href="https://github.com/One-com/assetgraph">AssetGraph</a>
|
73 | transforms.
|
74 | - Automatically adds `rel="noopener"` to cross domain anchors opening in new windows ([The performance benefits of rel=noopener](https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/))
|
75 |
|
76 | ## Installation
|
77 |
|
78 | Optional first step: To take full advantage of the image processing
|
79 | and optimization features, you need several libraries and command line
|
80 | utilities installed. On Ubuntu you can grab them all by running:
|
81 |
|
82 | ```
|
83 | sudo apt-get install -y graphicsmagick inkscape
|
84 | ```
|
85 |
|
86 | Or on OS X, with [homebrew](http://brew.sh/):
|
87 |
|
88 | ```sh
|
89 | # Image manipulation
|
90 | brew install graphicsmagick
|
91 | brew install vips --with-webp --with-graphicsmagick
|
92 |
|
93 | # SVG rengering with Inkscape
|
94 | brew cask install xquartz
|
95 | brew cask install inkscape
|
96 |
|
97 | # Export PKG_CONFIG_PATH to make Inkscape work. Put this in your .profile or .bashrc
|
98 | export PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig
|
99 | ```
|
100 |
|
101 | Then make sure you have node.js and <a href="http://npmjs.org/">npm</a> installed,
|
102 | then run:
|
103 |
|
104 | ```
|
105 | $ npm install -g assetgraph-builder
|
106 | ```
|
107 |
|
108 | Now you'll have the `buildProduction` script in your PATH.
|
109 |
|
110 | ## Usage
|
111 |
|
112 | ```
|
113 | $ buildProduction -o outputPath [--root webrootPath] [startingAssets]
|
114 | ```
|
115 |
|
116 | Assetgraph needs a web root to resolve URLs correctly. If you pass in the `--root` option assetgraph will use it, otherwise it will take a best guess based on your `startingAssets`.
|
117 |
|
118 | The `-o` option tells assetgraph-builder where to write the built files to. If the directory does not exist it will be created for you.
|
119 |
|
120 | Your `startingAssets` can be one or more file paths or minimatch patterns, which will be used as the starting point of assetgraphs automatic discovery process. The default is `index.html`, but you might also want to add any file here that is not linked to by your website, but still has to be a part of the build, for example `robots.txt`, `.htaccess` or `404.html`. If one or more files are missing from your build, check that you are actually linking to them. If you are not, and it is by design, then you should add these files as input paths in `startingAssets`.
|
121 |
|
122 | There are many more options to assetgraph-builder. We suggest you consult the help with `buildProduction -h`.
|
123 |
|
124 | ## Example usage
|
125 |
|
126 | Build a single page application:
|
127 |
|
128 | ```
|
129 | buildProduction -o path/to/production --root path/to/dev path/to/dev/index.html
|
130 | ```
|
131 |
|
132 | This will load path/to/dev/index.html, follow all local relations to
|
133 | JavaScript, CSS, etc., perform the above mentioned optimizations, then
|
134 | output the result to the directory `path/to/production`.
|
135 |
|
136 | Create a CDN-enabled build:
|
137 |
|
138 | ```
|
139 | buildProduction -o path/to/production --root path/to/dev path/to/dev/index.html \
|
140 | --cdnroot http://xxxxxx.cloudfront.net/static/cdn
|
141 | ```
|
142 |
|
143 | This will produce a build that assumes that the contents of `path/to/production/static/cdn`
|
144 | are available at `http://xxxxxx.cloudfront.net/static/cdn`. We recommend putting the entire
|
145 | contents of `path/to/production` online and pointing your CloudFront (or other CDN provider)
|
146 | distribution at the root of your origin server. As long as you serve `/static` and everything
|
147 | below it with a far-future expires, you won't need to touch your CDN config or manually
|
148 | upload anything to your CDN provider.
|
149 |
|
150 | ## Specifying which browsers to support
|
151 |
|
152 | It's highly recommended that you tell `buildProduction` which browsers you need
|
153 | to support via the `--browsers` switch. It draws its syntax from the
|
154 | [browserslist](https://github.com/ai/browserslist) module and governs a wide
|
155 | range of tweaks and hacks, for example:
|
156 |
|
157 | - Whether the `screw IE8` option is passed to [UglifyJS](https://github.com/mishoo/UglifyJS2#usage).
|
158 | - The set of browsers autoprefixer is instructed to support, if autoprefixer is available.
|
159 | - Whether to add fallback stylesheets referenced via conditional comments when images
|
160 | are inlined in CSS (due to IE7 not supporting `data:` urls and IE8's 32 KB `data:` url limit).
|
161 |
|
162 | The default is to support all browsers, which will cause a heavier build,
|
163 | especially when IE8 and below are included and inlining of CSS images is active
|
164 | (which it is by default). If you're lucky enough that you don't need to support
|
165 | those browsers, you can add `--browsers ">0%, not ie <= 8"` and avoid those hacks.
|
166 |
|
167 | ## Replacing require.js with almond.js on build
|
168 |
|
169 | Simply add a `data-almond`-attribute to the script tag that has `require.js` as its source.
|
170 | The value should be the path to `almond.js` like so:
|
171 |
|
172 | ```html
|
173 | <script
|
174 | data-main="app/main"
|
175 | data-almond="path/to/almond.js"
|
176 | src="path/to/require.js"
|
177 | ></script>
|
178 | ```
|
179 |
|
180 | When you do this you should not use require as an external script loader, since almond does not support this.
|
181 |
|
182 | ## Working with a Content Security Policy
|
183 |
|
184 | If you add the `--contentsecuritypolicy` switch and one or more of your HTML
|
185 | files contain a CSP in a meta tag such as:
|
186 |
|
187 | ```html
|
188 | <meta
|
189 | http-equiv="Content-Security-Policy"
|
190 | content="default-src 'self'; script-src foo.com"
|
191 | />
|
192 | ```
|
193 |
|
194 | it will be read and updated to reflect the changes that were made during the build.
|
195 | This includes whitelisting your CDN, adding `image-src data:` if images are inlined,
|
196 | and generating hashes for inline scripts and stylesheets if your policy does not
|
197 | allow `'unsafe-inline'`.
|
198 |
|
199 | You can extract the resulting CSPs from the build and add it to your web server's
|
200 | config, or use something like
|
201 | [express-extractheaders](https://github.com/papandreou/express-extractheaders) to
|
202 | also send the CSP as a response header.
|
203 |
|
204 | We encourage a workflow like this so that the CSPs of your project are also
|
205 | in effect in your development setup, as that will help catch bugs early.
|
206 |
|
207 | Tip: If you want to use inline scripts and stylesheets in your development
|
208 | setup, yet don't want to allow `'unsafe-inline'` in your policy, you can
|
209 | use a nonce in development:
|
210 |
|
211 | ```html
|
212 | <!DOCTYPE html>
|
213 | <html>
|
214 | <head>
|
215 | <meta
|
216 | http-equiv="Content-Security-Policy"
|
217 | content="script-src 'nonce-yeah', style-src 'nonce-yeah'"
|
218 | />
|
219 | <style rel="stylesheet" nonce="yeah">
|
220 | body {
|
221 | color: red;
|
222 | }
|
223 | </style>
|
224 | </head>
|
225 | <body>
|
226 | <script nonce="yeah">
|
227 | alert('Hello');
|
228 | </script>
|
229 | </body>
|
230 | </html>
|
231 | ```
|
232 |
|
233 | `buildProduction --contentsecuritypolicy` will upgrade the nonce to a hash
|
234 | token if the scripts and stylesheets are still inline when the bundling/externalization
|
235 | steps have been carried out.
|
236 |
|
237 | ## Sub resource integrity
|
238 |
|
239 | The `--subresourceintegrity` switch will make `buildProduction` add an `integrity`
|
240 | attribute to every `<script src=...>` and `<link rel="stylesheet" href=...>`
|
241 | that points at an asset that is part of the build. Note that this excludes
|
242 | references to assets that are already located on a CDN, or indeed any http:// url.
|
243 | If you want to lock down such dependencies, please use the bundled
|
244 | `addIntegrityToForeignRelations` tool or compute the hash yourself and
|
245 | add it to your development HTML manually, for instance:
|
246 |
|
247 | ```html
|
248 | <script src="https://code.jquery.com/jquery-2.2.3.min.js"
|
249 | integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="</script>
|
250 | ```
|
251 |
|
252 | The reason why this isn't automated is that `buildProduction` cannot know
|
253 | if a given external resource might change in the future, thus breaking your
|
254 | production build.
|
255 |
|
256 | ## Excluding assets from your build
|
257 |
|
258 | If you want `buildProduction` to avoid including specific assets, paths or entire parts of
|
259 | your page, you can use the `--exclude` option.
|
260 |
|
261 | This could come in handy if you have multiple different sections on your site, where
|
262 | assetgraph-builder only handles a subset of them. If the assetgraph-builder covered section
|
263 | of site links to sections that it shouldn't handle, this is where you use `--exclude`
|
264 |
|
265 | `--exclude` can be used multiple times in the same command line to specify more than one pattern.
|
266 |
|
267 | Exclude patterns are always prefixed with `process.cwd()`, making the path addressable in the same
|
268 | manner as the entry point arguments.
|
269 |
|
270 | You may use `*` for wildcards.
|
271 |
|
272 | ## Image optimization and processing
|
273 |
|
274 | The `buildProduction` switch `--optimizeimages` turns on automatic lossless
|
275 | optimization of all images of the relevant type in the graph.
|
276 |
|
277 | Additionally, you can specify individual processing instructions for
|
278 | each image using custom GET parameters. For example you might want to
|
279 | reduce the palette of an image to a specific number of colors or apply
|
280 | a specific compression level:
|
281 |
|
282 | ```html
|
283 | <img src="myImage.png?pngquant=37" />
|
284 | <img src="myOtherImage.png?optipng=-o7&pngcrush=-rem+tEXT" />
|
285 | ```
|
286 |
|
287 | The image processing is supported everywhere you can refer to an
|
288 | image, including `background-image` properties in CSS, shortcut icon
|
289 | links etc.
|
290 |
|
291 | Additionally, all GraphicsMagick operations (as exposed by the <a
|
292 | href="https://github.com/aheckmann/gm">gm module</a>) are supported:
|
293 |
|
294 | ```css
|
295 | body {
|
296 | background-image: url(foo.png?resize=500 + 300&flip&magnify&pngcrush);
|
297 | }
|
298 | ```
|
299 |
|
300 | These are especially useful for responsive images:
|
301 |
|
302 | ```html
|
303 | <img
|
304 | srcset="
|
305 | bar.jpg 1024w,
|
306 | bar.jpg?resize=600 600w,
|
307 | bar.jpg?resize=500&gravity=Center&crop=300+300 300w
|
308 | "
|
309 | sizes="(min-width: 768px) 50vw, 100vw"
|
310 | />
|
311 | ```
|
312 |
|
313 | They work in JavaScript too:
|
314 |
|
315 | ```js
|
316 | var img = document.querySelector('.responsive-image');
|
317 | img.setAttribute(
|
318 | 'srcset',
|
319 | 'baz.gif'.toString('url') +
|
320 | ' 500w, ' +
|
321 | 'baz.gif?resize=300'.toString('url') +
|
322 | ' 300w'
|
323 | );
|
324 | picturefill({ elements: [img] }); // reload if you're using Picturefill
|
325 | ```
|
326 |
|
327 | This allows you to only check your original images into version
|
328 | control and have your build system create the scaled/processed/derived
|
329 | ones dynamically.
|
330 |
|
331 | The processing instructions are executed using the same engine that
|
332 | powers <a
|
333 | href="https://github.com/papandreou/express-processimage">express-processimage</a>
|
334 | and <a href="https://github.com/One-com/LiveStyle">livestyle</a> with the
|
335 | `--processimage` switch. You can use one of those to have the image
|
336 | processing instructions applied on your development setup.
|
337 |
|
338 | ## License
|
339 |
|
340 | AssetGraph-builder is licensed under a standard 3-clause BSD license
|
341 | -- see the `LICENSE`-file for details.
|