Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compileSrc option to InjectManifet webpack plugin #2412

Merged
merged 3 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/workbox-build/src/options/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
babelPresetEnvTargets: ['chrome >= 56'],
cleanupOutdatedCaches: false,
clientsClaim: false,
compileSrc: true,
disableDevLogs: false,
exclude: [
/\.map$/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const joi = require('@hapi/joi');
const upath = require('upath');

const basePartial = require('../partials/base');
const defaults = require('../defaults');
const injectPartial = require('../partials/inject');
const webpackPartial = require('../partials/webpack');

Expand All @@ -22,7 +23,9 @@ const swSrcBasename = (context) => {
swSrcBasename.description = 'derived from the swSrc file name';

const supportedOptions = Object.assign({
webpackCompilationPlugins: joi.array().items(joi.object()),
compileSrc: joi.boolean().default(defaults.compileSrc),
webpackCompilationPlugins: joi.array().items(joi.object()).when(
'compileSrc', {is: false, then: joi.forbidden()}),
}, basePartial, injectPartial, webpackPartial);

module.exports = joi.object().keys(supportedOptions).keys({
Expand Down
61 changes: 48 additions & 13 deletions packages/workbox-webpack-plugin/src/inject-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ class InjectManifest {
* @param {Array<string>} [config.chunks] One or more chunk names whose corresponding
* output files should be included in the precache manifest.
*
* @param {boolean} [config.compileSrc=true] When `true` (the default), the
* `swSrc` file will be compiled by webpack. When `false`, compilation will
* not occur (and `webpackCompilationPlugins` can't be used.) Set to `false`
* if you want to inject the manifest into, e.g., a JSON file.
*
* @param {RegExp} [config.dontCacheBustURLsMatching] Assets that match this will be
* assumed to be uniquely versioned via their URL, and exempted from the normal
* HTTP cache-busting that's done when populating the precache. While not
Expand Down Expand Up @@ -158,17 +163,7 @@ class InjectManifest {
*
* @private
*/
async handleMake(compilation, parentCompiler) {
try {
this.config = validate(this.config, webpackInjectManifestSchema);
} catch (error) {
throw new Error(`Please check your ${this.constructor.name} plugin ` +
`configuration:\n${error.message}`);
}

this.config.swDest = relativeToOutputPath(compilation, this.config.swDest);
_generatedAssetNames.add(this.config.swDest);

async performChildCompilation(compilation, parentCompiler) {
const outputOptions = {
path: parentCompiler.options.output.path,
filename: this.config.swDest,
Expand Down Expand Up @@ -211,6 +206,42 @@ class InjectManifest {
});
}

/**
* @param {Object} compilation The webpack compilation.
* @param {Object} parentCompiler The webpack parent compiler.
*
* @private
*/
addSrcToAssets(compilation, parentCompiler) {
const source = parentCompiler.inputFileSystem.readFileSync(
this.config.swSrc).toString();
compilation.assets[this.config.swDest] = new RawSource(source);
}

/**
* @param {Object} compilation The webpack compilation.
* @param {Object} parentCompiler The webpack parent compiler.
*
* @private
*/
async handleMake(compilation, parentCompiler) {
try {
this.config = validate(this.config, webpackInjectManifestSchema);
} catch (error) {
throw new Error(`Please check your ${this.constructor.name} plugin ` +
`configuration:\n${error.message}`);
}

this.config.swDest = relativeToOutputPath(compilation, this.config.swDest);
_generatedAssetNames.add(this.config.swDest);

if (this.config.compileSrc) {
await this.performChildCompilation(compilation, parentCompiler);
} else {
this.addSrcToAssets(compilation, parentCompiler);
}
}

/**
* @param {Object} compilation The webpack compilation.
*
Expand Down Expand Up @@ -240,15 +271,19 @@ class InjectManifest {

const swAsset = compilation.assets[config.swDest];
const initialSWAssetString = swAsset.source();

if (!initialSWAssetString.includes(config.injectionPoint)) {
throw new Error(`Can't find ${config.injectionPoint} in your SW source.`);
}

const manifestEntries = await getManifestEntriesFromCompilation(
compilation, config);

// See https://github.com/GoogleChrome/workbox/issues/2263
const manifestString = stringify(manifestEntries).replace(/"/g, `'`);
let manifestString = stringify(manifestEntries);
if (this.config.compileSrc) {
// See https://github.com/GoogleChrome/workbox/issues/2263
manifestString = manifestString.replace(/"/g, `'`);
}

const sourcemapAssetName = getSourcemapAssetName(
compilation, initialSWAssetString, config.swDest);
Expand Down
127 changes: 123 additions & 4 deletions test/workbox-webpack-plugin/node/inject-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@
https://opensource.org/licenses/MIT.
*/

const chai = require('chai');
const chaiMatchPattern = require('chai-match-pattern');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkerPlugin = require('worker-plugin');
const expect = require('chai').expect;
const fse = require('fs-extra');
const globby = require('globby');
const upath = require('upath');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const tempy = require('tempy');
const upath = require('upath');
const webpack = require('webpack');
const WorkerPlugin = require('worker-plugin');

const CreateWebpackAssetPlugin = require('../../../infra/testing/create-webpack-asset-plugin');
const validateServiceWorkerRuntime = require('../../../infra/testing/validator/service-worker-runtime');
const webpackBuildCheck = require('../../../infra/testing/webpack-build-check');
const {InjectManifest} = require('../../../packages/workbox-webpack-plugin/src/index');

chai.use(chaiMatchPattern);
const {expect} = chai;

describe(`[workbox-webpack-plugin] InjectManifest (End to End)`, function() {
const WEBPACK_ENTRY_FILENAME = 'webpackEntry.js';
const SRC_DIR = upath.join(__dirname, '..', 'static', 'example-project-1');
Expand Down Expand Up @@ -1555,4 +1559,119 @@ describe(`[workbox-webpack-plugin] InjectManifest (End to End)`, function() {
});
});
});

describe(`[workbox-webpack-plugin] Non-compilation scenarios`, function() {
it(`should error when compileSrc is false and webpackCompilationPlugins is used`, function(done) {
const outputDir = tempy.directory();

const config = {
mode: 'production',
entry: upath.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: '[name].[hash:20].js',
path: outputDir,
},
plugins: [
new InjectManifest({
compileSrc: false,
swDest: 'injected-manifest.json',
swSrc: upath.join(__dirname, '..', 'static', 'injected-manifest.json'),
webpackCompilationPlugins: [{}],
}),
],
};

const compiler = webpack(config);
compiler.run((webpackError, stats) => {
expect(webpackError).not.to.exist;
const statsJson = stats.toJson();
expect(statsJson.warnings).to.be.empty;
expect(statsJson.errors).to.have.members([
`Please check your InjectManifest plugin configuration:\nchild "webpackCompilationPlugins" fails because ["webpackCompilationPlugins" is not allowed]`,
]);

done();
});
});

it(`should support injecting a manifest into a JSON file`, function(done) {
const outputDir = tempy.directory();

const config = {
mode: 'production',
entry: upath.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: '[name].[hash:20].js',
path: outputDir,
},
plugins: [
new InjectManifest({
compileSrc: false,
swDest: 'injected-manifest.json',
swSrc: upath.join(__dirname, '..', 'static', 'injected-manifest.json'),
}),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError, stats) => {
try {
webpackBuildCheck(webpackError, stats);

const files = await globby('**', {cwd: outputDir});
expect(files).to.have.length(2);

const manifest = await fse.readJSON(upath.join(outputDir, 'injected-manifest.json'));
expect(manifest).to.matchPattern([{
revision: /^[0-9a-f]{32}$/,
url: /^main\.[0-9a-f]{20}\.js$/,
}]);

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

it(`should support injecting a manifest into a CJS module`, function(done) {
const outputDir = tempy.directory();

const config = {
mode: 'production',
entry: upath.join(SRC_DIR, WEBPACK_ENTRY_FILENAME),
output: {
filename: '[name].[hash:20].js',
path: outputDir,
},
plugins: [
new InjectManifest({
compileSrc: false,
swDest: 'injected-manifest.js',
swSrc: upath.join(__dirname, '..', 'static', 'injected-manifest.js'),
}),
],
};

const compiler = webpack(config);
compiler.run(async (webpackError, stats) => {
try {
webpackBuildCheck(webpackError, stats);

const files = await globby('**', {cwd: outputDir});
expect(files).to.have.length(2);

const manifest = require(upath.join(outputDir, 'injected-manifest.js'));
expect(manifest).to.matchPattern([{
revision: /^[0-9a-f]{32}$/,
url: /^main\.[0-9a-f]{20}\.js$/,
}]);

done();
} catch (error) {
done(error);
}
});
});
});
8 changes: 8 additions & 0 deletions test/workbox-webpack-plugin/static/injected-manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Copyright 2020 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

module.exports = self.__WB_MANIFEST;
1 change: 1 addition & 0 deletions test/workbox-webpack-plugin/static/injected-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
self.__WB_MANIFEST