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

Provide a way to include all assets (issue #35) #36

Merged
merged 11 commits into from
Feb 28, 2018
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,23 @@ will inject just this:
<link rel="preload" as="script" href="home.31132ae6680e598f8879.js">
```

It is very common in Webpack to use loaders such as `file-loader` to generate assets for specific
types, such as fonts or images. If you wish to preload these files as well, you can use `include`
with value `all-assets`:

```js
plugins: [
new HtmlWebpackPlugin(),
new PreloadWebpackPlugin({
rel: 'preload',
include: 'all-assets',
})
]
```

Usually you don't want to preload all of them but only keep the necessary resources, you can use
`fileBlacklist` or `fileWhitelist` shown below to filter.

Filtering chunks
---------------------

Expand All @@ -181,6 +198,28 @@ new PreloadWebpackPlugin({
})
```

If you use `include="all-assets"`, you might find excluding all unnecessary files one by one a
bit annoying. In this case, you can use `fileWhitelist` to only include the files you want:

```js
new PreloadWebpackPlugin({
fileWhitelist: [/\.files/, /\.to/, /\.include/],
})
```

notice that if `fileWhitelist` is not provided, it will not filter any file out.

Also, you could use `fileWhitelist` and `fileBlacklist` together:

```js
new PreloadWebpackPlugin({
fileWhitelist: [/\.files/, /\.to/, /\.include/],
fileBlacklist: [/\.files/, /\.to/, /\.exclude/],
})
```

In example above, only files with name matches `/\.include/` will be included.

Resource Hints
---------------------

Expand Down
11 changes: 10 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class PreloadPlugin {
} else if (options.include === 'all') {
// Async chunks, vendor chunks, normal chunks.
extractedChunks = compilation.chunks;
} else if (options.include === 'all-assets') {
extractedChunks = [{files: Object.keys(compilation.assets)}];
} else if (Array.isArray(options.include)) {
// Keep only user specified chunks
extractedChunks = compilation
Expand All @@ -66,7 +68,14 @@ class PreloadPlugin {

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

flatten(extractedChunks.map(chunk => chunk.files)).filter(entry => {
flatten(extractedChunks.map(chunk => chunk.files))
.filter(entry => {
return (
!this.options.fileWhitelist ||
this.options.fileWhitelist.some(regex => regex.test(entry) === true)
);
})
.filter(entry => {
return this.options.fileBlacklist.every(regex => regex.test(entry) === false);
}).forEach(entry => {
entry = `${publicPath}${entry}`;
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@
"homepage": "https://github.com/googlechrome/preload-webpack-plugin",
"devDependencies": {
"babel-eslint": "^7.1.1",
"css-loader": "^0.28.7",
"eslint": "^3.14.1",
"eslint-config-google": "^0.7.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.26.0",
"jasmine": "^2.5.3",
"webpack": "^3.2.0"
"webpack": "^3.4.0"
},
"peerDependencies": {
"webpack": "^3.2.0"
Expand Down
Empty file added test/fixtures/font.woff2
Empty file.
22 changes: 22 additions & 0 deletions test/fixtures/load-css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
console.log('lol');
console.log(require('./style.css'));
require.ensure(["./home.js"], function() {
// var a = require("module-a");
// console.log(a);
}, 'home');
4 changes: 4 additions & 0 deletions test/fixtures/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@font-face {
font-family: test;
src: url(./font.woff2);
}
89 changes: 89 additions & 0 deletions test/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PreloadPlugin = require('../');
const OUTPUT_DIR = path.join(__dirname, 'dist');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

describe('PreloadPlugin preloads or prefetches async chunks', function() {
it('adds preload tags to async chunks', function(done) {
Expand Down Expand Up @@ -337,6 +338,94 @@ describe('PreloadPlugin filters chunks', function() {
});
compiler.outputFileSystem = new MemoryFileSystem();
});
it('use fileWhitelist to include only specific files', (done) => {
const compiler = webpack({
entry: path.join(__dirname, 'fixtures', 'file.js'),
devtool: 'cheap-source-map',
output: {
path: OUTPUT_DIR,
filename: 'bundle.js',
chunkFilename: '[name].js',
publicPath: '/',
},
plugins: [
new HtmlWebpackPlugin(),
new PreloadPlugin({
rel: 'preload',
as: 'script',
fileWhitelist: [/home/],
})
]
}, function(err, result) {
expect(err).toBeFalsy();
expect(JSON.stringify(result.compilation.errors)).toBe('[]');
const html = result.compilation.assets['index.html'].source();
expect(html).toContain('<link rel="preload" as="script" href="/home.js');
// exclude by default fileBlacklist
expect(html).not.toContain('<link rel="preload" as="script" href="/home.js.map');
// not included in fileWhitelist
expect(html).not.toContain('<link rel="preload" as="script" href="/bundle.js"');
done();
});
compiler.outputFileSystem = new MemoryFileSystem();
});
});

describe('PreloadPlugin preloads all assets', function() {
it('adds preload tags', function(done) {
const compiler = webpack({
entry: path.join(__dirname, 'fixtures', 'load-css.js'),
output: {
path: OUTPUT_DIR,
filename: 'bundle.js',
chunkFilename: 'chunk.[chunkhash].js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'css-loader',
use: [
{
loader: 'css-loader',
},
],
}),
},
{
test: /\.woff2?$/,
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
plugins: [
new ExtractTextPlugin({
filename: 'style.css',
allChunks: true,
}),
new HtmlWebpackPlugin(),
new PreloadPlugin({
rel: 'preload',
include: 'all-assets'
}),
]
}, function(err, result) {
expect(err).toBeFalsy();
expect(JSON.stringify(result.compilation.errors)).toBe('[]');
const html = result.compilation.assets['index.html'].source();
expect(html).toContain('<link rel="preload" as="script" href="/chunk');
expect(html).toContain('<link rel="preload" as="script" href="/bundle.js"');
expect(html).toContain('<link rel="preload" as="style" href="/style.css"');
expect(html).toContain('<link rel="preload" as="font" crossorigin="crossorigin" href="/font.woff2"');
done();
});
compiler.outputFileSystem = new MemoryFileSystem();
});
});

describe('filtering unwanted files', function() {
Expand Down