├── .gitignore
├── .travis.yml
├── README.md
├── index.d.ts
├── index.js
├── integration.sh
├── integration
├── check-gen-html.js
├── index.html
├── main.js
├── package.json
├── style.css
└── webpack.config.js
├── package.json
├── spec
└── support
│ └── jasmine.json
├── src
├── critical.spec.ts
└── critical.ts
├── tsconfig.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | node_modules/
3 |
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | sudo: false
3 | node_js:
4 | - '5'
5 |
6 | cache:
7 | directories:
8 | - node_modules
9 |
10 | install:
11 | - npm install
12 |
13 | script:
14 | - npm test
15 | - ./integration.sh
16 |
17 | notifications:
18 | webhooks:
19 | on_success: always # options: [always|never|change] default: always
20 | on_failure: always # options: [always|never|change] default: always
21 | on_start: false # default: false
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Critical Webpack Plugin
2 |
3 | This is a webpack wrapper around [Addy Osmani's critical library](https://github.com/addyosmani/critical), which helps
4 | to inline minimum necessary CSS in HTML documents to prevent stylesheet loading from blocking the [Critical Rendering Path](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/).
5 |
6 | ## Install
7 |
8 | ```
9 | $ npm install webpack-plugin-critical
10 | ```
11 |
12 | ## Usage
13 |
14 | The following example shows how the Critical Webpack Plugin can be used to modify
15 | the project's `index.html` file to inline only the (minified) CSS needed for the index page,
16 | and asynchronously load the remaining CSS.
17 |
18 | **webpack.config.js**
19 |
20 | ```js
21 | const CriticalPlugin = require('webpack-plugin-critical').CriticalPlugin;
22 | ...
23 | plugins: [
24 | new CriticalPlugin({
25 | src: 'index.html',
26 | inline: true,
27 | minify: true,
28 | dest: 'index.html'
29 | })
30 | ]
31 | ...
32 | ```
33 |
34 | The only required option is `dest` and either `src` or `html`, since without dest, the output would
35 | be lost. When using Critical directly (instead of using this plugin), `dest` isn't required because the
36 | callback can accept the HTML or CSS output as a parameter.
37 |
38 | Other than `dest`, all options are the same as Critical, so please see the
39 | [Critical options](https://github.com/addyosmani/critical#options).
40 |
41 | To see a fully working example, check out the [integration spec](./integration).
42 |
43 | ## Why?
44 |
45 | When the browser sees this in a page:
46 |
47 | ```html
48 |
49 | ```
50 |
51 | The browser stops, loads the stylesheet and its dependencies, and cannot continue
52 | rendering the page until the stylesheet is loaded and parsed.
53 | So the user sees an empty screen while they wait for every stylesheet and script to
54 | load.
55 | The critical library solves this problem by figuring out what CSS is actually needed
56 | for a given page, inlining the CSS into a `
62 |
63 | ```
64 |
65 | By loading the stylesheet using `preload` instead of `stylesheet`, the browser
66 | can begin downloading the stylesheet in the background, which comes in handy
67 | in single page applications where additional views may be loaded that depend
68 | on rules from the full stylesheet.
69 |
70 | ## TypeScript Support
71 |
72 | This plugin is written in TypeScript and includes TypeScript typings,
73 | which should automatically work if using TypeScript 2.x+.
74 |
75 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './dist/critical';
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function __export(m) {
3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4 | }
5 | __export(require('./dist/critical'));
6 |
--------------------------------------------------------------------------------
/integration.sh:
--------------------------------------------------------------------------------
1 | rm -rf integration/dist
2 | npm pack .
3 |
4 | PACKAGE=`find . -name webpack-plugin-critical-*`
5 |
6 | cd integration
7 |
8 | npm install
9 | npm install ../$PACKAGE
10 | rm ../$PACKAGE
11 |
12 | ./node_modules/.bin/webpack
13 | node check-gen-html.js
14 |
15 | cd ../
16 |
--------------------------------------------------------------------------------
/integration/check-gen-html.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const parse5 = require('parse5');
3 |
4 | const doc = fs.readFileSync('./dist/index.html', 'utf-8');
5 | const parsed = parse5.parse(doc, {treeAdapter: parse5.treeAdapters.htmlparser2});
6 | const head = parsed.firstChild.firstChild;
7 | const [style] = head.children.filter(n => n.name === 'style');
8 | const [link] = head.children.filter(n => n.name === 'link');
9 | const jasmine = require('jasmine');
10 |
11 | if (style.firstChild.data !== `
12 | .styleme{color:red}
13 | `) {
14 | throw new Error('Style is not correct:', style.firstChild.data);
15 | } else {
16 | console.log('