| /* |
| MIT License http://www.opensource.org/licenses/mit-license.php |
| Author Tobias Koppers @sokra |
| */ |
| "use strict"; |
| |
| const path = require("path"); |
| |
| const OptionsDefaulter = require("./OptionsDefaulter"); |
| const Template = require("./Template"); |
| |
| const isProductionLikeMode = options => { |
| return options.mode === "production" || !options.mode; |
| }; |
| |
| const isWebLikeTarget = options => { |
| return options.target === "web" || options.target === "webworker"; |
| }; |
| |
| const getDevtoolNamespace = library => { |
| // if options.output.library is a string |
| if (Array.isArray(library)) { |
| return library.join("."); |
| } else if (typeof library === "object") { |
| return getDevtoolNamespace(library.root); |
| } |
| return library || ""; |
| }; |
| |
| class WebpackOptionsDefaulter extends OptionsDefaulter { |
| constructor() { |
| super(); |
| |
| this.set("entry", "./src"); |
| |
| this.set("devtool", "make", options => |
| options.mode === "development" ? "eval" : false |
| ); |
| this.set("cache", "make", options => options.mode === "development"); |
| |
| this.set("context", process.cwd()); |
| this.set("target", "web"); |
| |
| this.set("module", "call", value => Object.assign({}, value)); |
| this.set("module.unknownContextRequest", "."); |
| this.set("module.unknownContextRegExp", false); |
| this.set("module.unknownContextRecursive", true); |
| this.set("module.unknownContextCritical", true); |
| this.set("module.exprContextRequest", "."); |
| this.set("module.exprContextRegExp", false); |
| this.set("module.exprContextRecursive", true); |
| this.set("module.exprContextCritical", true); |
| this.set("module.wrappedContextRegExp", /.*/); |
| this.set("module.wrappedContextRecursive", true); |
| this.set("module.wrappedContextCritical", false); |
| this.set("module.strictExportPresence", false); |
| this.set("module.strictThisContextOnImports", false); |
| this.set("module.unsafeCache", "make", options => !!options.cache); |
| this.set("module.rules", []); |
| this.set("module.defaultRules", "make", options => [ |
| { |
| type: "javascript/auto", |
| resolve: {} |
| }, |
| { |
| test: /\.mjs$/i, |
| type: "javascript/esm", |
| resolve: { |
| mainFields: |
| options.target === "web" || |
| options.target === "webworker" || |
| options.target === "electron-renderer" |
| ? ["browser", "main"] |
| : ["main"] |
| } |
| }, |
| { |
| test: /\.json$/i, |
| type: "json" |
| }, |
| { |
| test: /\.wasm$/i, |
| type: "webassembly/experimental" |
| } |
| ]); |
| |
| this.set("output", "call", (value, options) => { |
| if (typeof value === "string") { |
| return { |
| filename: value |
| }; |
| } else if (typeof value !== "object") { |
| return {}; |
| } else { |
| return Object.assign({}, value); |
| } |
| }); |
| |
| this.set("output.filename", "[name].js"); |
| this.set("output.chunkFilename", "make", options => { |
| const filename = options.output.filename; |
| if (typeof filename !== "function") { |
| const hasName = filename.includes("[name]"); |
| const hasId = filename.includes("[id]"); |
| const hasChunkHash = filename.includes("[chunkhash]"); |
| // Anything changing depending on chunk is fine |
| if (hasChunkHash || hasName || hasId) return filename; |
| // Elsewise prefix "[id]." in front of the basename to make it changing |
| return filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2"); |
| } |
| return "[id].js"; |
| }); |
| this.set("output.webassemblyModuleFilename", "[modulehash].module.wasm"); |
| this.set("output.library", ""); |
| this.set("output.hotUpdateFunction", "make", options => { |
| return Template.toIdentifier( |
| "webpackHotUpdate" + Template.toIdentifier(options.output.library) |
| ); |
| }); |
| this.set("output.jsonpFunction", "make", options => { |
| return Template.toIdentifier( |
| "webpackJsonp" + Template.toIdentifier(options.output.library) |
| ); |
| }); |
| this.set("output.chunkCallbackName", "make", options => { |
| return Template.toIdentifier( |
| "webpackChunk" + Template.toIdentifier(options.output.library) |
| ); |
| }); |
| this.set("output.globalObject", "make", options => { |
| switch (options.target) { |
| case "web": |
| case "electron-renderer": |
| case "node-webkit": |
| return "window"; |
| case "webworker": |
| return "self"; |
| case "node": |
| case "async-node": |
| case "electron-main": |
| return "global"; |
| default: |
| return "self"; |
| } |
| }); |
| this.set("output.devtoolNamespace", "make", options => { |
| return getDevtoolNamespace(options.output.library); |
| }); |
| this.set("output.libraryTarget", "var"); |
| this.set("output.path", path.join(process.cwd(), "dist")); |
| this.set( |
| "output.pathinfo", |
| "make", |
| options => options.mode === "development" |
| ); |
| this.set("output.sourceMapFilename", "[file].map[query]"); |
| this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js"); |
| this.set("output.hotUpdateMainFilename", "[hash].hot-update.json"); |
| this.set("output.crossOriginLoading", false); |
| this.set("output.jsonpScriptType", false); |
| this.set("output.chunkLoadTimeout", 120000); |
| this.set("output.hashFunction", "md4"); |
| this.set("output.hashDigest", "hex"); |
| this.set("output.hashDigestLength", 20); |
| this.set("output.devtoolLineToLine", false); |
| this.set("output.strictModuleExceptionHandling", false); |
| |
| this.set("node", "call", value => { |
| if (typeof value === "boolean") { |
| return value; |
| } else { |
| return Object.assign({}, value); |
| } |
| }); |
| this.set("node.console", false); |
| this.set("node.process", true); |
| this.set("node.global", true); |
| this.set("node.Buffer", true); |
| this.set("node.setImmediate", true); |
| this.set("node.__filename", "mock"); |
| this.set("node.__dirname", "mock"); |
| |
| this.set("performance", "call", (value, options) => { |
| if (value === false) return false; |
| if ( |
| value === undefined && |
| (!isProductionLikeMode(options) || !isWebLikeTarget(options)) |
| ) |
| return false; |
| return Object.assign({}, value); |
| }); |
| this.set("performance.maxAssetSize", 250000); |
| this.set("performance.maxEntrypointSize", 250000); |
| this.set("performance.hints", "make", options => |
| isProductionLikeMode(options) ? "warning" : false |
| ); |
| |
| this.set("optimization", "call", value => Object.assign({}, value)); |
| this.set("optimization.removeAvailableModules", true); |
| this.set("optimization.removeEmptyChunks", true); |
| this.set("optimization.mergeDuplicateChunks", true); |
| this.set("optimization.flagIncludedChunks", "make", options => |
| isProductionLikeMode(options) |
| ); |
| // TODO webpack 5 add `moduleIds: "named"` default for development |
| // TODO webpack 5 add `moduleIds: "size"` default for production |
| // TODO webpack 5 remove optimization.occurrenceOrder |
| this.set("optimization.occurrenceOrder", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.sideEffects", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.providedExports", true); |
| this.set("optimization.usedExports", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.concatenateModules", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.splitChunks", {}); |
| this.set("optimization.splitChunks.hidePathInfo", "make", options => { |
| return isProductionLikeMode(options); |
| }); |
| this.set("optimization.splitChunks.chunks", "async"); |
| this.set("optimization.splitChunks.minSize", "make", options => { |
| return isProductionLikeMode(options) ? 30000 : 10000; |
| }); |
| this.set("optimization.splitChunks.minChunks", 1); |
| this.set("optimization.splitChunks.maxAsyncRequests", "make", options => { |
| return isProductionLikeMode(options) ? 5 : Infinity; |
| }); |
| this.set("optimization.splitChunks.automaticNameDelimiter", "~"); |
| this.set("optimization.splitChunks.automaticNameMaxLength", 109); |
| this.set("optimization.splitChunks.maxInitialRequests", "make", options => { |
| return isProductionLikeMode(options) ? 3 : Infinity; |
| }); |
| this.set("optimization.splitChunks.name", true); |
| this.set("optimization.splitChunks.cacheGroups", {}); |
| this.set("optimization.splitChunks.cacheGroups.default", { |
| automaticNamePrefix: "", |
| reuseExistingChunk: true, |
| minChunks: 2, |
| priority: -20 |
| }); |
| this.set("optimization.splitChunks.cacheGroups.vendors", { |
| automaticNamePrefix: "vendors", |
| test: /[\\/]node_modules[\\/]/, |
| priority: -10 |
| }); |
| this.set("optimization.runtimeChunk", "call", value => { |
| if (value === "single") { |
| return { |
| name: "runtime" |
| }; |
| } |
| if (value === true || value === "multiple") { |
| return { |
| name: entrypoint => `runtime~${entrypoint.name}` |
| }; |
| } |
| return value; |
| }); |
| this.set("optimization.noEmitOnErrors", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.checkWasmTypes", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.mangleWasmImports", false); |
| // TODO webpack 5 remove optimization.namedModules |
| this.set( |
| "optimization.namedModules", |
| "make", |
| options => options.mode === "development" |
| ); |
| this.set("optimization.hashedModuleIds", false); |
| // TODO webpack 5 add `chunkIds: "named"` default for development |
| // TODO webpack 5 add `chunkIds: "size"` default for production |
| // TODO webpack 5 remove optimization.namedChunks |
| this.set( |
| "optimization.namedChunks", |
| "make", |
| options => options.mode === "development" |
| ); |
| this.set( |
| "optimization.portableRecords", |
| "make", |
| options => |
| !!( |
| options.recordsInputPath || |
| options.recordsOutputPath || |
| options.recordsPath |
| ) |
| ); |
| this.set("optimization.minimize", "make", options => |
| isProductionLikeMode(options) |
| ); |
| this.set("optimization.minimizer", "make", options => [ |
| { |
| apply: compiler => { |
| // Lazy load the Terser plugin |
| const TerserPlugin = require("terser-webpack-plugin"); |
| const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); |
| new TerserPlugin({ |
| cache: true, |
| parallel: true, |
| sourceMap: |
| (options.devtool && /source-?map/.test(options.devtool)) || |
| (options.plugins && |
| options.plugins.some(p => p instanceof SourceMapDevToolPlugin)) |
| }).apply(compiler); |
| } |
| } |
| ]); |
| this.set("optimization.nodeEnv", "make", options => { |
| // TODO: In webpack 5, it should return `false` when mode is `none` |
| return options.mode || "production"; |
| }); |
| |
| this.set("resolve", "call", value => Object.assign({}, value)); |
| this.set("resolve.unsafeCache", true); |
| this.set("resolve.modules", ["node_modules"]); |
| this.set("resolve.extensions", [".wasm", ".mjs", ".js", ".json"]); |
| this.set("resolve.mainFiles", ["index"]); |
| this.set("resolve.aliasFields", "make", options => { |
| if ( |
| options.target === "web" || |
| options.target === "webworker" || |
| options.target === "electron-renderer" |
| ) { |
| return ["browser"]; |
| } else { |
| return []; |
| } |
| }); |
| this.set("resolve.mainFields", "make", options => { |
| if ( |
| options.target === "web" || |
| options.target === "webworker" || |
| options.target === "electron-renderer" |
| ) { |
| return ["browser", "module", "main"]; |
| } else { |
| return ["module", "main"]; |
| } |
| }); |
| this.set("resolve.cacheWithContext", "make", options => { |
| return ( |
| Array.isArray(options.resolve.plugins) && |
| options.resolve.plugins.length > 0 |
| ); |
| }); |
| |
| this.set("resolveLoader", "call", value => Object.assign({}, value)); |
| this.set("resolveLoader.unsafeCache", true); |
| this.set("resolveLoader.mainFields", ["loader", "main"]); |
| this.set("resolveLoader.extensions", [".js", ".json"]); |
| this.set("resolveLoader.mainFiles", ["index"]); |
| this.set("resolveLoader.cacheWithContext", "make", options => { |
| return ( |
| Array.isArray(options.resolveLoader.plugins) && |
| options.resolveLoader.plugins.length > 0 |
| ); |
| }); |
| } |
| } |
| |
| module.exports = WebpackOptionsDefaulter; |