Skip to content

Commit

Permalink
Add in asset filename filtering via {test, include, exclude} (#1149)
Browse files Browse the repository at this point in the history
* Add in filtering via {test, include, exclude} options.

* Updated a comment.
  • Loading branch information
jeffposnick authored Jan 4, 2018
1 parent 3fc0178 commit dde16ba
Show file tree
Hide file tree
Showing 9 changed files with 538 additions and 13 deletions.
19 changes: 6 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"firebase-tools": "^3.13.1",
"fs-extra": "^4.0.1",
"geckodriver": "^1.8.1",
"generate-asset-webpack-plugin": "^0.3.0",
"github": "^12.0.1",
"glob": "^7.1.2",
"gulp": "github:gulpjs/gulp#4.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/workbox-webpack-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"json-stable-stringify": "^1.0.1",
"workbox-build": "^3.0.0-alpha.3"
},
"peerDependencies": {
"webpack": "^2.0.0 || ^3.0.0"
},
"author": "Will Farley <[email protected]> (http://www.willfarley.org/)",
"license": "Apache-2.0",
"repository": "googlechrome/workbox",
Expand Down
6 changes: 6 additions & 0 deletions packages/workbox-webpack-plugin/src/generate-sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ class GenerateSW {
constructor(config = {}) {
this.config = Object.assign({}, {
chunks: [],
exclude: [
// Exclude source maps.
/\.map$/,
// Exclude anything starting with manifest and ending .js or .json.
/^manifest.*\.js(?:on)?$/,
],
excludeChunks: [],
importScripts: [],
importWorkboxFrom: 'cdn',
Expand Down
6 changes: 6 additions & 0 deletions packages/workbox-webpack-plugin/src/inject-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class InjectManifest {

this.config = Object.assign({}, {
chunks: [],
exclude: [
// Exclude source maps.
/\.map$/,
// Exclude anything starting with manifest and ending .js or .json.
/^manifest.*\.js(?:on)?$/,
],
excludeChunks: [],
importScripts: [],
importWorkboxFrom: 'cdn',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
limitations under the License.
*/

const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');

const getAssetHash = require('./get-asset-hash');
const resolveWebpackUrl = require('./resolve-webpack-url');

Expand Down Expand Up @@ -177,6 +179,13 @@ function getManifestEntriesFromCompilation(compilation, config) {

const manifestEntries = [];
for (const [file, metadata] of Object.entries(filteredAssetMetadata)) {
// Filter based on test/include/exclude options set in the config,
// following webpack's conventions.
// This matches the behavior of, e.g., UglifyJS's webpack plugin.
if (!ModuleFilenameHelpers.matchObject(config, file)) {
continue;
}

const publicUrl = resolveWebpackUrl(publicPath, file);
const manifestEntry = getEntry(knownHashes, publicUrl, metadata.hash);
manifestEntries.push(manifestEntry);
Expand Down
6 changes: 6 additions & 0 deletions packages/workbox-webpack-plugin/src/lib/sanitize-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
function forGetManifest(originalConfig) {
const propertiesToRemove = [
'chunks',
'exclude',
'excludeChunks',
'importScripts',
'importWorkboxFrom',
'include',
'swDest',
'swSrc',
'test',
];

return sanitizeConfig(originalConfig, propertiesToRemove);
Expand All @@ -46,9 +49,12 @@ function forGetManifest(originalConfig) {
function forGenerateSWString(originalConfig) {
const propertiesToRemove = [
'chunks',
'exclude',
'excludeChunks',
'importWorkboxFrom',
'include',
'swDest',
'test',
];

return sanitizeConfig(originalConfig, propertiesToRemove);
Expand Down
248 changes: 248 additions & 0 deletions test/workbox-webpack-plugin/node/generate-sw.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const CopyWebpackPlugin = require('copy-webpack-plugin');
const GenerateAssetPlugin = require('generate-asset-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const expect = require('chai').expect;
const fse = require('fs-extra');
Expand Down Expand Up @@ -655,4 +656,251 @@ describe(`[workbox-webpack-plugin] GenerateSW (End to End)`, function() {
});
});
});

describe(`[workbox-webpack-plugin] Filtering via test/include/exclude`, function() {
const TEST_ASSET_CB = (compilation, callback) => callback(null, 'test');

it(`should exclude .map and manifest.js(on) files by default`, function(done) {
const FILE_MANIFEST_NAME = 'precache-manifest.43591bdf46c7ac47eb8d7b2bcd41f13e.js';
const outputDir = tempy.directory();
const config = {
entry: path.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: WEBPACK_ENTRY_FILENAME,
path: outputDir,
},
devtool: 'source-map',
plugins: [
new GenerateAssetPlugin({
filename: 'manifest.js',
fn: TEST_ASSET_CB,
}),
new GenerateAssetPlugin({
filename: 'manifest.json',
fn: TEST_ASSET_CB,
}),
new GenerateSW(),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError) => {
if (webpackError) {
return done(webpackError);
}

const swFile = path.join(outputDir, 'service-worker.js');
try {
// First, validate that the generated service-worker.js meets some basic assumptions.
await validateServiceWorkerRuntime({swFile, expectedMethodCalls: {
importScripts: [[
FILE_MANIFEST_NAME,
WORKBOX_SW_FILE_NAME,
]],
suppressWarnings: [[]],
precacheAndRoute: [[[], {}]],
}});

// Next, test the generated manifest to ensure that it contains
// exactly the entries that we expect.
const manifestFileContents = await fse.readFile(path.join(outputDir, FILE_MANIFEST_NAME), 'utf-8');
const context = {self: {}};
vm.runInNewContext(manifestFileContents, context);

const expectedEntries = [{
revision: '8e8e9f093f036bd18dfa',
url: 'webpackEntry.js',
}];
expect(context.self.__precacheManifest).to.eql(expectedEntries);

done();
} catch (error) {
done(error);
}
});
});

it(`should allow developers to override the default exclude filter`, function(done) {
const FILE_MANIFEST_NAME = 'precache-manifest.b87ef85173e527290f94979b09e72d12.js';
const outputDir = tempy.directory();
const config = {
entry: path.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: WEBPACK_ENTRY_FILENAME,
path: outputDir,
},
devtool: 'source-map',
plugins: [
new GenerateSW({
exclude: [],
}),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError) => {
if (webpackError) {
return done(webpackError);
}

const swFile = path.join(outputDir, 'service-worker.js');
try {
// First, validate that the generated service-worker.js meets some basic assumptions.
await validateServiceWorkerRuntime({swFile, expectedMethodCalls: {
importScripts: [[
FILE_MANIFEST_NAME,
WORKBOX_SW_FILE_NAME,
]],
suppressWarnings: [[]],
precacheAndRoute: [[[], {}]],
}});

// Next, test the generated manifest to ensure that it contains
// exactly the entries that we expect.
const manifestFileContents = await fse.readFile(path.join(outputDir, FILE_MANIFEST_NAME), 'utf-8');
const context = {self: {}};
vm.runInNewContext(manifestFileContents, context);

const expectedEntries = [{
revision: '8e8e9f093f036bd18dfa',
url: 'webpackEntry.js.map',
}, {
revision: '8e8e9f093f036bd18dfa',
url: 'webpackEntry.js',
}];
expect(context.self.__precacheManifest).to.eql(expectedEntries);

done();
} catch (error) {
done(error);
}
});
});

it(`should allow developers to whitelist via include`, function(done) {
const FILE_MANIFEST_NAME = 'precache-manifest.1242f9e007897f035a52e56690ff17a6.js';
const outputDir = tempy.directory();
const config = {
entry: path.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: WEBPACK_ENTRY_FILENAME,
path: outputDir,
},
devtool: 'source-map',
plugins: [
new CopyWebpackPlugin([{
from: SRC_DIR,
to: outputDir,
}]),
new GenerateSW({
include: [/.html$/],
}),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError) => {
if (webpackError) {
return done(webpackError);
}

const swFile = path.join(outputDir, 'service-worker.js');
try {
// First, validate that the generated service-worker.js meets some basic assumptions.
await validateServiceWorkerRuntime({swFile, expectedMethodCalls: {
importScripts: [[
FILE_MANIFEST_NAME,
WORKBOX_SW_FILE_NAME,
]],
suppressWarnings: [[]],
precacheAndRoute: [[[], {}]],
}});

// Next, test the generated manifest to ensure that it contains
// exactly the entries that we expect.
const manifestFileContents = await fse.readFile(path.join(outputDir, FILE_MANIFEST_NAME), 'utf-8');
const context = {self: {}};
vm.runInNewContext(manifestFileContents, context);

const expectedEntries = [{
revision: 'a3a71ce0b9b43c459cf58bd37e911b74',
url: 'page-2.html',
}, {
revision: '544658ab25ee8762dc241e8b1c5ed96d',
url: 'page-1.html',
}, {
revision: '3883c45b119c9d7e9ad75a1b4a4672ac',
url: 'index.html',
}];
expect(context.self.__precacheManifest).to.eql(expectedEntries);

done();
} catch (error) {
done(error);
}
});
});

it(`should allow developers to combine the test and exclude filters`, function(done) {
const FILE_MANIFEST_NAME = 'precache-manifest.83df65831eb442f8ad5fbeb8edecc558.js';
const outputDir = tempy.directory();
const config = {
entry: path.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: WEBPACK_ENTRY_FILENAME,
path: outputDir,
},
devtool: 'source-map',
plugins: [
new CopyWebpackPlugin([{
from: SRC_DIR,
to: outputDir,
}]),
new GenerateSW({
test: [/.html$/],
exclude: [/index/],
}),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError) => {
if (webpackError) {
return done(webpackError);
}

const swFile = path.join(outputDir, 'service-worker.js');
try {
// First, validate that the generated service-worker.js meets some basic assumptions.
await validateServiceWorkerRuntime({swFile, expectedMethodCalls: {
importScripts: [[
FILE_MANIFEST_NAME,
WORKBOX_SW_FILE_NAME,
]],
suppressWarnings: [[]],
precacheAndRoute: [[[], {}]],
}});

// Next, test the generated manifest to ensure that it contains
// exactly the entries that we expect.
const manifestFileContents = await fse.readFile(path.join(outputDir, FILE_MANIFEST_NAME), 'utf-8');
const context = {self: {}};
vm.runInNewContext(manifestFileContents, context);

const expectedEntries = [{
revision: 'a3a71ce0b9b43c459cf58bd37e911b74',
url: 'page-2.html',
}, {
revision: '544658ab25ee8762dc241e8b1c5ed96d',
url: 'page-1.html',
}];
expect(context.self.__precacheManifest).to.eql(expectedEntries);

done();
} catch (error) {
done(error);
}
});
});
});
});
Loading

0 comments on commit dde16ba

Please sign in to comment.