UNPKG

webpack

Version:

Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

381 lines (361 loc) 12 kB
/* 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)); // TODO webpack 5: Disable by default in a modes this.set( "optimization.removeAvailableModules", "make", options => options.mode !== "development" ); 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 ); }); this.set("infrastructureLogging", "call", value => Object.assign({}, value) ); this.set("infrastructureLogging.level", "info"); this.set("infrastructureLogging.debug", false); } } module.exports = WebpackOptionsDefaulter;