Skip to content

Commit

Permalink
Upgrade webpack to v4 (#93)
Browse files Browse the repository at this point in the history
- Update loaders and plugins to use the updated webpack interfaces
- Update webpack typings and remove unused typings
- Update tests
- Remove webpack mocks in favor of the actual classes
  • Loading branch information
mwistrand authored Nov 30, 2018
1 parent 0fee8c3 commit b8501f5
Show file tree
Hide file tree
Showing 33 changed files with 1,806 additions and 4,994 deletions.
5,476 changes: 1,428 additions & 4,048 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@
"bfj-node4": "5.2.0",
"chalk": "2.3.0",
"commander": "2.13.0",
"copy-webpack-plugin": "4.0.1",
"copy-webpack-plugin": "4.6.0",
"express": "4.16.2",
"filesize": "3.5.11",
"filter-css": "0.1.2",
"fs-extra": "7.0.0",
"get-port": "4.0.0",
"glob": "^7.1.2",
"gzip-size": "4.1.0",
"html-webpack-include-assets-plugin": "1.0.2",
"html-webpack-include-assets-plugin": "1.0.6",
"http-server": "0.11.1",
"istanbul-lib-instrument": "1.10.1",
"loader-utils": "1.1.0",
Expand All @@ -67,9 +67,9 @@
"puppeteer": "1.10.0",
"recast": "0.12.7",
"source-map": "0.6.1",
"ts-loader": "3.1.1",
"typed-css-modules": "0.3.1",
"workbox-webpack-plugin": "3.2.0"
"ts-loader": "5.3.0",
"typed-css-modules": "0.3.7",
"workbox-webpack-plugin": "3.6.3"
},
"devDependencies": {
"@dojo/scripts": "~3.0.1",
Expand All @@ -86,16 +86,16 @@
"@types/mockery": "1.4.29",
"@types/node": "9.6.5",
"@types/sinon": "~4.3.3",
"@types/tapable": "0.2.5",
"@types/webpack": "3.8.1",
"@types/tapable": "1.0.4",
"@types/webpack": "4.4.19",
"chai": "4.1.2",
"chai-subset": "1.6.0",
"classnames": "2.2.5",
"codecov": "~3.0.4",
"cpx": "~1.5.0",
"css-loader": "0.28.9",
"css-loader": "1.0.1",
"del": "3.0.0",
"exports-loader": "0.6.4",
"exports-loader": "0.7.0",
"husky": "0.14.3",
"lint-staged": "6.0.0",
"mockery": "2.1.0",
Expand All @@ -105,9 +105,9 @@
"shx": "^0.3.2",
"sinon": "~4.5.0",
"stream-combiner2": "1.1.1",
"style-loader": "0.20.1",
"style-loader": "0.23.1",
"typescript": "~2.6.1",
"webpack": "3.8.1"
"webpack": "4.25.1"
},
"lint-staged": {
"*.{ts,tsx}": [
Expand Down
18 changes: 9 additions & 9 deletions src/build-time-render/BuildTimeRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ export interface BuildTimeRenderArguments {
}

export default class BuildTimeRender {
private _paths: any[];
private _useManifest: boolean;
private _manifest: any;
private _entries: string[];
private _root: string;
private _output?: string;
private _cssFiles: string[] = [];
private _useHistory = false;
private _inlinedCssClassNames: string[] = [];
private _entries: string[];
private _head: string;
private _inlinedCssClassNames: string[] = [];
private _manifest: any;
private _output?: string;
private _paths: any[];
private _puppeteerOptions: any;
private _root: string;
private _useHistory = false;
private _useManifest: boolean;

constructor(args: BuildTimeRenderArguments) {
const { paths = [], root = '', useManifest = false, entries, useHistory, puppeteerOptions } = args;
Expand Down Expand Up @@ -149,7 +149,7 @@ export default class BuildTimeRender {
if (!this._root) {
return;
}
compiler.plugin('after-emit', async (compilation, callback) => {
compiler.hooks.afterEmit.tap(this.constructor.name, async (compilation, callback) => {
this._output = compiler.options.output && compiler.options.output.path;
if (!this._output) {
return Promise.resolve().then(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/css-module-decorator-loader/loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import webpack = require('webpack');
import { join, basename } from 'path';
import { existsSync } from 'fs';
import * as webpack from 'webpack';

const themeKey = ' _key';

Expand All @@ -9,7 +9,7 @@ const packageJsonPath = join(basePath, 'package.json');
const packageJson = existsSync(packageJsonPath) ? require(packageJsonPath) : {};
const packageName = packageJson.name || '';

export default function(this: webpack.LoaderContext, content: string, map?: any): string {
export default function(this: webpack.loader.LoaderContext, content: string, map?: any): string {
let response = content;
const localsRexExp = /exports.locals = {([.\s\S]*)};/;
const matches = content.match(localsRexExp);
Expand Down
12 changes: 6 additions & 6 deletions src/css-module-dts-loader/loader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import webpack = require('webpack');
import { createSourceFile, forEachChild, Node, ScriptTarget, SyntaxKind } from 'typescript';
import { statSync } from 'fs';
import { dirname } from 'path';
import { createSourceFile, forEachChild, Node, ScriptTarget, SyntaxKind } from 'typescript';
import * as webpack from 'webpack';
const DtsCreator = require('typed-css-modules');
const { getOptions } = require('loader-utils');
const instances = require('ts-loader/dist/instances');
Expand Down Expand Up @@ -39,7 +39,7 @@ function generateDTSFile(filePath: string, sourceFilesRegex: RegExp): Promise<vo
});
}

function getCssImport(node: Node, loaderContext: webpack.LoaderContext): Promise<string> | void {
function getCssImport(node: Node, loaderContext: webpack.loader.LoaderContext): Promise<string> | void {
if (node.kind === SyntaxKind.StringLiteral) {
const importPath = node.getText().replace(/\'|\"/g, '');
if (/\.css$/.test(importPath)) {
Expand All @@ -62,7 +62,7 @@ function getCssImport(node: Node, loaderContext: webpack.LoaderContext): Promise
function traverseNode(
node: Node,
filePaths: Promise<string>[],
loaderContext: webpack.LoaderContext
loaderContext: webpack.loader.LoaderContext
): Promise<string>[] {
switch (node.kind) {
case SyntaxKind.SourceFile:
Expand All @@ -80,8 +80,8 @@ function traverseNode(
return filePaths;
}

export default function(this: webpack.LoaderContext, content: string, sourceMap?: string) {
const callback = this.async();
export default function(this: webpack.loader.LoaderContext, content: string, sourceMap?: string) {
const callback = this.async() as Function;
const { type = 'ts', instanceName, sourceFilesPattern = /src[\\\/]/ }: LoaderArgs = getOptions(this);
const sourceFilesRegex =
typeof sourceFilesPattern === 'string' ? new RegExp(sourceFilesPattern) : sourceFilesPattern;
Expand Down
28 changes: 13 additions & 15 deletions src/css-module-plugin/CssModulePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { existsSync } from 'fs';
import { normalize, sep, isAbsolute, resolve } from 'path';
import { Compiler, NormalModuleReplacementPlugin } from 'webpack';
import NormalModuleFactory = require('webpack/lib/NormalModuleFactory');

/**
* Test whether a module ID is relative or absolute.
Expand All @@ -25,20 +24,19 @@ export default class CssModulePlugin {
}

apply(compiler: Compiler) {
compiler.apply(
new NormalModuleReplacementPlugin(/\.m\.css$/, (result: NormalModuleFactory.BeforeData) => {
if (isAbsolute(result.request)) {
return;
}
const requestFileName = isRelative(result.request)
? resolve(result.context, result.request)
: resolve(this.basePath, 'node_modules', result.request);
const jsFileName = requestFileName + '.js';
const nmrPlugin = new NormalModuleReplacementPlugin(/\.m\.css$/, (result: any) => {
if (isAbsolute(result.request)) {
return;
}
const requestFileName = isRelative(result.request)
? resolve(result.context, result.request)
: resolve(this.basePath, 'node_modules', result.request);
const jsFileName = requestFileName + '.js';

if (existsSync(jsFileName)) {
result.request = result.request.replace(/\.m\.css$/, '.m.css.js');
}
})
);
if (existsSync(jsFileName)) {
result.request = result.request.replace(/\.m\.css$/, '.m.css.js');
}
});
nmrPlugin.apply(compiler);
}
}
44 changes: 22 additions & 22 deletions src/external-loader-plugin/ExternalLoaderPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,29 @@ export default class ExternalLoaderPlugin {
[] as string[]
);

compiler.apply(
new CopyWebpackPlugin(
this._dependencies.reduce(
(config, dependency) =>
typeof dependency === 'string' || !dependency.from
? config
: config.concat([
{
from: `${dependency.from}`,
to: prefixPath(dependency.to || dependency.from)
}
]),
[] as { from: string; to: string; transform?: Function }[]
)
const copyPlugin = new CopyWebpackPlugin(
this._dependencies.reduce(
(config, dependency) =>
typeof dependency === 'string' || !dependency.from
? config
: config.concat([
{
from: `${dependency.from}`,
to: prefixPath(dependency.to || dependency.from)
}
]),
[] as { from: string; to: string; transform?: Function }[]
)
);
compiler.apply(
new HtmlWebpackIncludeAssetsPlugin({
assets: toInject,
append: false,
files: `${this._pathPrefix}index.html`,
hash: this._hash
})
);

const htmlPlugin = new HtmlWebpackIncludeAssetsPlugin({
assets: toInject,
append: false,
files: `${this._pathPrefix}index.html`,
hash: this._hash
});

copyPlugin.apply(compiler);
htmlPlugin.apply(compiler);
}
}
25 changes: 13 additions & 12 deletions src/i18n-plugin/I18nPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,26 @@ export default class I18nPlugin {
apply(compiler: Compiler) {
const { defaultLocale, supportedLocales = [] } = this;

compiler.apply(
new DefinePlugin({
__defaultLocale__: `'${defaultLocale}'`,
__supportedLocales__: JSON.stringify(supportedLocales),
__cldrData__: JSON.stringify(this._loadCldrData())
})
);
const definePlugin = new DefinePlugin({
__defaultLocale__: `'${defaultLocale}'`,
__supportedLocales__: JSON.stringify(supportedLocales),
__cldrData__: JSON.stringify(this._loadCldrData())
});
definePlugin.apply(compiler);

compiler.plugin('compilation', (compilation, params) => {
compiler.hooks.compilation.tap(this.constructor.name, (compilation, params) => {
compilation.dependencyFactories.set(InjectedModuleDependency as any, params.normalModuleFactory);
compilation.dependencyTemplates.set(
InjectedModuleDependency as any,
new InjectedModuleDependency.Template()
// `@types/webpack` defines `Compilation#dependencyTemplates` as `Map<typeof Dependency, Tapable>`,
// which is incorrect. The templates used throughout webpack do *not* extend Tapable.
new InjectedModuleDependency.Template() as any
);

compilation.plugin('succeed-module', (module: NormalModule) => {
if (this.target.test(module.resource)) {
compilation.hooks.succeedModule.tap(this.constructor.name, (module) => {
if (this.target.test((module as NormalModule).resource)) {
const dep = new InjectedModuleDependency(join(__dirname, './templates/setLocaleData.js'));
module.addDependency(dep);
(module as NormalModule).addDependency(dep);
}
});
});
Expand Down
65 changes: 32 additions & 33 deletions src/service-worker-plugin/ServiceWorkerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,39 +104,38 @@ export default class ServiceWorkerPlugin {
return precacheProperties;
}, Object.create(null));

compiler.apply(
new GenerateSW(
this._getDefinedOptions({
...precacheProperties,
cacheId: cachePrefix,
chunks: bundles,
clientsClaim,
excludeChunks: excludeBundles,
importScripts,
importWorkboxFrom: 'local',
skipWaiting,
runtimeCaching: routes.map((route) => {
const { options = {}, strategy, urlPattern } = route;
const { cacheName, cacheableResponse, expiration, networkTimeoutSeconds } = options;

if (!urlPattern || !strategy) {
throw new Error('Each route must have both a `urlPattern` and `strategy`');
}

return {
urlPattern: new RegExp(urlPattern),
handler: strategy,
options: this._getDefinedOptions({
cacheName,
cacheableResponse,
expiration,
networkTimeoutSeconds
})
};
})
const generateSW = new GenerateSW(
this._getDefinedOptions({
...precacheProperties,
cacheId: cachePrefix,
chunks: bundles,
clientsClaim,
excludeChunks: excludeBundles,
importScripts,
importWorkboxFrom: 'local',
skipWaiting,
runtimeCaching: routes.map((route) => {
const { options = {}, strategy, urlPattern } = route;
const { cacheName, cacheableResponse, expiration, networkTimeoutSeconds } = options;

if (!urlPattern || !strategy) {
throw new Error('Each route must have both a `urlPattern` and `strategy`');
}

return {
urlPattern: new RegExp(urlPattern),
handler: strategy,
options: this._getDefinedOptions({
cacheName,
cacheableResponse,
expiration,
networkTimeoutSeconds
})
};
})
)
})
);
generateSW.apply(compiler);
}

/**
Expand All @@ -150,8 +149,8 @@ export default class ServiceWorkerPlugin {
throw new Error('The service worker path must be a non-empty string');
}

compiler.plugin('before-run', (compiler, next) => {
compiler.apply(new CopyWebpackPlugin({ from: this._serviceWorker }));
compiler.hooks.beforeRun.tapAsync(this.constructor.name, (compiler, next) => {
new CopyWebpackPlugin({ from: this._serviceWorker }).apply(compiler);
next();
});
}
Expand Down
10 changes: 7 additions & 3 deletions src/static-build-loader/loader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import getFeatures from './getFeatures';
import { LoaderContext, RawSourceMap } from 'webpack';
import * as webpack from 'webpack';
import * as recast from 'recast';
import { ExpressionStatement, BaseNode } from 'estree';

Expand Down Expand Up @@ -67,7 +67,11 @@ function setComment<T>(
* @param content The JavaScript code to optimize
* @param sourceMap Optional Source map for the code. If provided it will be updated to reflect the optimizations made
*/
export default function loader(this: LoaderContext, content: string, sourceMap?: RawSourceMap): string | void {
export default function loader(
this: webpack.loader.LoaderContext,
content: string,
sourceMap?: webpack.RawSourceMap
): string | void {
if (content.indexOf('/has') < 0 && content.indexOf('has(') < 0) {
if (sourceMap) {
this.callback(null, content, sourceMap);
Expand Down Expand Up @@ -294,7 +298,7 @@ export default function loader(this: LoaderContext, content: string, sourceMap?:
sourceMap,
result.map
);
this.callback(null, result.code, map, ast);
this.callback(null, result.code, map);
return;
}
return recast.print(ast).code;
Expand Down
Loading

0 comments on commit b8501f5

Please sign in to comment.