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 support for webpack v5 #83

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fb7781c
Upgrade to webpack v5.0.0
jayaddison Oct 11, 2020
a66eb15
Typing: Plugin -> WebpackPluginInstance
jayaddison Oct 11, 2020
c6d0528
Typing: use WebpackError type definition from webpack
jayaddison Oct 11, 2020
ef3582e
Typing: update exit promise resolution handler
jayaddison Oct 11, 2020
0f33cf2
Typing: Use upstream Chunk, Module types from webpack, and adhere to …
jayaddison Oct 11, 2020
a23607c
Update to use new ChunkGraph, ModuleGraph APIs
jayaddison Oct 11, 2020
4790470
Add Travis build env definition for webpack v5
jayaddison Oct 11, 2020
bb9674f
Update yarn.lock
jayaddison Oct 11, 2020
21d9bc0
Merge branch 'master' into upgrades/webpack-5
jayaddison Oct 19, 2020
90b4b07
Revert "Typing: update exit promise resolution handler"
jayaddison Oct 19, 2020
601a919
Treat chunk.files as a Set
jayaddison Oct 19, 2020
60f82a1
Remove Travis build env definitions for webpack v4
jayaddison Oct 19, 2020
f59957b
Merge branch 'master' into upgrades/webpack-5
jayaddison Oct 29, 2020
986535f
Revert "Revert "Typing: update exit promise resolution handler""
jayaddison Oct 29, 2020
a820379
Bump required dependencies
skjnldsv Nov 14, 2020
5d9914e
Remove unnecessary write-file-webpack-plugin
skjnldsv Nov 14, 2020
80ed9a9
Fix assert polyfill requirements
skjnldsv Nov 14, 2020
10cfbce
Make sure we have a valid error message
skjnldsv Nov 14, 2020
d57d9ef
Remove test:file script
jayaddison Nov 19, 2020
59feadb
Fixup: determine moduleId on a per-module basis
jayaddison Dec 1, 2020
3ff335e
Adjust test runner callback handling
jayaddison Dec 14, 2020
9255dba
Revert "Make sure we have a valid error message"
jayaddison Dec 14, 2020
7932938
Revert ensureWebpackErrors implementation changes
jayaddison Dec 14, 2020
712ebdb
Restore webpackStats argument to WEBPACK_READY_EVENT emissions
jayaddison Dec 14, 2020
29d77f2
fix exit code build problem for watch return type
verasztol Feb 6, 2021
10ad998
Merge pull request #2 from verasztol/upgrades/webpack-5
jayaddison Feb 7, 2021
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
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ install:
- yarn install --immutable

env:
- WEBPACK_VERSION=4 MOCHA_VERSION=6
- WEBPACK_VERSION=4 MOCHA_VERSION=7
- WEBPACK_VERSION=4 MOCHA_VERSION=8
- WEBPACK_VERSION=5 MOCHA_VERSION=7
- WEBPACK_VERSION=5 MOCHA_VERSION=8

before_script:
- "yarn add -D webpack@$WEBPACK_VERSION"
Expand Down
15 changes: 7 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"license": "MIT",
"peerDependencies": {
"mocha": ">=6 <9",
"webpack": "^4.0.0"
"webpack": "^5.0.0"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
Expand All @@ -66,11 +66,11 @@
"@types/node": "^12.12.17",
"@types/sinon": "^9.0.0",
"@types/sinon-chai": "^3.2.4",
"@types/webpack": "^4.41.0",
"@types/yargs": "^15.0.4",
"@typescript-eslint/eslint-plugin": "^2.11.0",
"@typescript-eslint/parser": "^2.11.0",
"anymatch": "3.1.1",
"assert": "^2.0.0",
"babel-eslint": "^9.0.0",
"babel-loader": "^8.0.0",
"babel-plugin-istanbul": "4.1.6",
Expand All @@ -79,11 +79,11 @@
"chai": "^4.1.0",
"coffee-script": "^1.11.1",
"cross-env": "6.0.3",
"css-loader": "3.2.0",
"css-loader": "^5.0.1",
"del": "5.1.0",
"del-cli": "3.0.0",
"eslint": "^6.7.2",
"eslint-config-airbnb-base": "12.1.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-import": "^2.9.0",
"fs-extra": "5.0.0",
Expand All @@ -99,16 +99,15 @@
"np": "5.1.0",
"nyc": "14.1.1",
"prettier": "^1.19.1",
"sass-loader": "6.0.7",
"sass-loader": "^10.1.0",
"sinon": "^9.0.2",
"sinon-chai": "^3.5.0",
"strip-ansi": "^5.2.0",
"tiny-worker": "2.3.0",
"ts-mocha": "^7.0.0",
"typescript": "^3.8.3",
"webpack": "4.41.0",
"worker-loader": "2.0.0",
"write-file-webpack-plugin": "^4.2.0"
"webpack": "5.0.0",
"worker-loader": "^3.0.5"
},
"dependencies": {
"@babel/runtime-corejs2": "^7.0.0",
Expand Down
4 changes: 2 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ async function cli() {
}
return mochaWebpack.run()
})
.then((failures: number) => {
exit(cliOptions.mocha.cli.exit, failures)
.then(() => {
exit(cliOptions.mocha.cli.exit, 0)
})
.catch((e: Error) => {
if (e) console.error(e.stack) // eslint-disable-line
Expand Down
8 changes: 4 additions & 4 deletions src/runner/TestRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ export default class TestRunner extends EventEmitter {
failures = await new Promise((resolve, reject) => {
registerReadyCallback(
compiler,
(err: (Error | string) | null, webpackStats: Stats | null) => {
this.emit(WEBPACK_READY_EVENT, err, webpackStats)
(err: Error, webpackStats: Stats) => {
this.emit(WEBPACK_READY_EVENT, err)
if (err || !webpackStats) {
reject()
return
Expand Down Expand Up @@ -216,8 +216,8 @@ export default class TestRunner extends EventEmitter {
// register webpack ready callback
registerReadyCallback(
compiler,
(err: (Error | string) | null, webpackStats: Stats | null) => {
this.emit(WEBPACK_READY_EVENT, err, webpackStats)
(err: Error, webpackStats: Stats) => {
this.emit(WEBPACK_READY_EVENT, err, null)
if (err) {
// wait for fixed tests
return
Expand Down
4 changes: 2 additions & 2 deletions src/runner/runnerUtils/createWebpackConfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
has as _has,
merge as _merge
} from 'lodash'
import { Configuration, Plugin, RuleSetRule } from 'webpack'
import { Configuration, WebpackPluginInstance, RuleSetRule } from 'webpack'
import { glob } from '../../../util/glob'
import { EntryConfig } from '../../../webpack/loader/entryLoader'
import { buildProgressPlugin } from '../../../webpack/plugin/buildProgressPlugin'
Expand Down Expand Up @@ -48,7 +48,7 @@ const getPublicPath = (
const buildPluginsArray = (
webpackConfig: Configuration,
interactive: boolean
): Plugin[] => {
): WebpackPluginInstance[] => {
const plugins = webpackConfig.plugins || []

if (interactive) {
Expand Down
4 changes: 2 additions & 2 deletions src/runner/runnerUtils/createWebpackConfig/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Configuration, Plugin, RuleSetRule } from 'webpack'
import { Configuration, WebpackPluginInstance, RuleSetRule } from 'webpack'
import { EntryConfig } from '../../../webpack/loader/entryLoader'

export interface CreateWebpackConfigOptions {
Expand All @@ -19,7 +19,7 @@ export interface BuildLoaderRulesOptions extends CreateWebpackConfigOptions {
export interface BuildWebpackConfigOptions extends BuildLoaderRulesOptions {
loaderRules: RuleSetRule[]
outputPath: string
plugins: Plugin[]
plugins: WebpackPluginInstance[]
publicPath: string
}

Expand Down
6 changes: 3 additions & 3 deletions src/webpack/compiler/registerReadyCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { MOCHAPACK_NAME } from '../../util/constants'

export default function registerReadyCallback(
compiler: Compiler,
cb: (err: (Error | string) | null, stats: Stats | null) => void
) {
compiler.hooks.failed.tap(MOCHAPACK_NAME, cb)
cb: (err: Error, stats: Stats) => void
) {
compiler.hooks.failed.tap(MOCHAPACK_NAME, (error: Error) => cb(error, null))
compiler.hooks.done.tap(MOCHAPACK_NAME, (stats: Stats) => {
if (stats.hasErrors()) {
const jsonStats = stats.toJson()
Expand Down
11 changes: 2 additions & 9 deletions src/webpack/util/createStatsFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { EOL } from 'os'
import chalk from 'chalk'
import { Stats } from 'webpack'
import RequestShortener from 'webpack/lib/RequestShortener'
import WebpackError from 'webpack/lib/WebpackError'
import { formatErrorMessage, stripLoaderFromPath } from './formatUtil'
import { WebpackError } from '../types'

const createGetFile = (requestShortener: RequestShortener) => (
e: WebpackError
Expand All @@ -29,14 +29,7 @@ const createGetFile = (requestShortener: RequestShortener) => (
const ensureWebpackErrors = (
errors: Array<string | WebpackError>
): Array<WebpackError> =>
errors.map((e: string | WebpackError) => {
/* istanbul ignore if */
if (typeof e === 'string') {
// webpack does this also, so there must be case when this happens
return ({ message: e } as any) as WebpackError
}
return e
})
errors.map((e: WebpackError) => e.toString())

const prependWarning = (message: string) =>
`${chalk.yellow('Warning')} ${message}`
Expand Down
81 changes: 48 additions & 33 deletions src/webpack/util/getAffectedModuleIds.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Module, Chunk } from '../types'
import Chunk from 'webpack/lib/Chunk'
import ChunkGraph from 'webpack/lib/ChunkGraph'
import Module from 'webpack/lib/Module'
import ModuleGraph from 'webpack/lib/ModuleGraph'

type ModuleMap = {
[key: string]: Module
Expand All @@ -11,6 +14,7 @@ const isBuilt = (module: Module): boolean => module.built
const getId = (module: any): number | string => module.id

const affectedModules = (
chunkGraph: ChunkGraph,
map: ModuleMap,
usageMap: ModuleUsageMap,
affected: ModuleMap,
Expand All @@ -22,13 +26,13 @@ const affectedModules = (
}
// module is identified as affected by this function call
const module = map[moduleId]
affected[module.id] = module // eslint-disable-line no-param-reassign
affected[moduleId] = module // eslint-disable-line no-param-reassign

// next we need to mark all usages aka parents also as affected
const usages = usageMap[module.id]
const usages = usageMap[moduleId]
if (typeof usages !== 'undefined') {
const ids = Object.keys(usages)
ids.forEach((id: string) => affectedModules(map, usageMap, affected, id))
ids.forEach((id: string) => affectedModules(chunkGraph, map, usageMap, affected, id))
}
}

Expand All @@ -38,9 +42,9 @@ const affectedModules = (
* [moduleId]: Module
* }
*/
const buildModuleMap = (modules: Array<Module>): ModuleMap => {
const moduleMap = modules.reduce(
(memo, module: Module) => ({ ...memo, [module.id]: module }),
const buildModuleMap = (chunkGraph: ChunkGraph, modules: Set<Module>): ModuleMap => {
const moduleMap = Array.from(modules).reduce(
(memo, module: Module) => ({ ...memo, [chunkGraph.getModuleId(module)]: module }),
{}
)
return moduleMap
Expand All @@ -55,12 +59,15 @@ const buildModuleMap = (modules: Array<Module>): ModuleMap => {
* }
* }
*
* @param modules Array<number>
* @param chunks Set<Chunk>
* @param modules Set<Module>
* @return ModuleUsageMap
*/
const buildModuleUsageMap = (
chunks: Array<Chunk>,
modules: Array<Module>
chunks: Set<Chunk>,
chunkGraph: ChunkGraph,
modules: Set<Module>,
moduleGraph: ModuleGraph
): ModuleUsageMap => {
// build a map of all modules with their parent
// {
Expand All @@ -69,18 +76,20 @@ const buildModuleUsageMap = (
// }
// }
//
const moduleUsageMap: ModuleUsageMap = modules.reduce(
const moduleUsageMap: ModuleUsageMap = Array.from(modules).reduce(
(memo, module: Module) => {
module.dependencies.forEach(dependency => {
const dependentModule = dependency.module
const dependentModule = moduleGraph.getModule(dependency)

if (!dependentModule) {
return
}
if (typeof memo[dependentModule.id] === 'undefined') {
memo[dependentModule.id] = {} // eslint-disable-line no-param-reassign
const dependentModuleId = chunkGraph.getModuleId(dependentModule)
if (typeof memo[dependentModuleId] === 'undefined') {
memo[dependentModuleId] = {} // eslint-disable-line no-param-reassign
}
memo[dependentModule.id][module.id] = module // eslint-disable-line no-param-reassign
const moduleId = chunkGraph.getModuleId(module)
memo[dependentModuleId][moduleId] = module // eslint-disable-line no-param-reassign
})
return memo
},
Expand All @@ -93,14 +102,15 @@ const buildModuleUsageMap = (
// [moduleId]: Module
// }
// }
const chunkModuleMap: ModuleUsageMap = chunks.reduce((memo, chunk: Chunk) => {
const chunkModuleMap: ModuleUsageMap = Array.from(chunks).reduce((memo, chunk: Chunk) => {
// build chunk map first to get also empty chunks (without modules)
memo[chunk.id] = {} // eslint-disable-line no-param-reassign
return memo
}, {})
modules.reduce((memo, module: Module) => {
module.getChunks().forEach((chunk: Chunk) => {
memo[chunk.id][module.id] = module // eslint-disable-line no-param-reassign
Array.from(modules).reduce((memo, module: Module) => {
chunkGraph.getModuleChunksIterable(module).forEach((chunk: Chunk) => {
const moduleId = chunkGraph.getModuleId(module)
memo[chunk.id][moduleId] = module // eslint-disable-line no-param-reassign
})
return memo
}, chunkModuleMap)
Expand All @@ -115,10 +125,12 @@ const buildModuleUsageMap = (
// and mark all modules of this chunk as a direct dependency of the original module
Object.values(chunkModuleMap[chunkId] as ModuleMap).forEach(
(childModule: any) => {
if (typeof moduleUsageMap[childModule.id] === 'undefined') {
moduleUsageMap[childModule.id] = {}
const childModuleId = chunkGraph.getModuleId(childModule)
if (typeof moduleUsageMap[childModuleId] === 'undefined') {
moduleUsageMap[childModuleId] = {}
}
moduleUsageMap[childModule.id][module.id] = module
const moduleId = chunkGraph.getModuleId(module)
moduleUsageMap[childModuleId][moduleId] = module
}
)
})
Expand All @@ -133,22 +145,25 @@ const buildModuleUsageMap = (
* - affected directly by a file change
* - affected indirectly by a change of it's dependencies and so on
*
* @param chunks Array<Chunk>
* @param modules Array<Module>
* @param chunks Set<Chunk>
* @param modules Set<Module>
* @return {Array.<number>}
*/
export default function getAffectedModuleIds(
chunks: Array<Chunk>,
modules: Array<Module>
chunks: Set<Chunk>,
chunkGraph: ChunkGraph,
modules: Set<Module>,
moduleGraph: ModuleGraph
): Array<number | string> {
const moduleMap: ModuleMap = buildModuleMap(modules)
const moduleUsageMap: ModuleUsageMap = buildModuleUsageMap(chunks, modules)
const moduleMap: ModuleMap = buildModuleMap(chunkGraph, modules)
const moduleUsageMap: ModuleUsageMap = buildModuleUsageMap(chunks, chunkGraph, modules, moduleGraph)

const builtModules = modules.filter(isBuilt)
const builtModules = Array.from(modules).filter(isBuilt)
const affectedMap: ModuleMap = {}
builtModules.forEach((module: Module) =>
affectedModules(moduleMap, moduleUsageMap, affectedMap, module.id)
)
builtModules.forEach((module: Module) => {
const moduleId: string = chunkGraph.getModuleId(module)
affectedModules(chunkGraph, moduleMap, moduleUsageMap, affectedMap, moduleId)
})

return Object.values(affectedMap).map(getId)
return Object.values(affectedMap).map(chunkGraph.getModuleId)
}
17 changes: 9 additions & 8 deletions src/webpack/util/getBuildStats.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import path from 'path'
import { Stats } from 'webpack'
import Chunk from 'webpack/lib/Chunk'
import Module from 'webpack/lib/Module'
import sortChunks from './sortChunks'
import getAffectedModuleIds from './getAffectedModuleIds'
import { Chunk, Module } from '../types'

export type BuildStats = {
affectedModules: Array<number | string>
Expand All @@ -14,17 +15,17 @@ export default function getBuildStats(
stats: Stats,
outputPath: string
): BuildStats {
const { chunks, chunkGroups, modules } = stats.compilation
const { chunks, chunkGraph, chunkGroups, modules, moduleGraph } = stats.compilation

const sortedChunks = sortChunks(chunks, chunkGroups)
const affectedModules = getAffectedModuleIds(chunks, modules)
const affectedModules = getAffectedModuleIds(chunks, chunkGraph, modules, moduleGraph)

const entries = []
const js = []
const pathHelper = f => path.join(outputPath, f)

sortedChunks.forEach((chunk: Chunk) => {
const files = Array.isArray(chunk.files) ? chunk.files : [chunk.files]
const files = Array.from(chunk.files)

if (chunk.isOnlyInitial()) {
// only entry files
Expand All @@ -33,11 +34,11 @@ export default function getBuildStats(
}

if (
chunk
.getModules()
.some((module: Module) => affectedModules.indexOf(module.id) !== -1)
chunkGraph
.getChunkModules(chunk)
.some((module: Module) => affectedModules.indexOf(chunkGraph.getModuleId(module)) !== -1)
) {
files.forEach(file => {
files.forEach((file: string) => {
if (/\.js$/.test(file)) {
js.push(file)
}
Expand Down
Loading