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

feat: migrate workbox-webpack-plugin to typescript #2882

Merged
merged 26 commits into from Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ab4752c
feat: migrate workbox-webpack-plugin to typescript
roikoren755 Jul 4, 2021
e1db3a6
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Aug 5, 2021
7c70903
progress on typescript migration
tropicadri Aug 24, 2021
ab6494d
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Aug 25, 2021
e68ffd3
15e from ts lint
tropicadri Aug 25, 2021
bf21104
draft
tropicadri Aug 26, 2021
9e56e65
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Aug 26, 2021
9a03d5c
fixing webpack version
tropicadri Sep 3, 2021
e47a480
running tests
tropicadri Sep 3, 2021
eec253b
running tests
tropicadri Sep 4, 2021
e4f9032
eslint
tropicadri Sep 4, 2021
8a5ee86
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Dec 23, 2021
3ded4ab
passing tests for workbox webpack plugin
tropicadri Jan 3, 2022
39d313b
passing tests for wb wpp
tropicadri Jan 3, 2022
347bbe2
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Jan 3, 2022
33df7d5
Merge branch 'copyofwbwpp' into workbox-webpack-plugin-ts
tropicadri Jan 3, 2022
dfcc568
passing tests for workbox webpack plugin
tropicadri Jan 3, 2022
852d638
Merge branch 'workbox-webpack-plugin-ts' of github.com:GoogleChrome/w…
tropicadri Jan 8, 2022
fa26432
cleaning some eslint messages
tropicadri Jan 8, 2022
9147336
keeping the checkConditions method signature for backward compatibility
tropicadri Feb 17, 2022
3917f2f
fixing documentation
tropicadri Feb 17, 2022
d115025
commiting package-lock
tropicadri Feb 17, 2022
784d0d8
Merge branch 'v6' into workbox-webpack-plugin-ts
tropicadri Feb 17, 2022
e563152
updating the webpack plugin package-lock
tropicadri Feb 17, 2022
ea9a76e
Merge branch 'workbox-webpack-plugin-ts' of https://github.com/roikor…
tropicadri Feb 17, 2022
9ee1ec9
Fixing typescript typing issues
tropicadri Feb 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27,203 changes: 26,980 additions & 223 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -22,6 +22,7 @@
"@types/fs-extra": "^9.0.5",
"@types/lodash": "^4.14.165",
"@types/stringify-object": "^3.3.0",
"@types/webpack": "^5.28.0",
tropicadri marked this conversation as resolved.
Show resolved Hide resolved
"@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.32.0",
"acorn": "^8.0.1",
Expand Down Expand Up @@ -123,6 +124,5 @@
"test_node": "gulp test_node",
"test_server": "gulp test_server",
"version": "gulp build && git add -A packages"
},
"version": "0.0.0"
}
}
4 changes: 2 additions & 2 deletions packages/workbox-build/src/lib/populate-sw-template.ts
Expand Up @@ -31,9 +31,9 @@ export function populateSWTemplate({
offlineGoogleAnalytics,
runtimeCaching = [],
skipWaiting,
}: GeneratePartial & {manifestEntries: Array<ManifestEntry>}): string {
}: GeneratePartial & {manifestEntries?: Array<ManifestEntry>}): string {
// There needs to be at least something to precache, or else runtime caching.
if (!(manifestEntries.length > 0 || runtimeCaching.length > 0)) {
if (!(manifestEntries?.length > 0 || runtimeCaching.length > 0)) {
throw new Error(errors['no-manifest-entries-or-runtime-caching']);
}

Expand Down
6 changes: 2 additions & 4 deletions packages/workbox-webpack-plugin/package.json
Expand Up @@ -13,12 +13,10 @@
"file manifest"
],
"workbox": {
"packageType": "node"
"packageType": "node_ts"
},
"main": "build/index.js",
"files": [
"build"
],
"types": "build/index.d.ts",
"engines": {
"node": ">=10.0.0"
},
Expand Down
Expand Up @@ -6,26 +6,27 @@
https://opensource.org/licenses/MIT.
*/

const {validateWebpackGenerateSWOptions} =
require('workbox-build/build/lib/validate-options');
const {bundle} = require('workbox-build/build/lib/bundle');
const {populateSWTemplate} =
require('workbox-build/build/lib/populate-sw-template');
const prettyBytes = require('pretty-bytes');
const webpack = require('webpack');

const getScriptFilesForChunks = require('./lib/get-script-files-for-chunks');
const getManifestEntriesFromCompilation =
require('./lib/get-manifest-entries-from-compilation');
const relativeToOutputPath = require('./lib/relative-to-output-path');
import {validateWebpackGenerateSWOptions} from 'workbox-build/build/lib/validate-options';
import {bundle} from 'workbox-build/build/lib/bundle';
import {populateSWTemplate} from 'workbox-build/build/lib/populate-sw-template';
import prettyBytes from 'pretty-bytes';
import webpack from 'webpack';
import {ManifestEntry, WebpackGenerateSWOptions} from 'workbox-build';
import {getScriptFilesForChunks} from './lib/get-script-files-for-chunks';
import {getManifestEntriesFromCompilation} from './lib/get-manifest-entries-from-compilation';
import {relativeToOutputPath} from './lib/relative-to-output-path';

// webpack v4/v5 compatibility:
// https://github.com/webpack/webpack/issues/11425#issuecomment-686607633
const {RawSource} = webpack.sources || require('webpack-sources');

// Used to keep track of swDest files written by *any* instance of this plugin.
// See https://github.com/GoogleChrome/workbox/issues/2181
const _generatedAssetNames = new Set();
const _generatedAssetNames = new Set<string>();

interface GenerateSWConfig extends WebpackGenerateSWOptions {
manifestEntries?: Array<ManifestEntry>;
jeffposnick marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* This class supports creating a new, ready-to-use service worker file as
Expand All @@ -38,6 +39,8 @@ const _generatedAssetNames = new Set();
* @memberof module:workbox-webpack-plugin
*/
class GenerateSW {
private config: GenerateSWConfig;
private alreadyCalled: boolean;
// eslint-disable-next-line jsdoc/newline-after-description
/**
* Creates an instance of GenerateSW.
Expand Down Expand Up @@ -79,7 +82,7 @@ class GenerateSW {
* [asset's metadata](https://github.com/webpack/webpack/issues/9038) is used
* to determine whether it's immutable or not.)
*
* @param {Array<string|RegExp|Function>} [config.exclude=[/\.map$/, /^manifest.*\.js$]]
* @param {Array<string|RegExp>} [config.exclude=[/\.map$/, /^manifest.*\.js$]]
jeffposnick marked this conversation as resolved.
Show resolved Hide resolved
* One or more specifiers used to exclude assets from the precache manifest.
* This is interpreted following
* [the same rules](https://webpack.js.org/configuration/module/#condition)
Expand All @@ -104,7 +107,7 @@ class GenerateSW {
* webpack chunks. The content of those chunks will be included in the
* generated service worker, via a call to `importScripts()`.
*
* @param {Array<string|RegExp|Function>} [config.include]
* @param {Array<string|RegExp>} [config.include]
* One or more specifiers used to include assets in the precache manifest.
* This is interpreted following
* [the same rules](https://webpack.js.org/configuration/module/#condition)
Expand Down Expand Up @@ -190,7 +193,7 @@ class GenerateSW {
* @param {string} [config.swDest='service-worker.js'] The asset name of the
* service worker file that will be created by this plugin.
*/
constructor(config = {}) {
constructor(config: GenerateSWConfig = {}) {
this.config = config;
this.alreadyCalled = false;
}
Expand All @@ -200,46 +203,56 @@ class GenerateSW {
*
* @private
*/
propagateWebpackConfig(compiler) {
propagateWebpackConfig(compiler: webpack.Compiler): void {
// Because this.config is listed last, properties that are already set
// there take precedence over derived properties from the compiler.
this.config = Object.assign({
mode: compiler.options.mode,
sourcemap: Boolean(compiler.options.devtool),
}, this.config);
this.config = Object.assign(
{
mode: compiler.options.mode,
sourcemap: Boolean(compiler.options.devtool),
},
this.config,
);
}

/**
* @param {Object} [compiler] default compiler object passed from webpack
*
* @private
*/
apply(compiler) {
apply(compiler: webpack.Compiler): void {
this.propagateWebpackConfig(compiler);

// webpack v4/v5 compatibility:
// https://github.com/webpack/webpack/issues/11425#issuecomment-690387207
if (webpack.version.startsWith('4.')) {
compiler.hooks.emit.tapPromise(
this.constructor.name,
(compilation) => this.addAssets(compilation).catch(
(error) => compilation.errors.push(error)),
compiler.hooks.emit.tapPromise(this.constructor.name, (compilation) =>
this.addAssets(compilation).catch((error) => {
compilation.errors.push(error);
}),
);
} else {
const {PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER} = webpack.Compilation;
// Specifically hook into thisCompilation, as per
// https://github.com/webpack/webpack/issues/11425#issuecomment-690547848
compiler.hooks.thisCompilation.tap(
this.constructor.name, (compilation) => {
compilation.hooks.processAssets.tapPromise({
this.constructor.name,
(compilation) => {
compilation.hooks.processAssets.tapPromise(
{
name: this.constructor.name,
// TODO(jeffposnick): This may need to change eventually.
// See https://github.com/webpack/webpack/issues/11822#issuecomment-726184972
stage: PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER - 10,
}, () => this.addAssets(compilation).catch(
(error) => compilation.errors.push(error)),
);
},
},
() =>
this.addAssets(compilation).catch(
(error: webpack.WebpackError) => {
compilation.errors.push(error);
},
),
);
},
);
}
}
Expand All @@ -249,53 +262,68 @@ class GenerateSW {
*
* @private
*/
async addAssets(compilation) {
async addAssets(compilation: webpack.Compilation): Promise<void> {
// See https://github.com/GoogleChrome/workbox/issues/1790
if (this.alreadyCalled) {
const warningMessage = `${this.constructor.name} has been called ` +
const warningMessage =
`${this.constructor.name} has been called ` +
`multiple times, perhaps due to running webpack in --watch mode. The ` +
`precache manifest generated after the first call may be inaccurate! ` +
`Please see https://github.com/GoogleChrome/workbox/issues/1790 for ` +
`more information.`;

if (!compilation.warnings.some((warning) => warning instanceof Error &&
warning.message === warningMessage)) {
compilation.warnings.push(new Error(warningMessage));
if (
!compilation.warnings.some(
(warning) =>
warning instanceof Error && warning.message === warningMessage,
)
) {
compilation.warnings.push(
Error(warningMessage) as webpack.WebpackError,
);
}
} else {
this.alreadyCalled = true;
}

let config;
let config: GenerateSWConfig = {};
try {
// emit might be called multiple times; instead of modifying this.config,
// use a validated copy.
// See https://github.com/GoogleChrome/workbox/issues/2158
config = validateWebpackGenerateSWOptions(this.config);
} catch (error) {
throw new Error(`Please check your ${this.constructor.name} plugin ` +
`configuration:\n${error.message}`);
if (error instanceof Error) {
throw new Error(
`Please check your ${this.constructor.name} plugin ` +
`configuration:\n${error.message}`,
);
}
}

// Ensure that we don't precache any of the assets generated by *any*
// instance of this plugin.
config.exclude.push(({asset}) => _generatedAssetNames.has(asset.name));
config.exclude!.push((asset: string) => _generatedAssetNames.has(asset));

if (config.importScriptsViaChunks) {
// Anything loaded via importScripts() is implicitly cached by the service
// worker, and should not be added to the precache manifest.
config.excludeChunks = (config.excludeChunks || [])
.concat(config.importScriptsViaChunks);
config.excludeChunks = (config.excludeChunks || []).concat(
config.importScriptsViaChunks,
);

const scripts = getScriptFilesForChunks(
compilation, config.importScriptsViaChunks);
compilation,
config.importScriptsViaChunks,
);

config.importScripts = (config.importScripts || [])
.concat(scripts);
config.importScripts = (config.importScripts || []).concat(scripts);
}

const {size, sortedEntries} = await getManifestEntriesFromCompilation(
compilation, config);
compilation,
config,
);
config.manifestEntries = sortedEntries;

const unbundledCode = populateSWTemplate(config);
Expand All @@ -305,24 +333,28 @@ class GenerateSW {
inlineWorkboxRuntime: config.inlineWorkboxRuntime,
mode: config.mode,
sourcemap: config.sourcemap,
swDest: relativeToOutputPath(compilation, config.swDest),
swDest: relativeToOutputPath(compilation, config.swDest!),
unbundledCode,
});

for (const file of files) {
compilation.emitAsset(file.name, new RawSource(file.contents), {
// See https://github.com/webpack-contrib/compression-webpack-plugin/issues/218#issuecomment-726196160
minimized: config.mode === 'production',
});
compilation.emitAsset(
file.name,
new RawSource(Buffer.from(file.contents)),
{
// See https://github.com/webpack-contrib/compression-webpack-plugin/issues/218#issuecomment-726196160
minimized: config.mode === 'production',
},
);
_generatedAssetNames.add(file.name);
}

if (compilation.getLogger) {
const logger = compilation.getLogger(this.constructor.name);
logger.info(`The service worker at ${config.swDest} will precache
logger.info(`The service worker at ${config.swDest ?? ''} will precache
${config.manifestEntries.length} URLs, totaling ${prettyBytes(size)}.`);
}
}
}

module.exports = GenerateSW;
export {GenerateSW};
Expand Up @@ -6,14 +6,14 @@
https://opensource.org/licenses/MIT.
*/

const GenerateSW = require('./generate-sw');
const InjectManifest = require('./inject-manifest');
import {GenerateSW} from './generate-sw';
import {InjectManifest} from './inject-manifest';

/**
* @module workbox-webpack-plugin
*/

module.exports = {
export {
GenerateSW,
InjectManifest,
};