UNPKG

13.6 kBMarkdownView Raw
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
8AssetGraph-based build system (mostly) for single-page web
9applications.
10
11Looking for a Grunt integration? Try [grunt-reduce](https://github.com/Munter/grunt-reduce)
12
13## Quick start
14
15# Conventional
16
17```
18npm install -g assetgraph-builder
19buildProduction path/to/your/index.html -o path/to/output/directory
20```
21
22# [Docker](https://www.docker.com/)
23
24```
25docker run --rm -it -v "$(pwd)":/app/ -w /app/ assetgraph/assetgraph-builder path/to/your/index.html -o path/to/output/directory
26```
27
28Congratulations, 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
78Optional first step: To take full advantage of the image processing
79and optimization features, you need several libraries and command line
80utilities installed. On Ubuntu you can grab them all by running:
81
82```
83sudo apt-get install -y graphicsmagick inkscape
84```
85
86Or on OS X, with [homebrew](http://brew.sh/):
87
88```sh
89# Image manipulation
90brew install graphicsmagick
91brew install vips --with-webp --with-graphicsmagick
92
93# SVG rengering with Inkscape
94brew cask install xquartz
95brew cask install inkscape
96
97# Export PKG_CONFIG_PATH to make Inkscape work. Put this in your .profile or .bashrc
98export PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig
99```
100
101Then make sure you have node.js and <a href="http://npmjs.org/">npm</a> installed,
102then run:
103
104```
105$ npm install -g assetgraph-builder
106```
107
108Now you'll have the `buildProduction` script in your PATH.
109
110## Usage
111
112```
113$ buildProduction -o outputPath [--root webrootPath] [startingAssets]
114```
115
116Assetgraph 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
118The `-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
120Your `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
122There are many more options to assetgraph-builder. We suggest you consult the help with `buildProduction -h`.
123
124## Example usage
125
126Build a single page application:
127
128```
129buildProduction -o path/to/production --root path/to/dev path/to/dev/index.html
130```
131
132This will load path/to/dev/index.html, follow all local relations to
133JavaScript, CSS, etc., perform the above mentioned optimizations, then
134output the result to the directory `path/to/production`.
135
136Create a CDN-enabled build:
137
138```
139buildProduction -o path/to/production --root path/to/dev path/to/dev/index.html \
140 --cdnroot http://xxxxxx.cloudfront.net/static/cdn
141```
142
143This will produce a build that assumes that the contents of `path/to/production/static/cdn`
144are available at `http://xxxxxx.cloudfront.net/static/cdn`. We recommend putting the entire
145contents of `path/to/production` online and pointing your CloudFront (or other CDN provider)
146distribution at the root of your origin server. As long as you serve `/static` and everything
147below it with a far-future expires, you won't need to touch your CDN config or manually
148upload anything to your CDN provider.
149
150## Specifying which browsers to support
151
152It's highly recommended that you tell `buildProduction` which browsers you need
153to support via the `--browsers` switch. It draws its syntax from the
154[browserslist](https://github.com/ai/browserslist) module and governs a wide
155range 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
162The default is to support all browsers, which will cause a heavier build,
163especially 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
165those browsers, you can add `--browsers ">0%, not ie <= 8"` and avoid those hacks.
166
167## Replacing require.js with almond.js on build
168
169Simply add a `data-almond`-attribute to the script tag that has `require.js` as its source.
170The 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
180When 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
184If you add the `--contentsecuritypolicy` switch and one or more of your HTML
185files 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
194it will be read and updated to reflect the changes that were made during the build.
195This includes whitelisting your CDN, adding `image-src data:` if images are inlined,
196and generating hashes for inline scripts and stylesheets if your policy does not
197allow `'unsafe-inline'`.
198
199You can extract the resulting CSPs from the build and add it to your web server's
200config, or use something like
201[express-extractheaders](https://github.com/papandreou/express-extractheaders) to
202also send the CSP as a response header.
203
204We encourage a workflow like this so that the CSPs of your project are also
205in effect in your development setup, as that will help catch bugs early.
206
207Tip: If you want to use inline scripts and stylesheets in your development
208setup, yet don't want to allow `'unsafe-inline'` in your policy, you can
209use 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
234token if the scripts and stylesheets are still inline when the bundling/externalization
235steps have been carried out.
236
237## Sub resource integrity
238
239The `--subresourceintegrity` switch will make `buildProduction` add an `integrity`
240attribute to every `<script src=...>` and `<link rel="stylesheet" href=...>`
241that points at an asset that is part of the build. Note that this excludes
242references to assets that are already located on a CDN, or indeed any http:// url.
243If you want to lock down such dependencies, please use the bundled
244`addIntegrityToForeignRelations` tool or compute the hash yourself and
245add 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
252The reason why this isn't automated is that `buildProduction` cannot know
253if a given external resource might change in the future, thus breaking your
254production build.
255
256## Excluding assets from your build
257
258If you want `buildProduction` to avoid including specific assets, paths or entire parts of
259your page, you can use the `--exclude` option.
260
261This could come in handy if you have multiple different sections on your site, where
262assetgraph-builder only handles a subset of them. If the assetgraph-builder covered section
263of 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
267Exclude patterns are always prefixed with `process.cwd()`, making the path addressable in the same
268manner as the entry point arguments.
269
270You may use `*` for wildcards.
271
272## Image optimization and processing
273
274The `buildProduction` switch `--optimizeimages` turns on automatic lossless
275optimization of all images of the relevant type in the graph.
276
277Additionally, you can specify individual processing instructions for
278each image using custom GET parameters. For example you might want to
279reduce the palette of an image to a specific number of colors or apply
280a specific compression level:
281
282```html
283<img src="myImage.png?pngquant=37" />
284<img src="myOtherImage.png?optipng=-o7&amp;pngcrush=-rem+tEXT" />
285```
286
287The image processing is supported everywhere you can refer to an
288image, including `background-image` properties in CSS, shortcut icon
289links etc.
290
291Additionally, all GraphicsMagick operations (as exposed by the <a
292href="https://github.com/aheckmann/gm">gm module</a>) are supported:
293
294```css
295body {
296 background-image: url(foo.png?resize=500 + 300&flip&magnify&pngcrush);
297}
298```
299
300These 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&amp;gravity=Center&amp;crop=300+300 300w
308 "
309 sizes="(min-width: 768px) 50vw, 100vw"
310/>
311```
312
313They work in JavaScript too:
314
315```js
316var img = document.querySelector('.responsive-image');
317img.setAttribute(
318 'srcset',
319 'baz.gif'.toString('url') +
320 ' 500w, ' +
321 'baz.gif?resize=300'.toString('url') +
322 ' 300w'
323);
324picturefill({ elements: [img] }); // reload if you're using Picturefill
325```
326
327This allows you to only check your original images into version
328control and have your build system create the scaled/processed/derived
329ones dynamically.
330
331The processing instructions are executed using the same engine that
332powers <a
333href="https://github.com/papandreou/express-processimage">express-processimage</a>
334and <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
336processing instructions applied on your development setup.
337
338## License
339
340AssetGraph-builder is licensed under a standard 3-clause BSD license
341-- see the `LICENSE`-file for details.