webpack
Version:
Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
1,447 lines (1,368 loc) • 85.1 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const fs = require("fs");
const path = require("path");
const {
CSS_TYPE,
JAVASCRIPT_TYPE,
UNKNOWN_TYPE
} = require("../ModuleSourceTypeConstants");
const {
ASSET_MODULE_TYPE,
ASSET_MODULE_TYPE_BYTES,
ASSET_MODULE_TYPE_INLINE,
ASSET_MODULE_TYPE_RESOURCE,
ASSET_MODULE_TYPE_SOURCE,
CSS_MODULE_TYPE,
CSS_MODULE_TYPE_AUTO,
CSS_MODULE_TYPE_GLOBAL,
CSS_MODULE_TYPE_MODULE,
HTML_MODULE_TYPE,
JAVASCRIPT_MODULE_TYPE_AUTO,
JAVASCRIPT_MODULE_TYPE_DYNAMIC,
JAVASCRIPT_MODULE_TYPE_ESM,
JSON_MODULE_TYPE,
WEBASSEMBLY_MODULE_TYPE_ASYNC,
WEBASSEMBLY_MODULE_TYPE_SYNC
} = require("../ModuleTypeConstants");
const Template = require("../Template");
const RuleSetCompiler = require("../rules/RuleSetCompiler");
const { cleverMerge } = require("../util/cleverMerge");
const {
getDefaultTarget,
getTargetProperties,
getTargetsProperties
} = require("./target");
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptionsNormalized */
/** @typedef {import("../../declarations/WebpackOptions").Context} Context */
/** @typedef {import("../../declarations/WebpackOptions").DevTool} Devtool */
/** @typedef {import("../../declarations/WebpackOptions").CssGeneratorOptions} CssGeneratorOptions */
/** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
/** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
/** @typedef {import("../../declarations/WebpackOptions").Environment} Environment */
/** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
/** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */
/** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
/** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */
/** @typedef {import("../../declarations/WebpackOptions").FileCacheOptions} FileCacheOptions */
/** @typedef {import("../../declarations/WebpackOptions").GeneratorOptionsByModuleTypeKnown} GeneratorOptionsByModuleTypeKnown */
/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
/** @typedef {import("../../declarations/WebpackOptions").Library} Library */
/** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../../declarations/WebpackOptions").Loader} Loader */
/** @typedef {import("../../declarations/WebpackOptions").Mode} Mode */
/** @typedef {import("../../declarations/WebpackOptions").HashFunction} HashFunction */
/** @typedef {import("../../declarations/WebpackOptions").HashSalt} HashSalt */
/** @typedef {import("../../declarations/WebpackOptions").HashDigest} HashDigest */
/** @typedef {import("../../declarations/WebpackOptions").HashDigestLength} HashDigestLength */
/** @typedef {import("../../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
/** @typedef {import("../../declarations/WebpackOptions").Node} WebpackNode */
/** @typedef {import("../../declarations/WebpackOptions").OptimizationNormalized} Optimization */
/** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksOptions} OptimizationSplitChunksOptions */
/** @typedef {import("../../declarations/WebpackOptions").OutputNormalized} Output */
/** @typedef {import("../../declarations/WebpackOptions").ParserOptionsByModuleTypeKnown} ParserOptionsByModuleTypeKnown */
/** @typedef {import("../../declarations/WebpackOptions").Performance} Performance */
/** @typedef {import("../../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
/** @typedef {import("../../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
/** @typedef {import("../../declarations/WebpackOptions").RuleSetRules} RuleSetRules */
/** @typedef {import("../../declarations/WebpackOptions").SnapshotOptions} SnapshotOptions */
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptionsNormalized */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/EnableChunkLoadingPlugin").ChunkLoadingTypes} ChunkLoadingTypes */
/** @typedef {import("../wasm/EnableWasmLoadingPlugin").WasmLoadingTypes} WasmLoadingTypes */
/** @typedef {import("./target").PlatformTargetProperties} PlatformTargetProperties */
/** @typedef {import("./target").TargetProperties} TargetProperties */
/**
* Defines the recursive non nullable type used by this module.
* @template T
* @typedef {{ [P in keyof T]-?: T[P] extends object ? RecursiveNonNullable<NonNullable<T[P]>> : NonNullable<T[P]> }} RecursiveNonNullable
*/
/**
* Defines the shared type used by this module.
* @typedef {Output & {
* uniqueName: NonNullable<Output["uniqueName"]>,
* filename: NonNullable<Output["filename"]>,
* cssFilename: NonNullable<Output["cssFilename"]>,
* chunkFilename: NonNullable<Output["chunkFilename"]>,
* cssChunkFilename: NonNullable<Output["cssChunkFilename"]>,
* hotUpdateChunkFilename: NonNullable<Output["hotUpdateChunkFilename"]>,
* hotUpdateGlobal: NonNullable<Output["hotUpdateGlobal"]>,
* assetModuleFilename: NonNullable<Output["assetModuleFilename"]>,
* webassemblyModuleFilename: NonNullable<Output["webassemblyModuleFilename"]>,
* sourceMapFilename: NonNullable<Output["sourceMapFilename"]>,
* hotUpdateMainFilename: NonNullable<Output["hotUpdateMainFilename"]>,
* devtoolNamespace: NonNullable<Output["devtoolNamespace"]>,
* publicPath: NonNullable<Output["publicPath"]>,
* workerPublicPath: NonNullable<Output["workerPublicPath"]>,
* workerChunkFilename: NonNullable<Output["workerChunkFilename"]>,
* workerWasmLoading: NonNullable<Output["workerWasmLoading"]>,
* workerChunkLoading: NonNullable<Output["workerChunkLoading"]>,
* chunkFormat: NonNullable<Output["chunkFormat"]>,
* module: NonNullable<Output["module"]>,
* asyncChunks: NonNullable<Output["asyncChunks"]>,
* charset: NonNullable<Output["charset"]>,
* iife: NonNullable<Output["iife"]>,
* globalObject: NonNullable<Output["globalObject"]>,
* scriptType: NonNullable<Output["scriptType"]>,
* path: NonNullable<Output["path"]>,
* pathinfo: NonNullable<Output["pathinfo"]>,
* hashFunction: NonNullable<Output["hashFunction"]>,
* hashDigest: NonNullable<Output["hashDigest"]>,
* hashDigestLength: NonNullable<Output["hashDigestLength"]>,
* chunkLoadTimeout: NonNullable<Output["chunkLoadTimeout"]>,
* chunkLoading: NonNullable<Output["chunkLoading"]>,
* chunkLoadingGlobal: NonNullable<Output["chunkLoadingGlobal"]>,
* compareBeforeEmit: NonNullable<Output["compareBeforeEmit"]>,
* strictModuleErrorHandling: NonNullable<Output["strictModuleErrorHandling"]>,
* strictModuleExceptionHandling: NonNullable<Output["strictModuleExceptionHandling"]>,
* strictModuleResolution: NonNullable<Output["strictModuleResolution"]>,
* importFunctionName: NonNullable<Output["importFunctionName"]>,
* importMetaName: NonNullable<Output["importMetaName"]>,
* environment: RecursiveNonNullable<Output["environment"]>,
* crossOriginLoading: NonNullable<Output["crossOriginLoading"]>,
* wasmLoading: NonNullable<Output["wasmLoading"]>,
* }} OutputNormalizedWithDefaults
*/
/**
* Defines the shared type used by this module.
* @typedef {SnapshotOptions & {
* managedPaths: NonNullable<SnapshotOptions["managedPaths"]>,
* unmanagedPaths: NonNullable<SnapshotOptions["unmanagedPaths"]>,
* immutablePaths: NonNullable<SnapshotOptions["immutablePaths"]>,
* resolveBuildDependencies: NonNullable<SnapshotOptions["resolveBuildDependencies"]>,
* buildDependencies: NonNullable<SnapshotOptions["buildDependencies"]>,
* module: NonNullable<SnapshotOptions["module"]>,
* resolve: NonNullable<SnapshotOptions["resolve"]>,
* }} SnapshotNormalizedWithDefaults
*/
/**
* Defines the shared type used by this module.
* @typedef {Optimization & {
* runtimeChunk: NonNullable<Optimization["runtimeChunk"]>,
* splitChunks: NonNullable<Optimization["splitChunks"]>,
* mergeDuplicateChunks: NonNullable<Optimization["mergeDuplicateChunks"]>,
* removeAvailableModules: NonNullable<Optimization["removeAvailableModules"]>,
* removeEmptyChunks: NonNullable<Optimization["removeEmptyChunks"]>,
* flagIncludedChunks: NonNullable<Optimization["flagIncludedChunks"]>,
* moduleIds: NonNullable<Optimization["moduleIds"]>,
* chunkIds: NonNullable<Optimization["chunkIds"]>,
* sideEffects: NonNullable<Optimization["sideEffects"]>,
* providedExports: NonNullable<Optimization["providedExports"]>,
* usedExports: NonNullable<Optimization["usedExports"]>,
* mangleExports: NonNullable<Optimization["mangleExports"]>,
* innerGraph: NonNullable<Optimization["innerGraph"]>,
* inlineExports: NonNullable<Optimization["inlineExports"]>,
* concatenateModules: NonNullable<Optimization["concatenateModules"]>,
* avoidEntryIife: NonNullable<Optimization["avoidEntryIife"]>,
* emitOnErrors: NonNullable<Optimization["emitOnErrors"]>,
* checkWasmTypes: NonNullable<Optimization["checkWasmTypes"]>,
* mangleWasmImports: NonNullable<Optimization["mangleWasmImports"]>,
* portableRecords: NonNullable<Optimization["portableRecords"]>,
* realContentHash: NonNullable<Optimization["realContentHash"]>,
* minimize: NonNullable<Optimization["minimize"]>,
* minimizer: NonNullable<Exclude<Optimization["minimizer"], "...">>,
* nodeEnv: NonNullable<Optimization["nodeEnv"]>,
* }} OptimizationNormalizedWithDefaults
*/
/**
* Defines the shared type used by this module.
* @typedef {ExternalsPresets & {
* web: NonNullable<ExternalsPresets["web"]>,
* node: NonNullable<ExternalsPresets["node"]>,
* nwjs: NonNullable<ExternalsPresets["nwjs"]>,
* electron: NonNullable<ExternalsPresets["electron"]>,
* electronMain: NonNullable<ExternalsPresets["electronMain"]>,
* electronPreload: NonNullable<ExternalsPresets["electronPreload"]>,
* electronRenderer: NonNullable<ExternalsPresets["electronRenderer"]>,
* }} ExternalsPresetsNormalizedWithDefaults
*/
/**
* Defines the shared type used by this module.
* @typedef {InfrastructureLogging & {
* stream: NonNullable<InfrastructureLogging["stream"]>,
* level: NonNullable<InfrastructureLogging["level"]>,
* debug: NonNullable<InfrastructureLogging["debug"]>,
* colors: NonNullable<InfrastructureLogging["colors"]>,
* appendOnly: NonNullable<InfrastructureLogging["appendOnly"]>,
* }} InfrastructureLoggingNormalizedWithDefaults
*/
/**
* Defines the webpack options normalized with base defaults type used by this module.
* @typedef {WebpackOptionsNormalized & { context: NonNullable<WebpackOptionsNormalized["context"]> } & { infrastructureLogging: InfrastructureLoggingNormalizedWithDefaults }} WebpackOptionsNormalizedWithBaseDefaults
*/
/**
* Defines the webpack options normalized with defaults type used by this module.
* @typedef {WebpackOptionsNormalizedWithBaseDefaults & { target: NonNullable<WebpackOptionsNormalized["target"]> } & { output: OutputNormalizedWithDefaults } & { optimization: OptimizationNormalizedWithDefaults } & { devtool: NonNullable<WebpackOptionsNormalized["devtool"]> } & { stats: NonNullable<WebpackOptionsNormalized["stats"]> } & { node: NonNullable<WebpackOptionsNormalized["node"]> } & { profile: NonNullable<WebpackOptionsNormalized["profile"]> } & { parallelism: NonNullable<WebpackOptionsNormalized["parallelism"]> } & { snapshot: SnapshotNormalizedWithDefaults } & { externalsPresets: ExternalsPresetsNormalizedWithDefaults } & { externalsType: NonNullable<WebpackOptionsNormalized["externalsType"]> } & { watch: NonNullable<WebpackOptionsNormalized["watch"]> } & { performance: NonNullable<WebpackOptionsNormalized["performance"]> } & { recordsInputPath: NonNullable<WebpackOptionsNormalized["recordsInputPath"]> } & { recordsOutputPath: NonNullable<WebpackOptionsNormalized["recordsOutputPath"]> } & { dotenv: NonNullable<WebpackOptionsNormalized["dotenv"]> }} WebpackOptionsNormalizedWithDefaults
*/
/**
* Defines the resolved options type used by this module.
* @typedef {object} ResolvedOptions
* @property {PlatformTargetProperties | false} platform - platform target properties
*/
const NODE_MODULES_REGEXP = /[\\/]node_modules[\\/]/i;
const DEFAULT_CACHE_NAME = "default";
const DEFAULTS = {
// TODO webpack 6 - use xxhash64
HASH_FUNCTION: "md4"
};
/**
* Processes the provided obj.
* @template T
* @template {keyof T} P
* @param {T} obj an object
* @param {P} prop a property of this object
* @param {T[P]} value a default value of the property
* @returns {void}
*/
const D = (obj, prop, value) => {
if (obj[prop] === undefined) {
obj[prop] = value;
}
};
/**
* Processes the provided obj.
* @template T
* @template {keyof T} P
* @param {T} obj an object
* @param {P} prop a property of this object
* @param {() => T[P]} factory a default value factory for the property
* @returns {void}
*/
const F = (obj, prop, factory) => {
if (obj[prop] === undefined) {
obj[prop] = factory();
}
};
/**
* Sets a dynamic default value when undefined, by calling the factory function.
* factory must return an array or undefined
* When the current value is already an array an contains "..." it's replaced with
* the result of the factory function
* @template T
* @template {keyof T} P
* @param {T} obj an object
* @param {P} prop a property of this object
* @param {() => T[P]} factory a default value factory for the property
* @returns {void}
*/
const A = (obj, prop, factory) => {
const value = obj[prop];
if (value === undefined) {
obj[prop] = factory();
} else if (Array.isArray(value)) {
/** @type {EXPECTED_ANY[] | undefined} */
let newArray;
for (let i = 0; i < value.length; i++) {
const item = value[i];
if (item === "...") {
if (newArray === undefined) {
newArray = value.slice(0, i);
obj[prop] = /** @type {T[P]} */ (/** @type {unknown} */ (newArray));
}
const items =
/** @type {EXPECTED_ANY[]} */
(/** @type {unknown} */ (factory()));
if (items !== undefined) {
for (const item of items) {
newArray.push(item);
}
}
} else if (newArray !== undefined) {
newArray.push(item);
}
}
}
};
/**
* Apply webpack options base defaults.
* @param {WebpackOptionsNormalized} options options to be modified
* @returns {void}
*/
const applyWebpackOptionsBaseDefaults = (options) => {
F(options, "context", () => process.cwd());
applyInfrastructureLoggingDefaults(options.infrastructureLogging);
};
/**
* Apply webpack options defaults.
* @param {WebpackOptionsNormalized} options options to be modified
* @param {number=} compilerIndex index of compiler
* @returns {ResolvedOptions} Resolved options after apply defaults
*/
const applyWebpackOptionsDefaults = (options, compilerIndex) => {
F(options, "context", () => process.cwd());
F(options, "target", () =>
getDefaultTarget(/** @type {string} */ (options.context))
);
const { mode, name, target } = options;
const targetProperties =
target === false
? /** @type {false} */ (false)
: typeof target === "string"
? getTargetProperties(target, /** @type {Context} */ (options.context))
: getTargetsProperties(
/** @type {string[]} */ (target),
/** @type {Context} */ (options.context)
);
const development = mode === "development";
const production = mode === "production" || !mode;
if (typeof options.entry !== "function") {
for (const key of Object.keys(options.entry)) {
F(
options.entry[key],
"import",
() => /** @type {[string]} */ (["./src"])
);
}
}
D(options, "watch", false);
D(options, "profile", false);
D(options, "parallelism", 100);
D(options, "recordsInputPath", false);
D(options, "recordsOutputPath", false);
// Capture the raw html intent before "auto" is resolved: only an explicit
// `html: true` (or futureDefaults) keeps `.html` ahead of `.js` when resolving.
const htmlExplicitlyEnabled = options.experiments.html === true;
const htmlWasUnset = options.experiments.html === undefined;
applyExperimentsDefaults(options.experiments, {
production,
development,
targetProperties,
rules: options.module.rules
});
// After experiments are resolved: the default dev source map depends on the
// (possibly "auto"-resolved) `experiments.css` value.
F(
options,
"devtool",
() =>
/** @type {Devtool} */ (
development
? [
options.experiments.css
? {
type: "css",
use: "source-map"
}
: undefined,
{
type: "javascript",
use: "eval"
}
].filter(Boolean)
: false
)
);
const futureDefaults =
/** @type {NonNullable<ExperimentsNormalized["futureDefaults"]>} */
(options.experiments.futureDefaults);
// `.html` outranks `.js` only for an explicit opt-in (`html: true`, or the
// futureDefaults-forced default), never for the auto-enabled default.
const htmlFirst = htmlExplicitlyEnabled || (htmlWasUnset && futureDefaults);
F(options, "validate", () => !(futureDefaults === true && production));
// Progress lives on infrastructureLogging; webpack@6 shows the interactive
// bar by default (`"auto"` = TTY only), webpack@5 stays opt-in.
D(options.infrastructureLogging, "progress", futureDefaults ? "auto" : false);
F(options, "cache", () =>
development ? { type: /** @type {"memory"} */ ("memory") } : false
);
applyCacheDefaults(options.cache, {
name: name || DEFAULT_CACHE_NAME,
mode: mode || "production",
development,
cacheUnaffected: options.experiments.cacheUnaffected,
futureDefaults,
compilerIndex
});
const cache = Boolean(options.cache);
applySnapshotDefaults(options.snapshot, {
production,
futureDefaults
});
applyOutputDefaults(options.output, {
context: /** @type {Context} */ (options.context),
targetProperties,
isAffectedByBrowserslist:
target === undefined ||
(typeof target === "string" && target.startsWith("browserslist")) ||
(Array.isArray(target) &&
target.some((target) => target.startsWith("browserslist"))),
outputModule:
/** @type {NonNullable<ExperimentsNormalized["outputModule"]>} */
(options.experiments.outputModule),
development,
entry: options.entry,
futureDefaults,
asyncWebAssembly:
/** @type {boolean} */
(options.experiments.asyncWebAssembly)
});
applyModuleDefaults(options.module, {
cache,
hashSalt: /** @type {NonNullable<Output["hashSalt"]>} */ (
options.output.hashSalt
),
hashFunction: /** @type {NonNullable<Output["hashFunction"]>} */ (
options.output.hashFunction
),
syncWebAssembly:
/** @type {NonNullable<ExperimentsNormalized["syncWebAssembly"]>} */
(options.experiments.syncWebAssembly),
asyncWebAssembly:
/** @type {boolean} */
(options.experiments.asyncWebAssembly),
css:
/** @type {boolean} */
(options.experiments.css),
html:
/** @type {boolean} */
(options.experiments.html),
typescript:
/** @type {boolean} */
(options.experiments.typescript),
deferImport:
/** @type {NonNullable<ExperimentsNormalized["deferImport"]>} */
(options.experiments.deferImport),
sourceImport:
/** @type {NonNullable<ExperimentsNormalized["sourceImport"]>} */
(options.experiments.sourceImport),
futureDefaults,
isNode: targetProperties && targetProperties.node === true,
uniqueName: /** @type {string} */ (options.output.uniqueName),
targetProperties,
mode: options.mode,
outputModule:
/** @type {NonNullable<WebpackOptionsNormalized["output"]["module"]>} */
(options.output.module),
library: options.output.library
});
// `output.resourceHints.urlHints` shorthand: fan the project-wide rules out
// as the base `urlHints` of every URL-emitting parser (JS `new URL`, CSS
// `url()`, HTML `<img src>`). They go first so parser-scoped
// `parser.<type>.urlHints` rules — matched later, last-match-wins — override.
const outputUrlHints =
options.output.resourceHints && options.output.resourceHints.urlHints;
if (outputUrlHints && outputUrlHints.length > 0) {
for (const type of [
"javascript",
CSS_MODULE_TYPE,
CSS_MODULE_TYPE_AUTO,
CSS_MODULE_TYPE_MODULE,
CSS_MODULE_TYPE_GLOBAL,
HTML_MODULE_TYPE
]) {
const parser =
/** @type {{ urlHints?: import("../../declarations/WebpackOptions").UrlHintRule[] } | undefined} */
(options.module.parser[type]);
if (!parser) continue;
parser.urlHints = [...outputUrlHints, ...(parser.urlHints || [])];
}
}
applyExternalsPresetsDefaults(options.externalsPresets, {
targetProperties,
buildHttp: Boolean(options.experiments.buildHttp),
outputModule:
/** @type {NonNullable<WebpackOptionsNormalized["output"]["module"]>} */
(options.output.module)
});
applyLoaderDefaults(
/** @type {NonNullable<WebpackOptionsNormalized["loader"]>} */ (
options.loader
),
{ targetProperties, environment: options.output.environment }
);
F(options, "externalsType", () => {
const validExternalTypes = require("../../schemas/WebpackOptions.json")
.definitions.ExternalsType.enum;
return options.output.library &&
validExternalTypes.includes(options.output.library.type)
? /** @type {ExternalsType} */ (options.output.library.type)
: options.output.module
? "module-import"
: "var";
});
applyNodeDefaults(options.node, {
futureDefaults:
/** @type {NonNullable<WebpackOptionsNormalized["experiments"]["futureDefaults"]>} */
(options.experiments.futureDefaults),
outputModule:
/** @type {NonNullable<WebpackOptionsNormalized["output"]["module"]>} */
(options.output.module),
targetProperties
});
F(options, "performance", () =>
production &&
targetProperties &&
(targetProperties.browser || targetProperties.browser === null)
? {}
: false
);
applyPerformanceDefaults(
/** @type {NonNullable<WebpackOptionsNormalized["performance"]>} */
(options.performance),
{
production
}
);
applyOptimizationDefaults(options.optimization, {
development,
production,
css:
/** @type {boolean} */
(options.experiments.css),
records: Boolean(options.recordsInputPath || options.recordsOutputPath)
});
options.resolve = cleverMerge(
getResolveDefaults({
cache,
context: /** @type {Context} */ (options.context),
targetProperties,
mode: /** @type {Mode} */ (options.mode),
css:
/** @type {boolean} */
(options.experiments.css),
html:
/** @type {boolean} */
(options.experiments.html),
htmlFirst,
typescript:
/** @type {boolean} */
(options.experiments.typescript)
}),
options.resolve
);
options.resolveLoader = cleverMerge(
getResolveLoaderDefaults({ cache }),
options.resolveLoader
);
return {
platform:
targetProperties === false
? targetProperties
: {
web: targetProperties.web,
browser: targetProperties.browser,
webworker: targetProperties.webworker,
node: targetProperties.node,
deno: targetProperties.deno,
bun: targetProperties.bun,
nwjs: targetProperties.nwjs,
electron: targetProperties.electron,
// spans both web and node (target "universal" or ["web", "node"])
universal:
targetProperties.node === null && targetProperties.web === null
}
};
};
/**
* Apply experiments defaults.
* @param {ExperimentsNormalized} experiments options
* @param {object} options options
* @param {boolean} options.production is production
* @param {boolean} options.development is development mode
* @param {TargetProperties | false} options.targetProperties target properties
* @param {RuleSetRules} options.rules user `module.rules`, used to resolve the css/html/asyncWebAssembly/typescript "auto" defaults
* @returns {void}
*/
const applyExperimentsDefaults = (
experiments,
{ production, development, targetProperties, rules }
) => {
D(experiments, "futureDefaults", false);
D(experiments, "backCompat", !experiments.futureDefaults);
// TODO do we need sync web assembly in webpack@6?
D(experiments, "syncWebAssembly", false);
D(
experiments,
"asyncWebAssembly",
experiments.futureDefaults ? true : "auto"
);
// the universal target (web + node, neither specific) only works as ESM
const universal =
Boolean(targetProperties) &&
/** @type {TargetProperties} */ (targetProperties).node === null &&
/** @type {TargetProperties} */ (targetProperties).web === null;
// the deno and bun targets only emit ECMAScript modules
const deno =
Boolean(targetProperties) &&
/** @type {TargetProperties} */ (targetProperties).deno === true;
const bun =
Boolean(targetProperties) &&
/** @type {TargetProperties} */ (targetProperties).bun === true;
D(experiments, "outputModule", universal || deno || bun);
D(experiments, "lazyCompilation", undefined);
D(experiments, "buildHttp", undefined);
D(experiments, "cacheUnaffected", experiments.futureDefaults);
D(experiments, "deferImport", false);
D(experiments, "sourceImport", false);
F(experiments, "css", () => (experiments.futureDefaults ? true : "auto"));
F(experiments, "html", () => (experiments.futureDefaults ? true : "auto"));
F(experiments, "typescript", () =>
experiments.futureDefaults ? true : "auto"
);
// Resolve the "auto" default: enable the built-in css/html module type unless
// the user already registered a loader (or explicit type) for these files, so
// enabling them by default does not break existing css-loader/html-loader setups.
// The built-in `/\.css$/i` rule also covers `.module.css`, so a loader scoped to
// CSS modules must disable the built-in type too — sample both extensions.
// When enabled implicitly the value stays `"auto"` (truthy): Css/HtmlModulesPlugin
// then step aside per-module for requests that loaders were applied to
// (inline requests or loaders injected via hooks, e.g. html-webpack-plugin).
// TODO webpack 6: css/html default to `true`, drop the `"auto"` marker.
if (experiments.css === "auto") {
experiments.css =
!(
RuleSetCompiler.hasRuleForResource(rules, "/file.css") ||
RuleSetCompiler.hasRuleForResource(rules, "/file.module.css")
) && "auto";
}
if (experiments.html === "auto") {
experiments.html =
!RuleSetCompiler.hasRuleForResource(rules, "/file.html") && "auto";
}
// Auto-enable only when the built-in TypeScript support can actually run:
// it needs `module.stripTypeScriptTypes` (Node.js >= 22.6) and must step
// aside for a loader registered for `.ts`/`.mts`/`.cts` (e.g. ts-loader).
if (experiments.typescript === "auto") {
experiments.typescript =
// eslint-disable-next-line n/no-unsupported-features/node-builtins
typeof require("module").stripTypeScriptTypes === "function" &&
!(
RuleSetCompiler.hasRuleForResource(rules, "/file.ts") ||
RuleSetCompiler.hasRuleForResource(rules, "/file.mts") ||
RuleSetCompiler.hasRuleForResource(rules, "/file.cts")
);
}
// `syncWebAssembly` already claims `.wasm`, so don't let "auto" override it.
if (experiments.asyncWebAssembly === "auto") {
experiments.asyncWebAssembly =
!experiments.syncWebAssembly &&
!RuleSetCompiler.hasRuleForResource(rules, "/file.wasm");
}
if (typeof experiments.buildHttp === "object") {
D(experiments.buildHttp, "frozen", production);
D(experiments.buildHttp, "upgrade", false);
}
};
/**
* Apply cache defaults.
* @param {CacheOptionsNormalized} cache options
* @param {object} options options
* @param {string} options.name name
* @param {Mode} options.mode mode
* @param {boolean} options.futureDefaults is future defaults enabled
* @param {boolean} options.development is development mode
* @param {number=} options.compilerIndex index of compiler
* @param {Experiments["cacheUnaffected"]} options.cacheUnaffected the cacheUnaffected experiment is enabled
* @returns {void}
*/
const applyCacheDefaults = (
cache,
{ name, mode, development, cacheUnaffected, compilerIndex, futureDefaults }
) => {
if (cache === false) return;
switch (cache.type) {
case "filesystem":
F(cache, "name", () =>
compilerIndex !== undefined
? `${`${name}-${mode}`}__compiler${compilerIndex + 1}__`
: `${name}-${mode}`
);
D(cache, "version", "");
F(cache, "cacheDirectory", () => {
const cwd = process.cwd();
/** @type {string | undefined} */
let dir = cwd;
for (;;) {
try {
if (fs.statSync(path.join(dir, "package.json")).isFile()) break;
// eslint-disable-next-line no-empty
} catch (_err) {}
const parent = path.dirname(dir);
if (dir === parent) {
dir = undefined;
break;
}
dir = parent;
}
if (!dir) {
return path.resolve(cwd, ".cache/webpack");
} else if (process.versions.pnp === "1") {
return path.resolve(dir, ".pnp/.cache/webpack");
} else if (process.versions.pnp === "3") {
return path.resolve(dir, ".yarn/.cache/webpack");
}
return path.resolve(dir, "node_modules/.cache/webpack");
});
F(cache, "cacheLocation", () =>
path.resolve(
/** @type {NonNullable<FileCacheOptions["cacheDirectory"]>} */
(cache.cacheDirectory),
/** @type {NonNullable<FileCacheOptions["name"]>} */ (cache.name)
)
);
D(cache, "hashAlgorithm", futureDefaults ? "xxhash64" : "md4");
D(cache, "store", "pack");
D(cache, "compression", false);
D(cache, "profile", false);
D(cache, "idleTimeout", 60000);
D(cache, "idleTimeoutForInitialStore", 5000);
D(cache, "idleTimeoutAfterLargeChanges", 1000);
D(cache, "maxMemoryGenerations", development ? 5 : Infinity);
D(cache, "maxAge", 1000 * 60 * 60 * 24 * 60); // 1 month
D(cache, "allowCollectingMemory", development);
D(cache, "memoryCacheUnaffected", development && cacheUnaffected);
D(cache, "readonly", false);
D(
/** @type {NonNullable<FileCacheOptions["buildDependencies"]>} */
(cache.buildDependencies),
"defaultWebpack",
[path.resolve(__dirname, "..") + path.sep]
);
break;
case "memory":
D(cache, "maxGenerations", Infinity);
D(cache, "cacheUnaffected", development && cacheUnaffected);
break;
}
};
/**
* Apply snapshot defaults.
* @param {SnapshotOptions} snapshot options
* @param {object} options options
* @param {boolean} options.production is production
* @param {boolean} options.futureDefaults is future defaults enabled
* @returns {void}
*/
const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
if (futureDefaults) {
F(snapshot, "managedPaths", () =>
process.versions.pnp === "3"
? [
/^(.+?(?:[\\/]\.yarn[\\/]unplugged[\\/][^\\/]+)?[\\/]node_modules[\\/])/
]
: [/^(.+?[\\/]node_modules[\\/])/]
);
F(snapshot, "immutablePaths", () =>
process.versions.pnp === "3"
? [/^(.+?[\\/]cache[\\/][^\\/]+\.zip[\\/]node_modules[\\/])/]
: []
);
} else {
A(snapshot, "managedPaths", () => {
if (process.versions.pnp === "3") {
const match =
/^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
require.resolve("watchpack")
);
if (match) {
return [path.resolve(match[1], "unplugged")];
}
} else {
const match = /^(.+?[\\/]node_modules[\\/])/.exec(
require.resolve("watchpack")
);
if (match) {
return [match[1]];
}
}
return [];
});
A(snapshot, "immutablePaths", () => {
if (process.versions.pnp === "1") {
const match =
/^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
require.resolve("watchpack")
);
if (match) {
return [match[1]];
}
} else if (process.versions.pnp === "3") {
const match =
/^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
require.resolve("watchpack")
);
if (match) {
return [match[1]];
}
}
return [];
});
}
F(snapshot, "unmanagedPaths", () => []);
F(snapshot, "resolveBuildDependencies", () => ({
timestamp: true,
hash: true
}));
F(snapshot, "buildDependencies", () => ({ timestamp: true, hash: true }));
F(snapshot, "module", () =>
production ? { timestamp: true, hash: true } : { timestamp: true }
);
F(snapshot, "contextModule", () => ({ timestamp: true }));
F(snapshot, "resolve", () =>
production ? { timestamp: true, hash: true } : { timestamp: true }
);
};
/**
* Apply javascript parser options defaults.
* @param {JavascriptParserOptions} parserOptions parser options
* @param {object} options options
* @param {boolean} options.futureDefaults is future defaults enabled
* @param {boolean} options.deferImport is defer import enabled
* @param {boolean} options.sourceImport is import source enabled
* @param {boolean} options.isNode is node target platform
* @param {boolean} options.outputModule is output.module enabled
* @param {WebpackOptionsNormalized["output"]["library"]} options.library library options
* @param {boolean} options.typescript is typescript enabled
* @returns {void}
*/
const applyJavascriptParserOptionsDefaults = (
parserOptions,
{
futureDefaults,
deferImport,
sourceImport,
isNode,
outputModule,
library,
typescript
}
) => {
D(parserOptions, "unknownContextRequest", ".");
D(parserOptions, "unknownContextRegExp", false);
D(parserOptions, "unknownContextRecursive", true);
D(parserOptions, "unknownContextCritical", true);
D(parserOptions, "exprContextRequest", ".");
D(parserOptions, "exprContextRegExp", false);
D(parserOptions, "exprContextRecursive", true);
D(parserOptions, "exprContextCritical", true);
D(parserOptions, "wrappedContextRegExp", /.*/);
D(parserOptions, "wrappedContextRecursive", true);
D(parserOptions, "wrappedContextCritical", false);
D(parserOptions, "strictThisContextOnImports", false);
D(parserOptions, "importMeta", outputModule ? "preserve-unknown" : true);
D(parserOptions, "dynamicImportMode", "lazy");
D(parserOptions, "dynamicImportPrefetch", false);
D(parserOptions, "dynamicImportPreload", false);
D(parserOptions, "dynamicImportFetchPriority", false);
D(parserOptions, "createRequire", isNode);
D(parserOptions, "dynamicUrl", true);
D(parserOptions, "deferImport", deferImport);
D(parserOptions, "sourceImport", sourceImport);
D(parserOptions, "typescript", typescript);
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
D(parserOptions, "strictModeViolations", futureDefaults ? "error" : "warn");
D(parserOptions, "anonymousDefaultExportName", !library);
};
/**
* Apply json generator options defaults.
* @param {JsonGeneratorOptions} generatorOptions generator options
* @returns {void}
*/
const applyJsonGeneratorOptionsDefaults = (generatorOptions) => {
D(generatorOptions, "JSONParse", true);
};
/**
* Apply css generator options defaults.
* @param {CssGeneratorOptions} generatorOptions generator options
* @param {object} options options
* @param {TargetProperties | false} options.targetProperties target properties
* @returns {void}
*/
const applyCssGeneratorOptionsDefaults = (
generatorOptions,
{ targetProperties }
) => {
D(
generatorOptions,
"exportsOnly",
!targetProperties || targetProperties.document === false
);
D(generatorOptions, "esModule", true);
};
/**
* Apply module defaults.
* @param {ModuleOptions} module options
* @param {object} options options
* @param {boolean} options.cache is caching enabled
* @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
* @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
* @param {boolean} options.typescript is typescript enabled
* @param {boolean} options.css is css enabled
* @param {boolean} options.html is html enabled
* @param {boolean} options.futureDefaults is future defaults enabled
* @param {string} options.uniqueName the unique name
* @param {boolean} options.isNode is node target platform
* @param {boolean} options.deferImport is defer import enabled
* @param {boolean} options.sourceImport is import source enabled
* @param {TargetProperties | false} options.targetProperties target properties
* @param {Mode | undefined} options.mode mode
* @param {HashSalt} options.hashSalt hash salt
* @param {HashFunction} options.hashFunction hash function
* @param {boolean} options.outputModule is output.module enabled
* @param {WebpackOptionsNormalized["output"]["library"]} options.library library options
* @returns {void}
*/
const applyModuleDefaults = (
module,
{
hashSalt,
hashFunction,
cache,
syncWebAssembly,
asyncWebAssembly,
css,
html,
typescript,
futureDefaults,
isNode,
uniqueName,
targetProperties,
mode,
deferImport,
sourceImport,
outputModule,
library
}
) => {
if (cache) {
D(
module,
"unsafeCache",
/**
* Handles the callback logic for this hook.
* @param {Module} module module
* @returns {boolean} true, if we want to cache the module
*/
(module) => {
const name = module.nameForCondition();
if (!name) {
return false;
}
return NODE_MODULES_REGEXP.test(name);
}
);
} else {
D(module, "unsafeCache", false);
}
F(module.parser, ASSET_MODULE_TYPE, () => ({}));
F(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
(module.parser[ASSET_MODULE_TYPE]),
"dataUrlCondition",
() => ({})
);
if (
typeof (
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
(module.parser[ASSET_MODULE_TYPE]).dataUrlCondition
) === "object"
) {
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
(module.parser[ASSET_MODULE_TYPE]).dataUrlCondition,
"maxSize",
8096
);
}
F(module.parser, "javascript", () => ({}));
F(module.parser, JSON_MODULE_TYPE, () => ({}));
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[JSON_MODULE_TYPE]>} */
(module.parser[JSON_MODULE_TYPE]),
"exportsDepth",
mode === "development" ? 1 : Infinity
);
applyJavascriptParserOptionsDefaults(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown["javascript"]>} */
(module.parser.javascript),
{
futureDefaults,
deferImport,
sourceImport,
isNode,
outputModule,
library,
typescript
}
);
F(module.generator, "json", () => ({}));
applyJsonGeneratorOptionsDefaults(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown["json"]>} */
(module.generator.json)
);
if (css) {
F(module.parser, CSS_MODULE_TYPE, () => ({}));
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.parser[CSS_MODULE_TYPE]),
"import",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.parser[CSS_MODULE_TYPE]),
"url",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.parser[CSS_MODULE_TYPE]),
"namedExports",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.parser[CSS_MODULE_TYPE]),
"customMedia",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.parser[CSS_MODULE_TYPE]),
"customSelectors",
true
);
for (const type of [
CSS_MODULE_TYPE_AUTO,
CSS_MODULE_TYPE_MODULE,
CSS_MODULE_TYPE_GLOBAL
]) {
F(module.parser, type, () => ({}));
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"animation",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"container",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"customIdents",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"dashedIdents",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"function",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"grid",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"customMedia",
true
);
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.parser[type]),
"customSelectors",
true
);
}
F(module.generator, CSS_MODULE_TYPE, () => ({}));
applyCssGeneratorOptionsDefaults(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
(module.generator[CSS_MODULE_TYPE]),
{ targetProperties }
);
const localIdentName =
mode === "development"
? uniqueName.length > 0
? "[uniqueName]-[id]-[local]"
: "[id]-[local]"
: "[fullhash]";
const localIdentHashSalt = hashSalt;
const localIdentHashDigest = "base64url";
const localIdentHashDigestLength = 6;
const exportsConvention = "as-is";
for (const type of [
CSS_MODULE_TYPE_AUTO,
CSS_MODULE_TYPE_MODULE,
CSS_MODULE_TYPE_GLOBAL
]) {
F(module.generator, type, () => ({}));
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.generator[type]),
"localIdentName",
localIdentName
);
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.generator[type]),
"localIdentHashSalt",
localIdentHashSalt
);
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]>} */
(module.generator[type]),
"localIdentHashFunction",
hashFunction
);
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]>} */
(module.generator[type]),
"localIdentHashDigest",
localIdentHashDigest
);
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]>} */
(module.generator[type]),
"localIdentHashDigestLength",
localIdentHashDigestLength
);
D(
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]> | NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
(module.generator[type]),
"exportsConvention",
exportsConvention
);
}
}
if (html) {
// `module.generator.html.extract` is intentionally left undefined by
// default: HtmlGenerator treats undefined as "extract iff this HTML
// module is a compilation entry", which is the HTML-entry-point
// behaviour. Setting `extract: true` forces extraction for all HTML
// modules (including imported ones); `extract: false` disables it
// everywhere.
F(module.generator, HTML_MODULE_TYPE, () => ({}));
// `module.parser.html.sources` defaults to `true` — HtmlParser uses
// the built-in source list to extract URL-like attributes (`<img
// src>`, `<link href>`, `<script src>`, …) as webpack dependencies.
// Users may pass `false` to disable extraction entirely or an array
// (with `"..."` to include the defaults) to customize it.
F(module.parser, HTML_MODULE_TYPE, () => ({}));
D(
/** @type {NonNullable<ParserOptionsByModuleTypeKnown[HTML_MODULE_TYPE]>} */
(module.parser[HTML_MODULE_TYPE]),
"sources",
true
);
}
A(module, "defaultRules", () => {
const esm = {
type: JAVASCRIPT_MODULE_TYPE_ESM,
resolve: {
byDependency: {
esm: {
fullySpecified: true
}
}
}
};
const commonjs = {
type: JAVASCRIPT_MODULE_TYPE_DYNAMIC
};
/** @type {RuleSetRules} */
const rules = [
{
mimetype: "application/node",
type: JAVASCRIPT_MODULE_TYPE_AUTO
},
{
test: /\.json$/i,
type: JSON_MODULE_TYPE
},
{
mimetype: "application/json",
type: JSON_MODULE_TYPE
},
{
test: /\.mjs$/i,
...esm
},
{
test: /\.js$/i,
descriptionData: {
type: "module"
},
...esm
},
{
test: /\.cjs$/i,
...commonjs
},
{
test: /\.js$/i,
descriptionData: {
type: "commonjs"
},
...commonjs
},
{
mimetype: {
or: ["text/javascript", "application/javascript"]
},
...esm
}
];
if (asyncWebAssembly) {
const wasm = {
type: WEBASSEMBLY_MODULE_TYPE_ASYNC,
rules: [
{
descriptionData: {
type: "module"
},
resolve: {
fullySpecified: true
}
}
]
};
rules.push({
test: /\.wasm$/i,
...wasm
});
rules.push({
mimetype: "application/wasm",
...wasm
});
} else if (syncWebAssembly) {
const wasm = {
type: WEBASSEMBLY_MODULE_TYPE_SYNC,
rules: [
{
descriptionData: {
type: "module"
},
resolve: {
fullySpecified: true
}
}
]
};
rules.push({
test: /\.wasm$/i,
...wasm
});
rules.push({
mimetype: "application/wasm",
...wasm
});
}
if (css) {
const resolve = {
fullySpecified: true,
preferRelative: true
};
rules.push({
test: /\.css$/i,
type: CSS_MODULE_TYPE_AUTO,
resolve
});
rules.push({
mimetype: "text/css+module",
type: CSS_MODULE_TYPE_MODULE,
resolve
});
rules.push({
mimetype: "text/css",
type: CSS_MODULE_TYPE,
resolve
});
// For CSS modules, i.e. `.class { composes: className from "./style.css" }`
// We inherit for such constructions, but skip files that are already
// detected as CSS modules by extension (`.module.<ext>`) — they get
// the same modules-mode behavior from the auto rule, and forcing a
// different type stamp here would create a duplicate module instance.
const moduleExtension = /\.module\.\w+$/i;
rules.push({
dependency: /css-import-local-module/,
exclude: moduleExtension,
type: CSS_MODULE_TYPE_MODULE,
resolve
});
rules.push({
dependency: /css-import-global-module/,
exclude: moduleExtension,
type: CSS_MODULE_TYPE_GLOBAL,
resolve
});
rules.push(
{
with: { type: "css" },
parser: {
exportType: "css-style-sheet"
},
resolve
},
{
assert: { type: "css" },
parser: {
exportType: "css-style-sheet"
},
resolve
}
);
}
if (html) {
const resolve = {
fullySpecified: true,
preferRelative: true
};
rules.push({
test: /\.html$/i,
type: HTML_MODULE_TYPE,
resolve
});
rules.push({
mimetype: "text/html",
type: HTML_MODULE_TYPE,
resolve
});
// `<iframe srcdoc>` content is fed back through the HTML pipeline as a
// `data:text/html` module. `extract: "inline"` exposes the processed
// HTML on the `html` codegen channel that `HtmlInlineHtmlDependency.
// Template` reads back into the attribute, without emitting a standalone
// `.html` file (the module is never a page on its own).
rules.push({
dependency: "html-srcdoc",
generator: {
extract: "inline"
},
resolve
});
if (css) {
// Inline `<style>` content in an HTML module is fed into the
// CSS pipeline as a `data:text/css` virtual module. We force
// `exportType: "text"` so the CSS module exposes the
// processed CSS text on the `css-text` codegen channel that
// `HtmlInlineStyleDependency.Template` reads back into the
// `<style>` tag.
rules.push({
dependency: "html-style",
parser: {
exportType: "text"
},
resolve
});
// A `style="..."` attribute is a CSS block's contents, not a
// stylesheet, so parse it as one (`as: "block-contents"`).
rules.push({
dependency: "html-styl