Skip to content
This repository was archived by the owner on Jan 21, 2021. It is now read-only.

Commit 0f80892

Browse files
authored
Merge pull request #36 from laysent/master
Provide a way to include all assets (issue #35)
2 parents e29cdd4 + 40a1220 commit 0f80892

File tree

7 files changed

+197
-19
lines changed

7 files changed

+197
-19
lines changed

README.md

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,14 @@ will be injected into the document `<head>`:
132132
<link rel="preload" as="script" href="chunk.d15e7fdfc91b34bb78c4.js">
133133
```
134134

135-
You can also configure the plugin to preload all chunks (vendor, async, normal chunks) using `include: 'all'`, or only preload initial chunks with `include: 'initial'`:
135+
You can also configure the plugin to preload all chunks (vendor, async, normal chunks) using `include: 'allChunks'`, or only preload initial chunks with `include: 'initial'`:
136136

137137
```js
138138
plugins: [
139139
new HtmlWebpackPlugin(),
140140
new PreloadWebpackPlugin({
141141
rel: 'preload',
142-
include: 'all' // or 'initial'
142+
include: 'allChunks' // or 'initial'
143143
})
144144
]
145145
```
@@ -161,6 +161,28 @@ will inject just this:
161161
<link rel="preload" as="script" href="home.31132ae6680e598f8879.js">
162162
```
163163

164+
It is very common in Webpack to use loaders such as `file-loader` to generate assets for specific
165+
types, such as fonts or images. If you wish to preload these files as well, you can use `include`
166+
with value `allAssets`:
167+
168+
```js
169+
plugins: [
170+
new HtmlWebpackPlugin(),
171+
new PreloadWebpackPlugin({
172+
rel: 'preload',
173+
include: 'allAssets',
174+
})
175+
]
176+
```
177+
178+
One thing worth noticing: `file-loader` provides an option to specify `publicPath` just for assets.
179+
However, that information seems to be lost when this plugin is doing its job. Thus, this plugin
180+
will use `publicPath` defined in `output` config. It could be an issue, if `publicPath` in `file-loader`
181+
and `publicPath` in `webpack` config have different values.
182+
183+
Usually you don't want to preload all of them but only keep the necessary resources, you can use
184+
`fileBlacklist` or `fileWhitelist` shown below to filter.
185+
164186
Filtering chunks
165187
---------------------
166188

@@ -180,9 +202,31 @@ new PreloadWebpackPlugin({
180202
})
181203
```
182204

183-
## Filtering Html
205+
If you use `include="allAssets"`, you might find excluding all unnecessary files one by one a
206+
bit annoying. In this case, you can use `fileWhitelist` to only include the files you want:
207+
208+
```js
209+
new PreloadWebpackPlugin({
210+
fileWhitelist: [/\.files/, /\.to/, /\.include/],
211+
})
212+
```
213+
214+
notice that if `fileWhitelist` is not provided, it will not filter any file out.
215+
216+
Also, you could use `fileWhitelist` and `fileBlacklist` together:
217+
218+
```js
219+
new PreloadWebpackPlugin({
220+
fileWhitelist: [/\.files/, /\.to/, /\.include/],
221+
fileBlacklist: [/\.files/, /\.to/, /\.exclude/],
222+
})
223+
```
224+
225+
In example above, only files with name matches `/\.include/` will be included.
184226

185-
In some case, you may don't want to preload resource on some file. But using `fileBlacklist` is werid, because you may want to inlcude this chunk on another file. So you can use `excludeHtmlNames` to tell preload plugin to ignore this file.
227+
## Filtering HTML
228+
229+
In some case, you may don't want to preload resource on some file. But using `fileBlacklist` is weird, because you may want to inlcude this chunk on another file. So you can use `excludeHtmlNames` to tell preload plugin to ignore this file.
186230

187231
If you have multiple html like index.html and example.html, you can exclude index.html like this.
188232

@@ -201,8 +245,7 @@ plugins: [
201245
// I want this to affect only index.html
202246
new PreloadWebpackPlugin({
203247
excludeHtmlNames: ['index.html'],
204-
})
205-
]
248+
})
206249
```
207250

208251
Resource Hints

index.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,16 @@ class PreloadPlugin {
8484
} catch (e) {
8585
extractedChunks = compilation.chunks;
8686
}
87-
} else if (options.include === 'all') {
88-
// Async chunks, vendor chunks, normal chunks.
87+
} else if (options.include === 'allChunks' || options.include === 'all') {
88+
if (options.include === 'all') {
89+
/* eslint-disable no-console */
90+
console.warn('[WARNING]: { include: "all" } is deprecated, please use "allChunks" instead.');
91+
/* eslint-enable no-console */
92+
}
93+
// Async chunks, vendor chunks, normal chunks.
8994
extractedChunks = compilation.chunks;
95+
} else if (options.include === 'allAssets') {
96+
extractedChunks = [{files: Object.keys(compilation.assets)}];
9097
} else if (Array.isArray(options.include)) {
9198
// Keep only user specified chunks
9299
extractedChunks = compilation
@@ -103,11 +110,21 @@ class PreloadPlugin {
103110

104111
const publicPath = compilation.outputOptions.publicPath || '';
105112

106-
// Only handle the chunk import by the htmlWebpackPlugin
107-
extractedChunks = extractedChunks.filter(chunk => doesChunkBelongToHTML(
108-
chunk, Object.values(htmlPluginData.assets.chunks), {}));
113+
// only handle the chunks associated to this htmlWebpackPlugin instance, in case of multiple html plugin outputs
114+
// allow `allAssets` mode to skip, as assets are just files to be filtered by black/whitelist, not real chunks
115+
if (options.include !== 'allAssets') {
116+
extractedChunks = extractedChunks.filter(chunk => doesChunkBelongToHTML(
117+
chunk, Object.values(htmlPluginData.assets.chunks), {}));
118+
}
109119

110-
flatten(extractedChunks.map(chunk => chunk.files)).filter(entry => {
120+
flatten(extractedChunks.map(chunk => chunk.files))
121+
.filter(entry => {
122+
return (
123+
!this.options.fileWhitelist ||
124+
this.options.fileWhitelist.some(regex => regex.test(entry) === true)
125+
);
126+
})
127+
.filter(entry => {
111128
return this.options.fileBlacklist.every(regex => regex.test(entry) === false);
112129
}).forEach(entry => {
113130
entry = `${publicPath}${entry}`;

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@
3131
"homepage": "https://github.com/googlechromelabs/preload-webpack-plugin",
3232
"devDependencies": {
3333
"babel-eslint": "^7.1.1",
34+
"css-loader": "^0.28.7",
3435
"eslint": "^3.14.1",
3536
"eslint-config-google": "^0.7.1",
37+
"extract-text-webpack-plugin": "^3.0.0",
38+
"file-loader": "^0.11.2",
3639
"html-webpack-plugin": "^2.26.0",
3740
"jasmine": "^2.5.3",
38-
"webpack": "^3.2.0"
41+
"webpack": "^3.4.0"
3942
},
4043
"peerDependencies": {
4144
"webpack": "^3.2.0"

test/fixtures/font.woff2

Whitespace-only changes.

test/fixtures/load-css.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @license
3+
* Copyright 2017 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
console.log('lol');
18+
console.log(require('./style.css'));
19+
require.ensure(["./home.js"], function() {
20+
// var a = require("module-a");
21+
// console.log(a);
22+
}, 'home');

test/fixtures/style.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@font-face {
2+
font-family: test;
3+
src: url(./font.woff2);
4+
}

test/spec.js

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const webpack = require('webpack');
2323
const HtmlWebpackPlugin = require('html-webpack-plugin');
2424
const PreloadPlugin = require('../');
2525
const OUTPUT_DIR = path.join(__dirname, 'dist');
26+
const ExtractTextPlugin = require('extract-text-webpack-plugin');
2627

2728
describe('PreloadPlugin preloads or prefetches async chunks', function() {
2829
it('adds preload tags to async chunks', function(done) {
@@ -120,7 +121,7 @@ describe('PreloadPlugin preloads normal chunks', function() {
120121
new PreloadPlugin({
121122
rel: 'preload',
122123
as: 'script',
123-
include: 'all'
124+
include: 'allChunks'
124125
})
125126
]
126127
}, function(err, result) {
@@ -149,7 +150,7 @@ describe('PreloadPlugin preloads normal chunks', function() {
149150
new HtmlWebpackPlugin(),
150151
new PreloadPlugin({
151152
rel: 'preload',
152-
include: 'all'
153+
include: 'allChunks'
153154
})
154155
]
155156
}, function(err, result) {
@@ -177,7 +178,7 @@ describe('PreloadPlugin preloads normal chunks', function() {
177178
new PreloadPlugin({
178179
rel: 'preload',
179180
as: 'script',
180-
include: 'all'
181+
include: 'allChunks'
181182
})
182183
]
183184
}, function(err, result) {
@@ -206,7 +207,7 @@ describe('PreloadPlugin preloads normal chunks', function() {
206207
new HtmlWebpackPlugin(),
207208
new PreloadPlugin({
208209
rel: 'preload',
209-
include: 'all'
210+
include: 'allChunks'
210211
})
211212
]
212213
}, function(err, result) {
@@ -237,7 +238,7 @@ describe('PreloadPlugin preloads normal chunks', function() {
237238
if (entry.indexOf('/chunk') === 0) return 'style';
238239
return 'script';
239240
},
240-
include: 'all',
241+
include: 'allChunks',
241242
}),
242243
],
243244
}, function(err, result) {
@@ -263,7 +264,7 @@ describe('PreloadPlugin prefetches normal chunks', function() {
263264
new HtmlWebpackPlugin(),
264265
new PreloadPlugin({
265266
rel: 'prefetch',
266-
include: 'all'
267+
include: 'allChunks'
267268
})
268269
]
269270
}, function(err, result) {
@@ -337,6 +338,94 @@ describe('PreloadPlugin filters chunks', function() {
337338
});
338339
compiler.outputFileSystem = new MemoryFileSystem();
339340
});
341+
it('use fileWhitelist to include only specific files', (done) => {
342+
const compiler = webpack({
343+
entry: path.join(__dirname, 'fixtures', 'file.js'),
344+
devtool: 'cheap-source-map',
345+
output: {
346+
path: OUTPUT_DIR,
347+
filename: 'bundle.js',
348+
chunkFilename: '[name].js',
349+
publicPath: '/',
350+
},
351+
plugins: [
352+
new HtmlWebpackPlugin(),
353+
new PreloadPlugin({
354+
rel: 'preload',
355+
as: 'script',
356+
fileWhitelist: [/home/],
357+
})
358+
]
359+
}, function(err, result) {
360+
expect(err).toBeFalsy();
361+
expect(JSON.stringify(result.compilation.errors)).toBe('[]');
362+
const html = result.compilation.assets['index.html'].source();
363+
expect(html).toContain('<link rel="preload" as="script" href="/home.js');
364+
// exclude by default fileBlacklist
365+
expect(html).not.toContain('<link rel="preload" as="script" href="/home.js.map');
366+
// not included in fileWhitelist
367+
expect(html).not.toContain('<link rel="preload" as="script" href="/bundle.js"');
368+
done();
369+
});
370+
compiler.outputFileSystem = new MemoryFileSystem();
371+
});
372+
});
373+
374+
describe('PreloadPlugin preloads all assets', function() {
375+
it('adds preload tags', function(done) {
376+
const compiler = webpack({
377+
entry: path.join(__dirname, 'fixtures', 'load-css.js'),
378+
output: {
379+
path: OUTPUT_DIR,
380+
filename: 'bundle.js',
381+
chunkFilename: 'chunk.[chunkhash].js',
382+
publicPath: '/',
383+
},
384+
module: {
385+
rules: [
386+
{
387+
test: /\.css$/,
388+
loader: ExtractTextPlugin.extract({
389+
fallback: 'css-loader',
390+
use: [
391+
{
392+
loader: 'css-loader',
393+
},
394+
],
395+
}),
396+
},
397+
{
398+
test: /\.woff2?$/,
399+
loader: 'file-loader',
400+
options: {
401+
name: '[name].[ext]',
402+
},
403+
},
404+
],
405+
},
406+
plugins: [
407+
new ExtractTextPlugin({
408+
filename: 'style.css',
409+
allChunks: true,
410+
}),
411+
new HtmlWebpackPlugin(),
412+
new PreloadPlugin({
413+
rel: 'preload',
414+
include: 'allAssets'
415+
}),
416+
]
417+
}, function(err, result) {
418+
expect(err).toBeFalsy();
419+
expect(JSON.stringify(result.compilation.errors)).toBe('[]');
420+
const html = result.compilation.assets['index.html'].source();
421+
expect(html).toContain('<link rel="preload" as="script" href="/chunk');
422+
expect(html).toContain('<link rel="preload" as="script" href="/bundle.js"');
423+
expect(html).toContain('<link rel="preload" as="style" href="/style.css"');
424+
expect(html).toContain('<link rel="preload" as="font" crossorigin="crossorigin" href="/font.woff2"');
425+
done();
426+
});
427+
compiler.outputFileSystem = new MemoryFileSystem();
428+
});
340429
});
341430

342431
describe('filtering unwanted files', function() {

0 commit comments

Comments
 (0)