From 45c5c21738dd79cf0edaf9c45affed9f1726c17e Mon Sep 17 00:00:00 2001 From: Henry Heino Date: Fri, 29 Jul 2022 21:45:31 -0700 Subject: [PATCH] Mobile: Migrate from rollup to webpack Rollup was having trouble importing TypeScript from other packages in the repo. See https://github.com/rollup/plugins/issues/1083 and https://github.com/rollup/plugins/issues/287 --- packages/app-mobile/package.json | 7 +- packages/app-mobile/tools/buildInjectedJs.ts | 187 +++++++++------- yarn.lock | 212 +++++++++++-------- 3 files changed, 233 insertions(+), 173 deletions(-) diff --git a/packages/app-mobile/package.json b/packages/app-mobile/package.json index 268c700440f..a7d9f7b69ff 100644 --- a/packages/app-mobile/package.json +++ b/packages/app-mobile/package.json @@ -89,8 +89,6 @@ "@codemirror/view": "^6.0.0", "@joplin/tools": "~2.9", "@lezer/highlight": "^1.0.0", - "@rollup/plugin-node-resolve": "^13.0.0", - "@rollup/plugin-typescript": "^8.2.1", "@types/jest": "^28.1.3", "@types/react-native": "^0.64.4", "babel-plugin-module-resolver": "^4.1.0", @@ -102,9 +100,10 @@ "jetifier": "^1.6.5", "metro-react-native-babel-preset": "^0.66.2", "nodemon": "^2.0.12", - "rollup": "^2.53.1", "ts-jest": "^28.0.5", + "ts-loader": "^9.3.1", "typescript": "^4.0.5", - "uglify-js": "^3.13.10" + "uglify-js": "^3.13.10", + "webpack": "^5.74.0" } } diff --git a/packages/app-mobile/tools/buildInjectedJs.ts b/packages/app-mobile/tools/buildInjectedJs.ts index a69492edf2b..9cc66da853a 100644 --- a/packages/app-mobile/tools/buildInjectedJs.ts +++ b/packages/app-mobile/tools/buildInjectedJs.ts @@ -7,21 +7,15 @@ import { mkdirp, readFile, writeFile } from 'fs-extra'; import { dirname, extname, basename } from 'path'; const execa = require('execa'); -import { OutputOptions, rollup, RollupOptions, watch as rollupWatch } from 'rollup'; -import typescript from '@rollup/plugin-typescript'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; +import webpack from 'webpack'; const rootDir = dirname(dirname(dirname(__dirname))); const mobileDir = `${rootDir}/packages/app-mobile`; const outputDir = `${mobileDir}/lib/rnInjectedJs`; -/** - * Stores the contents of the file at [filePath] as an importable string. - * - * @param name the name (excluding the .js extension) of the output file that will contain - * the JSON-ified file content - * @param filePath Path to the file to JSON-ify. - */ +// Stores the contents of the file at [filePath] as an importable string. +// [name] should be the name (excluding the .js extension) of the output file that will contain +// the JSON-ified file content. async function copyJs(name: string, filePath: string) { const outputPath = `${outputDir}/${name}.js`; console.info(`Creating: ${outputPath}`); @@ -47,28 +41,43 @@ class BundledFile { this.bundleMinifiedPath = `${this.rootFileDirectory}/${this.bundleBaseName}.bundle.min.js`; } - private getRollupOptions(): [RollupOptions, OutputOptions] { - const rollupInputOptions: RollupOptions = { - input: this.sourceFilePath, - plugins: [ - typescript({ - // Exclude all .js files. Rollup will attempt to import a .js - // file if both a .ts and .js file are present, conflicting - // with our build setup. See - // https://discourse.joplinapp.org/t/importing-a-ts-file-from-a-rollup-bundled-ts-file/ - exclude: `${this.rootFileDirectory}/**/*.js`, - }), - nodeResolve(), - ], - }; - - const rollupOutputOptions: OutputOptions = { - format: 'iife', - name: this.bundleName, - file: this.bundleOutputPath, + private getWebpackOptions(mode: 'production' | 'development'): webpack.Configuration { + const config: webpack.Configuration = { + mode, + entry: this.sourceFilePath, + output: { + path: this.rootFileDirectory, + filename: `${this.bundleBaseName}.bundle.js`, + + library: { + type: 'window', + name: this.bundleName, + }, + }, + // See https://webpack.js.org/guides/typescript/ + module: { + rules: [ + { + // Include .tsx to include react components + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + // Increase the minimum size required + // to trigger warnings. + // See https://stackoverflow.com/a/53517149/17055750 + performance: { + maxAssetSize: 2_000_000, // 2-ish MiB + maxEntrypointSize: 2_000_000, + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, }; - return [rollupInputOptions, rollupOutputOptions]; + return config; } private async uglify() { @@ -81,62 +90,89 @@ class BundledFile { ]); } - /** - * Create a minified JS file in the same directory as `this.sourceFilePath` with - * the same name. - */ - public async build() { - const [rollupInputOptions, rollupOutputOptions] = this.getRollupOptions(); + private handleErrors(err: Error | undefined | null, stats: webpack.Stats | undefined): boolean { + let failed = false; + + if (err) { + console.error(`Error: ${err.name}`, err.message, err.stack); + failed = true; + } else if (stats?.hasErrors() || stats?.hasWarnings()) { + const data = stats.toJson(); + + if (data.warnings && data.warningsCount) { + console.warn('Warnings: ', data.warningsCount); + for (const warning of data.warnings) { + // Stack contains the message + if (warning.stack) { + console.warn(warning.stack); + } else { + console.warn(warning.message); + } + } + } + if (data.errors && data.errorsCount) { + console.error('Errors: ', data.errorsCount); + for (const error of data.errors) { + if (error.stack) { + console.error(error.stack); + } else { + console.error(error.message); + } + console.error(); + } - console.info(`Building bundle: ${this.bundleName}...`); - const bundle = await rollup(rollupInputOptions); - await bundle.write(rollupOutputOptions); + failed = true; + } + } - await this.uglify(); + return failed; } - public async startWatching() { - const [rollupInputOptions, rollupOutputOptions] = this.getRollupOptions(); - const watcher = rollupWatch({ - ...rollupInputOptions, - output: [rollupOutputOptions], - watch: { - exclude: [ - `${mobileDir}/node_modules/`, - ], - }, + // Create a minified JS file in the same directory as `this.sourceFilePath` with + // the same name. + public build() { + const compiler = webpack(this.getWebpackOptions('production')); + return new Promise((resolve, reject) => { + console.info(`Building bundle: ${this.bundleName}...`); + + compiler.run((err, stats) => { + let failed = this.handleErrors(err, stats); + + // Clean up. + compiler.close(async (error) => { + if (error) { + console.error('Error cleaning up:', error); + failed = true; + } + if (!failed) { + await this.uglify(); + resolve(); + } else { + reject(); + } + }); + }); }); + } + + public startWatching() { + const compiler = webpack(this.getWebpackOptions('development')); + const watchOptions = { + ignored: '**/node_modules', + }; - watcher.on('event', async event => { - if (event.code === 'BUNDLE_END') { + console.info('Watching bundle: ', this.bundleName); + compiler.watch(watchOptions, async (err, stats) => { + const failed = this.handleErrors(err, stats); + if (!failed) { await this.uglify(); await this.copyToImportableFile(); - console.info(`☑ Bundled ${this.bundleName}!`); - - // Let plugins clean up - await event.result.close(); - } else if (event.code === 'ERROR') { - console.error(event.error); - - // Clean up any bundle-related resources - if (event.result) { - await event.result?.close(); - } - } else if (event.code === 'END') { - console.info('Done bundling.'); - } else if (event.code === 'START') { - console.info('Starting bundler...'); } }); - - // We're done configuring the watcher - watcher.close(); } - /** - * Creates a file that can be imported by React native. This file contains the - * bundled JS as a string. - */ + // Creates a file that can be imported by React native. This file contains the + // bundled JS as a string. public async copyToImportableFile() { await copyJs(`${this.bundleBaseName}.bundle`, this.bundleMinifiedPath); } @@ -166,7 +202,8 @@ export async function buildInjectedJS() { export async function watchInjectedJS() { // Watch for changes for (const file of bundledFiles) { - void(file.startWatching()); + file.startWatching(); } } + diff --git a/yarn.lock b/yarn.lock index 002fa75ca54..88a450a29d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3821,8 +3821,6 @@ __metadata: "@react-native-community/netinfo": ^6.0.0 "@react-native-community/push-notification-ios": ^1.6.0 "@react-native-community/slider": ^3.0.3 - "@rollup/plugin-node-resolve": ^13.0.0 - "@rollup/plugin-typescript": ^8.2.1 "@types/jest": ^28.1.3 "@types/react-native": ^0.64.4 assert-browserify: ^2.0.0 @@ -3871,16 +3869,17 @@ __metadata: react-redux: 5.0.7 redux: 4.0.0 rn-fetch-blob: ^0.12.0 - rollup: ^2.53.1 stream: 0.0.2 stream-browserify: ^3.0.0 string-natural-compare: ^2.0.2 timers: ^0.1.1 ts-jest: ^28.0.5 + ts-loader: ^9.3.1 typescript: ^4.0.5 uglify-js: ^3.13.10 url: ^0.11.0 valid-url: ^1.0.9 + webpack: ^5.74.0 languageName: unknown linkType: soft @@ -5709,49 +5708,6 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-node-resolve@npm:^13.0.0": - version: 13.0.6 - resolution: "@rollup/plugin-node-resolve@npm:13.0.6" - dependencies: - "@rollup/pluginutils": ^3.1.0 - "@types/resolve": 1.17.1 - builtin-modules: ^3.1.0 - deepmerge: ^4.2.2 - is-module: ^1.0.0 - resolve: ^1.19.0 - peerDependencies: - rollup: ^2.42.0 - checksum: da304025ca898f3ad70e3a24d788634298f2ca6e139517adff43f27ea9cf821af3ee3530ca6f8abaf7e697294b59803837cd8f0ec22e3b1d34d3411c39e9a32c - languageName: node - linkType: hard - -"@rollup/plugin-typescript@npm:^8.2.1": - version: 8.3.0 - resolution: "@rollup/plugin-typescript@npm:8.3.0" - dependencies: - "@rollup/pluginutils": ^3.1.0 - resolve: ^1.17.0 - peerDependencies: - rollup: ^2.14.0 - tslib: "*" - typescript: ">=3.7.0" - checksum: f8253a775389f29feadf639c2e04d87bddb4c30126b0d95b9e17bfffa2addad1b6275cb8dead40604348ea7ac0128fe4394413bc3b2129c4a545f93eb4585149 - languageName: node - linkType: hard - -"@rollup/pluginutils@npm:^3.1.0": - version: 3.1.0 - resolution: "@rollup/pluginutils@npm:3.1.0" - dependencies: - "@types/estree": 0.0.39 - estree-walker: ^1.0.1 - picomatch: ^2.2.2 - peerDependencies: - rollup: ^1.20.0||^2.0.0 - checksum: 8be16e27863c219edbb25a4e6ec2fe0e1e451d9e917b6a43cf2ae5bc025a6b8faaa40f82a6e53b66d0de37b58ff472c6c3d57a83037ae635041f8df959d6d9aa - languageName: node - linkType: hard - "@samverschueren/stream-to-observable@npm:^0.3.0": version: 0.3.1 resolution: "@samverschueren/stream-to-observable@npm:0.3.1" @@ -6130,6 +6086,16 @@ __metadata: languageName: node linkType: hard +"@types/eslint-scope@npm:^3.7.3": + version: 3.7.4 + resolution: "@types/eslint-scope@npm:3.7.4" + dependencies: + "@types/eslint": "*" + "@types/estree": "*" + checksum: ea6a9363e92f301cd3888194469f9ec9d0021fe0a397a97a6dd689e7545c75de0bd2153dfb13d3ab532853a278b6572c6f678ce846980669e41029d205653460 + languageName: node + linkType: hard + "@types/eslint-visitor-keys@npm:^1.0.0": version: 1.0.0 resolution: "@types/eslint-visitor-keys@npm:1.0.0" @@ -6154,10 +6120,10 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:0.0.39": - version: 0.0.39 - resolution: "@types/estree@npm:0.0.39" - checksum: 412fb5b9868f2c418126451821833414189b75cc6bf84361156feed733e3d92ec220b9d74a89e52722e03d5e241b2932732711b7497374a404fad49087adc248 +"@types/estree@npm:^0.0.51": + version: 0.0.51 + resolution: "@types/estree@npm:0.0.51" + checksum: e56a3bcf759fd9185e992e7fdb3c6a5f81e8ff120e871641607581fb3728d16c811702a7d40fa5f869b7f7b4437ab6a87eb8d98ffafeee51e85bbe955932a189 languageName: node linkType: hard @@ -6701,15 +6667,6 @@ __metadata: languageName: node linkType: hard -"@types/resolve@npm:1.17.1": - version: 1.17.1 - resolution: "@types/resolve@npm:1.17.1" - dependencies: - "@types/node": "*" - checksum: dc6a6df507656004e242dcb02c784479deca516d5f4b58a1707e708022b269ae147e1da0521f3e8ad0d63638869d87e0adc023f0bd5454aa6f72ac66c7525cf5 - languageName: node - linkType: hard - "@types/responselike@npm:*, @types/responselike@npm:^1.0.0": version: 1.0.0 resolution: "@types/responselike@npm:1.0.0" @@ -7398,6 +7355,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.7.1": + version: 8.8.0 + resolution: "acorn@npm:8.8.0" + bin: + acorn: bin/acorn + checksum: 7270ca82b242eafe5687a11fea6e088c960af712683756abf0791b68855ea9cace3057bd5e998ffcef50c944810c1e0ca1da526d02b32110e13c722aa959afdc + languageName: node + linkType: hard + "agent-base@npm:4, agent-base@npm:^4.3.0": version: 4.3.0 resolution: "agent-base@npm:4.3.0" @@ -13870,6 +13836,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.10.0": + version: 5.10.0 + resolution: "enhanced-resolve@npm:5.10.0" + dependencies: + graceful-fs: ^4.2.4 + tapable: ^2.2.0 + checksum: 0bb9830704db271610f900e8d79d70a740ea16f251263362b0c91af545576d09fe50103496606c1300a05e588372d6f9780a9bc2e30ce8ef9b827ec8f44687ff + languageName: node + linkType: hard + "enhanced-resolve@npm:^5.3.2, enhanced-resolve@npm:^5.8.3": version: 5.8.3 resolution: "enhanced-resolve@npm:5.8.3" @@ -14847,13 +14823,6 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^1.0.1": - version: 1.0.1 - resolution: "estree-walker@npm:1.0.1" - checksum: 7e70da539691f6db03a08e7ce94f394ce2eef4180e136d251af299d41f92fb2d28ebcd9a6e393e3728d7970aeb5358705ddf7209d52fbcb2dd4693f95dcf925f - languageName: node - linkType: hard - "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -20829,7 +20798,7 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^2.3.0": +"json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f @@ -23042,6 +23011,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.5": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: ^3.0.2 + picomatch: ^2.3.1 + checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + languageName: node + linkType: hard + "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": version: 4.0.4 resolution: "micromatch@npm:4.0.4" @@ -23052,16 +23031,6 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.5": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - "miller-rabin@npm:^4.0.0": version: 4.0.1 resolution: "miller-rabin@npm:4.0.1" @@ -25657,7 +25626,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.2.3": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3": version: 2.3.0 resolution: "picomatch@npm:2.3.0" checksum: 16818720ea7c5872b6af110760dee856c8e4cd79aed1c7a006d076b1cc09eff3ae41ca5019966694c33fbd2e1cc6ea617ab10e4adac6df06556168f13be3fca2 @@ -28008,7 +27977,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.x, resolve@npm:^1.1.3, resolve@npm:^1.1.4, resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.4.0, resolve@npm:^1.9.0, resolve@npm:~1.20.0": +"resolve@npm:1.x, resolve@npm:^1.1.3, resolve@npm:^1.1.4, resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.4.0, resolve@npm:^1.9.0, resolve@npm:~1.20.0": version: 1.20.0 resolution: "resolve@npm:1.20.0" dependencies: @@ -28035,7 +28004,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@1.x#~builtin, resolve@patch:resolve@^1.1.3#~builtin, resolve@patch:resolve@^1.1.4#~builtin, resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.13.1#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.4.0#~builtin, resolve@patch:resolve@^1.9.0#~builtin, resolve@patch:resolve@~1.20.0#~builtin": +"resolve@patch:resolve@1.x#~builtin, resolve@patch:resolve@^1.1.3#~builtin, resolve@patch:resolve@^1.1.4#~builtin, resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.13.1#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.4.0#~builtin, resolve@patch:resolve@^1.9.0#~builtin, resolve@patch:resolve@~1.20.0#~builtin": version: 1.20.0 resolution: "resolve@patch:resolve@npm%3A1.20.0#~builtin::version=1.20.0&hash=07638b" dependencies: @@ -28282,20 +28251,6 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^2.53.1": - version: 2.60.2 - resolution: "rollup@npm:2.60.2" - dependencies: - fsevents: ~2.3.2 - dependenciesMeta: - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: bcd41dfe8afb7e0d97ce2237752165bdda689bcce6321d96821d565de3e0c865a49b544923f315985be2bfde086f72b54aae4ae7c87f798b3cb9558a5bec4e65 - languageName: node - linkType: hard - "root@workspace:.": version: 0.0.0-use.local resolution: "root@workspace:." @@ -31383,6 +31338,21 @@ __metadata: languageName: node linkType: hard +"ts-loader@npm:^9.3.1": + version: 9.3.1 + resolution: "ts-loader@npm:9.3.1" + dependencies: + chalk: ^4.1.0 + enhanced-resolve: ^5.0.0 + micromatch: ^4.0.0 + semver: ^7.3.4 + peerDependencies: + typescript: "*" + webpack: ^5.0.0 + checksum: 462a8ac315017cf4961dafd2be29d5abe7c3af63c4515e325269f79b9d0212b35c59184d7fd01fc378749c88454752e1599301d2190eb6844ea5fe332de5f695 + languageName: node + linkType: hard + "tsame@npm:^1.1.2": version: 1.1.2 resolution: "tsame@npm:1.1.2" @@ -32711,6 +32681,16 @@ __metadata: languageName: node linkType: hard +"watchpack@npm:^2.4.0": + version: 2.4.0 + resolution: "watchpack@npm:2.4.0" + dependencies: + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.1.2 + checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 + languageName: node + linkType: hard + "wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" @@ -32805,6 +32785,13 @@ __metadata: languageName: node linkType: hard +"webpack-sources@npm:^3.2.3": + version: 3.2.3 + resolution: "webpack-sources@npm:3.2.3" + checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 + languageName: node + linkType: hard + "webpack@npm:^5.65.0": version: 5.65.0 resolution: "webpack@npm:5.65.0" @@ -32842,6 +32829,43 @@ __metadata: languageName: node linkType: hard +"webpack@npm:^5.74.0": + version: 5.74.0 + resolution: "webpack@npm:5.74.0" + dependencies: + "@types/eslint-scope": ^3.7.3 + "@types/estree": ^0.0.51 + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/wasm-edit": 1.11.1 + "@webassemblyjs/wasm-parser": 1.11.1 + acorn: ^8.7.1 + acorn-import-assertions: ^1.7.6 + browserslist: ^4.14.5 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.10.0 + es-module-lexer: ^0.9.0 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.9 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.1.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.1.3 + watchpack: ^2.4.0 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 320c41369a75051b19e18c63f408b3dcc481852e992f83d311771c5ec0f05f2946385e8ebef62030cf3587f0a3d2f12779ffdb191569a966847289ba7313f946 + languageName: node + linkType: hard + "whatwg-encoding@npm:^1.0.1, whatwg-encoding@npm:^1.0.3, whatwg-encoding@npm:^1.0.5": version: 1.0.5 resolution: "whatwg-encoding@npm:1.0.5"