add experiments.asyncEntries

add async entries plugin
async entries in global parser options
allow chunkFormat, chunkFilename and initialChunkFilename for entries
This commit is contained in:
Tobias Koppers 2021-01-05 12:35:35 +01:00
parent 7fa009e254
commit d3cc2de2f9
39 changed files with 2578 additions and 311 deletions

View File

@ -56,90 +56,9 @@ export type EntryStatic = EntryObject | EntryUnnamed;
*/ */
export type EntryItem = string[] | string; export type EntryItem = string[] | string;
/** /**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins). * An object with entry point description.
*/ */
export type ChunkLoading = false | ChunkLoadingType; export type EntryDescription = EntryDescriptionOptions & EntryDescriptionExtra;
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
export type ChunkLoadingType =
| ("jsonp" | "import-scripts" | "require" | "async-node")
| string;
/**
* Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type EntryFilename = FilenameTemplate;
/**
* Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type FilenameTemplate =
| string
| ((
pathData: import("../lib/Compilation").PathData,
assetInfo?: import("../lib/Compilation").AssetInfo
) => string);
/**
* Specifies the layer in which modules of this entrypoint are placed.
*/
export type Layer = null | string;
/**
* Add a comment in the UMD wrapper.
*/
export type AuxiliaryComment = string | LibraryCustomUmdCommentObject;
/**
* Specify which export should be exposed as library.
*/
export type LibraryExport = string[] | string;
/**
* The name of the library (some types allow unnamed libraries too).
*/
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
export type LibraryType =
| (
| "var"
| "module"
| "assign"
| "assign-properties"
| "this"
| "window"
| "self"
| "global"
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "amd"
| "amd-require"
| "umd"
| "umd2"
| "jsonp"
| "system"
)
| string;
/**
* If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.
*/
export type UmdNamedDefine = boolean;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
export type EntryRuntime = string;
/**
* The name of the runtime that the entry will be associated to. Optimization for modules will be done per runtime.
*/
export type EntryRuntimeName = string;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
export type WasmLoading = false | WasmLoadingType;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
export type WasmLoadingType =
| ("fetch-streaming" | "fetch" | "async-node")
| string;
/** /**
* An entry point without name. * An entry point without name.
*/ */
@ -421,6 +340,10 @@ export type AssetModuleFilename =
pathData: import("../lib/Compilation").PathData, pathData: import("../lib/Compilation").PathData,
assetInfo?: import("../lib/Compilation").AssetInfo assetInfo?: import("../lib/Compilation").AssetInfo
) => string); ) => string);
/**
* Add a comment in the UMD wrapper.
*/
export type AuxiliaryComment = string | LibraryCustomUmdCommentObject;
/** /**
* Add charset attribute for script tag. * Add charset attribute for script tag.
*/ */
@ -429,14 +352,37 @@ export type Charset = boolean;
* Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk. * Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/ */
export type ChunkFilename = FilenameTemplate; export type ChunkFilename = FilenameTemplate;
/**
* Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type FilenameTemplate =
| string
| ((
pathData: import("../lib/Compilation").PathData,
assetInfo?: import("../lib/Compilation").AssetInfo
) => string);
/** /**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins). * The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/ */
export type ChunkFormat = ("array-push" | "commonjs" | false) | string; export type ChunkFormat = false | ChunkFormatType;
/**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/
export type ChunkFormatType = ("array-push" | "commonjs") | string;
/** /**
* Number of milliseconds before chunk request expires. * Number of milliseconds before chunk request expires.
*/ */
export type ChunkLoadTimeout = number; export type ChunkLoadTimeout = number;
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
export type ChunkLoading = false | ChunkLoadingType;
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
export type ChunkLoadingType =
| ("jsonp" | "import-scripts" | "require" | "async-node")
| string;
/** /**
* The global variable used by webpack for loading of chunks. * The global variable used by webpack for loading of chunks.
*/ */
@ -465,14 +411,48 @@ export type DevtoolModuleFilenameTemplate = string | Function;
* Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries. * Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.
*/ */
export type DevtoolNamespace = string; export type DevtoolNamespace = string;
/**
* List of chunk format types enabled for use by entry points.
*/
export type EnabledChunkFormatTypes = ChunkFormatType[];
/** /**
* List of chunk loading types enabled for use by entry points. * List of chunk loading types enabled for use by entry points.
*/ */
export type EnabledChunkLoadingTypes = ChunkLoadingType[]; export type EnabledChunkLoadingTypes = ChunkLoadingType[];
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
export type LibraryType =
| (
| "var"
| "module"
| "assign"
| "assign-properties"
| "this"
| "window"
| "self"
| "global"
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "amd"
| "amd-require"
| "umd"
| "umd2"
| "jsonp"
| "system"
)
| string;
/** /**
* List of library types enabled for use by entry points. * List of library types enabled for use by entry points.
*/ */
export type EnabledLibraryTypes = LibraryType[]; export type EnabledLibraryTypes = LibraryType[];
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
export type WasmLoadingType =
| ("fetch-streaming" | "fetch" | "async-node")
| string;
/** /**
* List of wasm loading types enabled for use by entry points. * List of wasm loading types enabled for use by entry points.
*/ */
@ -533,6 +513,18 @@ export type InitialChunkFilename = FilenameTemplate;
* Make the output files a library, exporting the exports of the entry point. * Make the output files a library, exporting the exports of the entry point.
*/ */
export type Library = LibraryName | LibraryOptions; export type Library = LibraryName | LibraryOptions;
/**
* The name of the library (some types allow unnamed libraries too).
*/
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Specify which export should be exposed as library.
*/
export type LibraryExport = string[] | string;
/**
* If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.
*/
export type UmdNamedDefine = boolean;
/** /**
* Output javascript files as module source type. * Output javascript files as module source type.
*/ */
@ -582,6 +574,10 @@ export type StrictModuleExceptionHandling = boolean;
* A unique name of the webpack build to avoid multiple webpack runtimes to conflict when using globals. * A unique name of the webpack build to avoid multiple webpack runtimes to conflict when using globals.
*/ */
export type UniqueName = string; export type UniqueName = string;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
export type WasmLoading = false | WasmLoadingType;
/** /**
* The filename of WebAssembly modules as relative path inside the 'output.path' directory. * The filename of WebAssembly modules as relative path inside the 'output.path' directory.
*/ */
@ -716,6 +712,27 @@ export type AssetParserDataUrlFunction = (
source: string | Buffer, source: string | Buffer,
context: {filename: string; module: import("../lib/Module")} context: {filename: string; module: import("../lib/Module")}
) => boolean; ) => boolean;
/**
* An object with entry point description.
*/
export type EntryDescriptionNamed = EntryDescriptionOptions &
EntryDescriptionNamedExtra;
/**
* Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type EntryFilename = FilenameTemplate;
/**
* Specifies the layer in which modules of this entrypoint are placed.
*/
export type Layer = null | string;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
export type EntryRuntime = string;
/**
* The name of the runtime that the entry will be associated to. Optimization for modules will be done per runtime.
*/
export type EntryRuntimeName = string;
/** /**
* A Function returning a Promise resolving to a normalized entry. * A Function returning a Promise resolving to a normalized entry.
*/ */
@ -1001,110 +1018,6 @@ export interface EntryObject {
*/ */
[k: string]: EntryItem | EntryDescription; [k: string]: EntryItem | EntryDescription;
} }
/**
* An object with entry point description.
*/
export interface EntryDescription {
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
chunkLoading?: ChunkLoading;
/**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/
dependOn?: string[] | string;
/**
* Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
filename?: EntryFilename;
/**
* Module(s) that are loaded upon startup.
*/
import: EntryItem;
/**
* Specifies the layer in which modules of this entrypoint are placed.
*/
layer?: Layer;
/**
* Options for library.
*/
library?: LibraryOptions;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: EntryRuntime;
/**
* The name of the runtime that the entry will be associated to. Optimization for modules will be done per runtime.
*/
runtimeName?: EntryRuntimeName;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
wasmLoading?: WasmLoading;
}
/**
* Options for library.
*/
export interface LibraryOptions {
/**
* Add a comment in the UMD wrapper.
*/
auxiliaryComment?: AuxiliaryComment;
/**
* Specify which export should be exposed as library.
*/
export?: LibraryExport;
/**
* The name of the library (some types allow unnamed libraries too).
*/
name?: LibraryName;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
type: LibraryType;
/**
* If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.
*/
umdNamedDefine?: UmdNamedDefine;
}
/**
* Set explicit comments for `commonjs`, `commonjs2`, `amd`, and `root`.
*/
export interface LibraryCustomUmdCommentObject {
/**
* Set comment for `amd` section in UMD.
*/
amd?: string;
/**
* Set comment for `commonjs` (exports) section in UMD.
*/
commonjs?: string;
/**
* Set comment for `commonjs2` (module.exports) section in UMD.
*/
commonjs2?: string;
/**
* Set comment for `root` (global variable) section in UMD.
*/
root?: string;
}
/**
* Description object for all UMD variants of the library name.
*/
export interface LibraryCustomUmdObject {
/**
* Name of the exposed AMD library in the UMD.
*/
amd?: string;
/**
* Name of the exposed commonjs export in the UMD.
*/
commonjs?: string;
/**
* Name of the property exposed globally by a UMD library.
*/
root?: string[] | string;
}
/** /**
* Enables/Disables experiments (experimental features with relax SemVer compatibility). * Enables/Disables experiments (experimental features with relax SemVer compatibility).
*/ */
@ -1113,6 +1026,10 @@ export interface Experiments {
* Allow module type 'asset' to generate assets. * Allow module type 'asset' to generate assets.
*/ */
asset?: boolean; asset?: boolean;
/**
* Allow to configure that async entries can be parsed.
*/
asyncEntries?: boolean;
/** /**
* Support WebAssembly as asynchronous EcmaScript Module. * Support WebAssembly as asynchronous EcmaScript Module.
*/ */
@ -1973,6 +1890,10 @@ export interface Output {
* Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries. * Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.
*/ */
devtoolNamespace?: DevtoolNamespace; devtoolNamespace?: DevtoolNamespace;
/**
* List of chunk format types enabled for use by entry points.
*/
enabledChunkFormatTypes?: EnabledChunkFormatTypes;
/** /**
* List of chunk loading types enabled for use by entry points. * List of chunk loading types enabled for use by entry points.
*/ */
@ -2114,6 +2035,27 @@ export interface Output {
*/ */
workerWasmLoading?: WasmLoading; workerWasmLoading?: WasmLoading;
} }
/**
* Set explicit comments for `commonjs`, `commonjs2`, `amd`, and `root`.
*/
export interface LibraryCustomUmdCommentObject {
/**
* Set comment for `amd` section in UMD.
*/
amd?: string;
/**
* Set comment for `commonjs` (exports) section in UMD.
*/
commonjs?: string;
/**
* Set comment for `commonjs2` (module.exports) section in UMD.
*/
commonjs2?: string;
/**
* Set comment for `root` (global variable) section in UMD.
*/
root?: string;
}
/** /**
* Advanced options for cleaning assets. * Advanced options for cleaning assets.
*/ */
@ -2160,6 +2102,48 @@ export interface Environment {
*/ */
module?: boolean; module?: boolean;
} }
/**
* Description object for all UMD variants of the library name.
*/
export interface LibraryCustomUmdObject {
/**
* Name of the exposed AMD library in the UMD.
*/
amd?: string;
/**
* Name of the exposed commonjs export in the UMD.
*/
commonjs?: string;
/**
* Name of the property exposed globally by a UMD library.
*/
root?: string[] | string;
}
/**
* Options for library.
*/
export interface LibraryOptions {
/**
* Add a comment in the UMD wrapper.
*/
auxiliaryComment?: AuxiliaryComment;
/**
* Specify which export should be exposed as library.
*/
export?: LibraryExport;
/**
* The name of the library (some types allow unnamed libraries too).
*/
name?: LibraryName;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
type: LibraryType;
/**
* If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.
*/
umdNamedDefine?: UmdNamedDefine;
}
/** /**
* Configuration object for web performance recommendations. * Configuration object for web performance recommendations.
*/ */
@ -2664,22 +2648,79 @@ export interface EmptyParserOptions {}
* An object with entry point description. * An object with entry point description.
*/ */
export interface EntryDescriptionNormalized { export interface EntryDescriptionNormalized {
/**
* Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
chunkFilename?: ChunkFilename;
/**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/
chunkFormat?: ChunkFormatType;
/** /**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins). * The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/ */
chunkLoading?: ChunkLoading; chunkLoading?: ChunkLoadingType;
/** /**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded. * The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/ */
dependOn?: string[]; dependOn?: string[];
/** /**
* Specifies the filename of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk. * Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/ */
filename?: Filename; filename?: EntryFilename;
/** /**
* Module(s) that are loaded upon startup. The last one is exported. * Module(s) that are loaded upon startup. The last one is exported.
*/ */
import?: string[]; import?: string[];
/**
* Specifies the filename template of output files of initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
initialChunkFilename?: InitialChunkFilename;
/**
* Specifies the layer in which modules of this entrypoint are placed.
*/
layer?: Layer;
/**
* Options for library.
*/
library?: LibraryOptions;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: EntryRuntime;
/**
* The name of the runtime that the entry will be associated to. Optimization for modules will be done per runtime.
*/
runtimeName?: EntryRuntimeName;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/
wasmLoading?: WasmLoading;
}
/**
* An object with entry point description.
*/
export interface EntryDescriptionOptions {
/**
* Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
chunkFilename?: ChunkFilename;
/**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/
chunkFormat?: ChunkFormatType;
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
chunkLoading?: ChunkLoadingType;
/**
* Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
filename?: EntryFilename;
/**
* Specifies the filename template of output files of initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
initialChunkFilename?: InitialChunkFilename;
/** /**
* Specifies the layer in which modules of this entrypoint are placed. * Specifies the layer in which modules of this entrypoint are placed.
*/ */
@ -2739,6 +2780,38 @@ export interface ExternalItemFunctionData {
*/ */
request?: string; request?: string;
} }
/**
* Options for any async entrypoint.
*/
export interface JavascriptParserAsyncEntryDescription {
/**
* Determine values based on custom logic. First argument is an context object, second and following arguments are values passed in source code. Return value is merged with the static values.
*/
byArguments?: (
info: {expression: import("estree").Expression},
...args: any[]
) => false | JavascriptParserAsyncEntryDescription;
/**
* Specify the dependency type of the request that is used for resolving.
*/
dependencyType?: string;
/**
* An object with entry point description.
*/
entryOptions?: EntryDescriptionNamed;
/**
* Specify the request to reference a module.
*/
request?: string;
/**
* Specify the returned value (void: returns undefined, files: returns an array of filenames, urls: returns an array of URLs).
*/
return?: "void" | "files" | "urls";
/**
* Any JSON value that should be returned.
*/
value?: any;
}
/** /**
* Parser options for javascript modules. * Parser options for javascript modules.
*/ */
@ -2759,6 +2832,17 @@ export interface JavascriptParserOptions {
* Enable/disable parsing of magic comments in CommonJs syntax. * Enable/disable parsing of magic comments in CommonJs syntax.
*/ */
commonjsMagicComments?: boolean; commonjsMagicComments?: boolean;
/**
* Disable or configure handling of async entrypoints specified in source code.
*/
entries?:
| false
| {
/**
* Specify behavior of this async entrypoint.
*/
[k: string]: false | JavascriptParserAsyncEntryDescription;
};
/** /**
* Enable warnings for full dynamic dependencies. * Enable warnings for full dynamic dependencies.
*/ */
@ -2938,6 +3022,10 @@ export interface OutputNormalized {
* Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries. * Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.
*/ */
devtoolNamespace?: DevtoolNamespace; devtoolNamespace?: DevtoolNamespace;
/**
* List of chunk format types enabled for use by entry points.
*/
enabledChunkFormatTypes?: EnabledChunkFormatTypes;
/** /**
* List of chunk loading types enabled for use by entry points. * List of chunk loading types enabled for use by entry points.
*/ */
@ -3208,6 +3296,28 @@ export interface WebpackOptionsNormalized {
*/ */
watchOptions: WatchOptions; watchOptions: WatchOptions;
} }
/**
* An object with entry point description.
*/
export interface EntryDescriptionExtra {
/**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/
dependOn?: string[] | string;
/**
* Module(s) that are loaded upon startup.
*/
import: EntryItem;
}
/**
* An object with entry point description.
*/
export interface EntryDescriptionNamedExtra {
/**
* Name of this entrypoint.
*/
name?: string;
}
/** /**
* If an dependency matches exactly a property of the object, the property value is used as dependency. * If an dependency matches exactly a property of the object, the property value is used as dependency.
*/ */

View File

@ -0,0 +1,878 @@
# webpack.config.js
```javascript
/** @type {import("../../").Configuration} */
module.exports = {
entry: {
page: {
import: "./page.js",
layer: "server",
library: {
type: "commonjs-module",
export: "default"
}
}
},
target: "node",
output: {
filename: "[name].js",
chunkFilename: "[name].js"
},
module: {
parser: {
javascript: {
entries: {
CLIENT: {
entryOptions: {
name: "client",
layer: "client",
chunkLoading: "jsonp",
chunkFormat: "array-push",
initialChunkFilename: "client/[name].js",
chunkFilename: "client/[name].js"
},
return: "files"
},
CLIENT_MODERN: {
entryOptions: {
name: "modern",
layer: "modern",
chunkLoading: "jsonp",
chunkFormat: "array-push",
initialChunkFilename: "client/modern-[name].js",
chunkFilename: "client/modern-[name].js"
},
return: "files"
},
API: {
entryOptions: {
layer: "server",
chunkLoading: "require",
chunkFormat: "commonjs",
runtime: "api-runtime",
library: {
type: "commonjs-module",
export: "default"
}
},
byArguments: (info, request, name) => ({
entryOptions: {
name: `api/${name}`
},
value: `/${name}`
})
}
}
}
}
},
optimization: {
splitChunks: {
cacheGroups: {
merge: {
name: "merged",
test: /helper/,
layer: "server",
enforce: true
}
}
}
},
externals: {
byLayer: {
server: {
react: "react"
}
}
},
experiments: {
topLevelAwait: true,
layers: true,
asyncEntries: true
}
};
```
# page.js
```javascript
import { log } from "./helper";
const urls = CLIENT("./client.js");
const modernUrls = CLIENT_MODERN("./client.js");
const head = [
...urls.map(href =>
href.endsWith(".js")
? `<script nomodule src="${href}">`
: href.endsWith(".css")
? `<link href="${href}">`
: ""
),
...modernUrls.map(href => `<script type="module" src="${href}">`)
].join("");
export default () => {
log("Generating page");
return `<html><head>${head}</head></html>`;
};
```
# client.js
```javascript
import { log } from "./helper.js";
log(await import("./callTextApi.js"));
fetch(API("./trackUser.js", "analytics/track")).catch(() => {});
export {};
document.addEventListener("load", () => {
if (__webpack_layer__ === "modern") {
navigator.serviceWorker.register(
/* webpackEntryOptions: { filename: "client/sw.js" } */
new URL("./sw.js", import.meta.url)
);
}
if (__webpack_layer__ === "client") {
navigator.serviceWorker.register(
/* webpackEntryOptions: { filename: "client/modern-sw.js" } */
new URL("./sw.js", import.meta.url)
);
}
});
```
# callTextApi.js
```javascript
const url = API("./getText.js", "getText");
const res = await fetch(url);
export default await res.text();
```
# getText.js
```javascript
import { log } from "./helper";
export default () => {
log("api called");
return "Hello World";
};
```
# dist/page.js
```javascript
module.exports =
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */
/*!*****************!*\
!*** ./page.js ***!
\*****************/
/*! namespace exports */
/*! export default [provided] [used in page] [usage prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_exports__, __webpack_require__.r, __webpack_require__.u, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helper */ 1);
const urls = /* async entry files */ [3].map(__webpack_require__.u);
const modernUrls = /* async entry files */ [5].map(__webpack_require__.u);
const head = [
...urls.map(href =>
href.endsWith(".js")
? `<script nomodule src="${href}">`
: href.endsWith(".css")
? `<link href="${href}">`
: ""
),
...modernUrls.map(href => `<script type="module" src="${href}">`)
].join("");
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (() => {
(0,_helper__WEBPACK_IMPORTED_MODULE_0__.log)("Generating page");
return `<html><head>${head}</head></html>`;
});
/***/ }),
/* 1 */
/*!*******************!*\
!*** ./helper.js ***!
\*******************/
/*! namespace exports */
/*! export log [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "log": () => /* binding */ log
/* harmony export */ });
function log(msg) {
console.log(msg);
}
/***/ })
/******/ ]);
```
<details><summary><code>/* webpack runtime code */</code></summary>
``` js
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames not based on template
/******/ if (chunkId === 3) return "client/client.js";
/******/ // return url for filenames based on template
/******/ return "client/modern-" + "modern" + ".js";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
```
</details>
``` js
/******/ // module exports must be returned from runtime so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })()
.default;
```
# dist/client/client.js
```javascript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */,
/* 2 */
/*!*******************!*\
!*** ./client.js ***!
\*******************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, module, __webpack_require__.e, __webpack_require__.p, __webpack_require__.b, __webpack_require__.u, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _helper_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helper.js */ 3);
(0,_helper_js__WEBPACK_IMPORTED_MODULE_0__.log)(await __webpack_require__.e(/*! import() */ 9).then(__webpack_require__.bind(__webpack_require__, /*! ./callTextApi.js */ 6)));
fetch("/analytics/track").catch(() => {});
document.addEventListener("load", () => {
if (false) {}
if (true) {
navigator.serviceWorker.register(
/* webpackEntryOptions: { filename: "client/modern-sw.js" } */
new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(7), __webpack_require__.b)
);
}
});
return __webpack_exports__;
})();
/***/ }),
/* 3 */
/*!*******************!*\
!*** ./helper.js ***!
\*******************/
/*! namespace exports */
/*! export log [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "log": () => /* binding */ log
/* harmony export */ });
function log(msg) {
console.log(msg);
}
/***/ })
/******/ ]);
```
<details><summary><code>/* webpack runtime code */</code></summary>
``` js
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames not based on template
/******/ if (chunkId === 9) return "client/9.js";
/******/ if (chunkId === 7) return "client/modern-sw.js";
/******/ // return url for filenames based on template
/******/ return "" + {"1":"api/analytics/track","2":"api/getText"}[chunkId] + ".js";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ // data-webpack is not used as build has no uniqueName
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key) => {
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
/******/ var script, needAttach;
/******/ if(key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for(var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if(s.getAttribute("src") == url) { script = s; break; }
/******/ }
/******/ }
/******/ if(!script) {
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/
/******/ script.src = url;
/******/ }
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => fn(event));
/******/ if(prev) return prev(event);
/******/ }
/******/ ;
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ __webpack_require__.p = "dist/";
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ __webpack_require__.b = document.baseURI || self.location.href;
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // Promise = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ 3: 0
/******/ };
/******/
/******/
/******/ __webpack_require__.f.j = (chunkId, promises) => {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if(true) { // all chunks have JS
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => {
/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
/******/ });
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId);
/******/ } else installedChunks[chunkId] = 0;
/******/ }
/******/ }
/******/ };
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ // no deferred startup
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) runtime(__webpack_require__);
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ while(resolves.length) {
/******/ resolves.shift()();
/******/ }
/******/
/******/ }
/******/
/******/ var chunkLoadingGlobal = global["webpackChunk"] = global["webpackChunk"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/
/******/ // no deferred startup
/******/ })();
/******/
/************************************************************************/
```
</details>
``` js
/******/ // startup
/******/ // Load entry module
/******/ __webpack_require__(2);
/******/ // This entry module used 'module' so it can't be inlined
/******/ })()
;
```
# dist/api/getText.js
```javascript
module.exports =
(() => {
var exports = {};
exports.id = 2;
exports.ids = [2];
exports.modules = {
/***/ 11:
/*!********************!*\
!*** ./getText.js ***!
\********************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_exports__, __webpack_require__.r, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helper */ 1);
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (() => {
(0,_helper__WEBPACK_IMPORTED_MODULE_0__.log)("api called");
return "Hello World";
});
/***/ })
};
;
// load runtime
var __webpack_require__ = require("../api-runtime.js");
__webpack_require__.C(exports);
return __webpack_require__.X([4], 11);
})().default;
```
# Info
## Unoptimized
```
assets by path client/*.js 31.4 KiB
asset client/client.js 11.6 KiB [emitted] (name: client)
asset client/modern-modern.js 11.6 KiB [emitted] (name: modern)
asset client/modern-sw.js 3.19 KiB [emitted]
asset client/sw.js 3.19 KiB [emitted]
asset client/modern-10.js 948 bytes [emitted]
asset client/9.js 946 bytes [emitted]
assets by path *.js 10.5 KiB
asset page.js 4.96 KiB [emitted] (name: page)
asset api-runtime.js 4.8 KiB [emitted] (name: api-runtime)
asset merged.js 765 bytes [emitted] (name: merged) (id hint: merge)
assets by path api/ 2.4 KiB
asset api/getText.js 1.2 KiB [emitted] (name: api/getText)
asset api/analytics/track.js 1.2 KiB [emitted] (name: api/analytics/track)
chunk (runtime: api-runtime) api-runtime.js (api-runtime) [chunk format commonjs] 2.05 KiB [entry] [rendered]
> ./client.js 5:6-46
> ./client.js 5:6-46
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
runtime modules 2.05 KiB 7 modules
chunk (runtime: api-runtime) api/analytics/track.js (api/analytics/track) [chunk format commonjs] 94 bytes [rendered]
> ./client.js 5:6-46
> ./client.js 5:6-46
./trackUser.js (in server) 94 bytes [built] [code generated]
[exports: default]
[used exports unknown]
async entry ./trackUser.js ./client.js 5:6-46
async entry ./trackUser.js ./client.js 5:6-46
chunk (runtime: api-runtime) api/getText.js (api/getText) [chunk format commonjs] 102 bytes [rendered]
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
./getText.js (in server) 102 bytes [built] [code generated]
[exports: default]
[used exports unknown]
async entry ./getText.js ./callTextApi.js 1:12-42
async entry ./getText.js ./callTextApi.js 1:12-42
chunk (runtime: ./page.js|server|3:13-34) client/client.js (client) [chunk format array-push] 617 bytes (javascript) 5.77 KiB (runtime) [entry] [rendered]
> ./page.js 3:13-34
runtime modules 5.77 KiB 8 modules
dependent modules 48 bytes [dependent] 1 module
./client.js (in client) 569 bytes [built] [code generated]
[no exports]
[used exports unknown]
async entry ./client.js ./page.js 3:13-34
chunk (runtime: api-runtime) merged.js (merged) (id hint: merge) [chunk format commonjs] 48 bytes [rendered] split chunk (cache group: merge) (name: merged)
> ./client.js 5:6-46
> ./client.js 5:6-46
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
./helper.js (in server) 48 bytes [built] [code generated]
[exports: log]
[used exports unknown]
harmony side effect evaluation ./helper ./getText.js 1:0-31
harmony import specifier ./helper ./getText.js 4:1-4
harmony side effect evaluation ./helper ./page.js 1:0-31
harmony import specifier ./helper ./page.js 18:1-4
harmony side effect evaluation ./helper ./trackUser.js 1:0-31
harmony import specifier ./helper ./trackUser.js 4:1-4
chunk (runtime: ./page.js|server|4:19-47) client/modern-modern.js (modern) [chunk format array-push] 617 bytes (javascript) 5.77 KiB (runtime) [entry] [rendered]
> ./page.js 4:19-47
runtime modules 5.77 KiB 8 modules
dependent modules 48 bytes [dependent] 1 module
./client.js (in modern) 569 bytes [built] [code generated]
[no exports]
[used exports unknown]
async entry ./client.js ./page.js 4:19-47
chunk (runtime: page) page.js (page) 509 bytes (javascript) 948 bytes (runtime) [entry] [rendered]
> ./page.js page
runtime modules 948 bytes 4 modules
dependent modules 48 bytes [dependent] 1 module
./page.js (in server) 461 bytes [built] [code generated]
[exports: default]
[used exports unknown]
entry ./page.js page
used as library export
chunk (runtime: ./client.js|client|17:2-20:3) client/modern-sw.js 112 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./client.js 17:2-20:3
runtime modules 668 bytes 3 modules
dependent modules 48 bytes [dependent] 1 module
./sw.js (in client) 64 bytes [built] [code generated]
[used exports unknown]
new Worker() ./sw.js ./client.js 17:2-20:3
chunk (runtime: ./client.js|modern|11:2-14:3) client/sw.js 112 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./client.js 11:2-14:3
runtime modules 668 bytes 3 modules
dependent modules 48 bytes [dependent] 1 module
./sw.js (in modern) 64 bytes [built] [code generated]
[used exports unknown]
new Worker() ./sw.js ./client.js 11:2-14:3
chunk (runtime: ./page.js|server|3:13-34) client/9.js [chunk format array-push] 108 bytes [rendered]
> ./callTextApi.js ./client.js 3:10-36
./callTextApi.js (in client) 108 bytes [built] [code generated]
[exports: default]
[used exports unknown]
import() ./callTextApi.js ./client.js 3:10-36
chunk (runtime: ./page.js|server|4:19-47) client/modern-10.js [chunk format array-push] 108 bytes [rendered]
> ./callTextApi.js ./client.js 3:10-36
./callTextApi.js (in modern) 108 bytes [built] [code generated]
[exports: default]
[used exports unknown]
import() ./callTextApi.js ./client.js 3:10-36
webpack 5.11.1 compiled successfully
```
## Production mode
```
assets by path client/*.js 6.2 KiB
asset client/modern-modern.js 2.35 KiB [emitted] [minimized] (name: modern)
asset client/client.js 2.34 KiB [emitted] [minimized] (name: client)
asset client/modern-sw.js 583 bytes [emitted] [minimized]
asset client/sw.js 583 bytes [emitted] [minimized]
asset client/945.js 192 bytes [emitted] [minimized]
asset client/modern-935.js 192 bytes [emitted] [minimized]
assets by path *.js 1.59 KiB
asset api-runtime.js 780 bytes [emitted] [minimized] (name: api-runtime)
asset page.js 727 bytes [emitted] [minimized] (name: page)
asset merged.js 125 bytes [emitted] [minimized] (name: merged) (id hint: merge)
assets by path api/ 492 bytes
asset api/analytics/track.js 247 bytes [emitted] [minimized] (name: api/analytics/track)
asset api/getText.js 245 bytes [emitted] [minimized] (name: api/getText)
chunk (runtime: ./page.js|server|3:13-34) client/client.js (client) [chunk format array-push] 617 bytes (javascript) 5.78 KiB (runtime) [entry] [rendered]
> ./page.js 3:13-34
runtime modules 5.78 KiB 8 modules
dependent modules 48 bytes [dependent] 1 module
./client.js (in client) 569 bytes [built] [code generated]
[no exports]
async entry ./client.js ./page.js + 1 modules ./page.js 3:13-34
chunk (runtime: ./client.js|modern|11:2-14:3) client/sw.js 112 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./client.js 11:2-14:3
runtime modules 668 bytes 3 modules
dependent modules 48 bytes [dependent] 1 module
./sw.js (in modern) 64 bytes [built] [code generated]
[no exports used]
new Worker() ./sw.js ./client.js 11:2-14:3
chunk (runtime: api-runtime) api-runtime.js (api-runtime) [chunk format commonjs] 2.06 KiB [entry] [rendered]
> ./client.js 5:6-46
> ./client.js 5:6-46
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
runtime modules 2.06 KiB 7 modules
chunk (runtime: ./page.js|server|4:19-47) client/modern-modern.js (modern) [chunk format array-push] 617 bytes (javascript) 5.78 KiB (runtime) [entry] [rendered]
> ./page.js 4:19-47
runtime modules 5.78 KiB 8 modules
dependent modules 48 bytes [dependent] 1 module
./client.js (in modern) 569 bytes [built] [code generated]
[no exports]
async entry ./client.js ./page.js + 1 modules ./page.js 4:19-47
chunk (runtime: api-runtime) api/analytics/track.js (api/analytics/track) [chunk format commonjs] 94 bytes [rendered]
> ./client.js 5:6-46
> ./client.js 5:6-46
./trackUser.js (in server) 94 bytes [built] [code generated]
[exports: default]
async entry ./trackUser.js ./client.js 5:6-46
async entry ./trackUser.js ./client.js 5:6-46
chunk (runtime: api-runtime) api/getText.js (api/getText) [chunk format commonjs] 102 bytes [rendered]
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
./getText.js (in server) 102 bytes [built] [code generated]
[exports: default]
async entry ./getText.js ./callTextApi.js 1:12-42
async entry ./getText.js ./callTextApi.js 1:12-42
chunk (runtime: ./client.js|client|17:2-20:3) client/modern-sw.js 112 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./client.js 17:2-20:3
runtime modules 668 bytes 3 modules
dependent modules 48 bytes [dependent] 1 module
./sw.js (in client) 64 bytes [built] [code generated]
[no exports used]
new Worker() ./sw.js ./client.js 17:2-20:3
chunk (runtime: api-runtime) merged.js (merged) (id hint: merge) [chunk format commonjs] 48 bytes [rendered] split chunk (cache group: merge) (name: merged)
> ./client.js 5:6-46
> ./client.js 5:6-46
> ./callTextApi.js 1:12-42
> ./callTextApi.js 1:12-42
./helper.js (in server) 48 bytes [built] [code generated]
[exports: log]
[all exports used]
[inactive] harmony side effect evaluation ./helper ./getText.js 1:0-31
harmony import specifier ./helper ./getText.js 4:1-4
[inactive] harmony side effect evaluation ./helper ./trackUser.js 1:0-31
harmony import specifier ./helper ./trackUser.js 4:1-4
chunk (runtime: page) page.js (page) 509 bytes (javascript) 675 bytes (runtime) [entry] [rendered]
> ./page.js page
runtime modules 675 bytes 3 modules
./page.js + 1 modules (in server) 509 bytes [built] [code generated]
[exports: default]
[all exports used]
entry ./page.js page
used as library export
chunk (runtime: ./page.js|server|4:19-47) client/modern-935.js [chunk format array-push] 108 bytes [rendered]
> ./callTextApi.js ./client.js 3:10-36
./callTextApi.js (in modern) 108 bytes [built] [code generated]
[exports: default]
import() ./callTextApi.js ./client.js 3:10-36
chunk (runtime: ./page.js|server|3:13-34) client/945.js [chunk format array-push] 108 bytes [rendered]
> ./callTextApi.js ./client.js 3:10-36
./callTextApi.js (in client) 108 bytes [built] [code generated]
[exports: default]
import() ./callTextApi.js ./client.js 3:10-36
webpack 5.11.1 compiled successfully
```

View File

@ -0,0 +1,2 @@
global.NO_TARGET_ARGS = true;
require("../build-common");

View File

@ -0,0 +1,4 @@
const url = API("./getText.js", "getText");
const res = await fetch(url);
export default await res.text();

View File

@ -0,0 +1,22 @@
import { log } from "./helper.js";
log(await import("./callTextApi.js"));
fetch(API("./trackUser.js", "analytics/track")).catch(() => {});
export {};
document.addEventListener("load", () => {
if (__webpack_layer__ === "modern") {
navigator.serviceWorker.register(
/* webpackEntryOptions: { filename: "client/sw.js" } */
new URL("./sw.js", import.meta.url)
);
}
if (__webpack_layer__ === "client") {
navigator.serviceWorker.register(
/* webpackEntryOptions: { filename: "client/modern-sw.js" } */
new URL("./sw.js", import.meta.url)
);
}
});

View File

@ -0,0 +1,6 @@
import { log } from "./helper";
export default () => {
log("api called");
return "Hello World";
};

View File

@ -0,0 +1,3 @@
export function log(msg) {
console.log(msg);
}

View File

@ -0,0 +1,20 @@
import { log } from "./helper";
const urls = CLIENT("./client.js");
const modernUrls = CLIENT_MODERN("./client.js");
const head = [
...urls.map(href =>
href.endsWith(".js")
? `<script nomodule src="${href}">`
: href.endsWith(".css")
? `<link href="${href}">`
: ""
),
...modernUrls.map(href => `<script type="module" src="${href}">`)
].join("");
export default () => {
log("Generating page");
return `<html><head>${head}</head></html>`;
};

View File

@ -0,0 +1,3 @@
const { log } = require("./helper");
log("in service worker");

View File

@ -0,0 +1,61 @@
# webpack.config.js
```javascript
_{{webpack.config.js}}_
```
# page.js
```javascript
_{{page.js}}_
```
# client.js
```javascript
_{{client.js}}_
```
# callTextApi.js
```javascript
_{{callTextApi.js}}_
```
# getText.js
```javascript
_{{getText.js}}_
```
# dist/page.js
```javascript
_{{dist/page.js}}_
```
# dist/client/client.js
```javascript
_{{dist/client/client.js}}_
```
# dist/api/getText.js
```javascript
_{{dist/api/getText.js}}_
```
# Info
## Unoptimized
```
_{{stdout}}_
```
## Production mode
```
_{{production:stdout}}_
```

View File

@ -0,0 +1,5 @@
import { log } from "./helper";
export default () => {
log("User is visiting the page");
};

View File

@ -0,0 +1,90 @@
/** @type {import("../../").Configuration} */
module.exports = {
entry: {
page: {
import: "./page.js",
layer: "server",
library: {
type: "commonjs-module",
export: "default"
}
}
},
target: "node",
output: {
filename: "[name].js",
chunkFilename: "[name].js"
},
module: {
parser: {
javascript: {
entries: {
CLIENT: {
entryOptions: {
name: "client",
layer: "client",
chunkLoading: "jsonp",
chunkFormat: "array-push",
initialChunkFilename: "client/[name].js",
chunkFilename: "client/[name].js"
},
return: "files"
},
CLIENT_MODERN: {
entryOptions: {
name: "modern",
layer: "modern",
chunkLoading: "jsonp",
chunkFormat: "array-push",
initialChunkFilename: "client/modern-[name].js",
chunkFilename: "client/modern-[name].js"
},
return: "files"
},
API: {
entryOptions: {
layer: "server",
chunkLoading: "require",
chunkFormat: "commonjs",
runtime: "api-runtime",
library: {
type: "commonjs-module",
export: "default"
}
},
byArguments: (info, request, name) => ({
entryOptions: {
name: `api/${name}`
},
value: `/${name}`
})
}
}
}
}
},
optimization: {
splitChunks: {
cacheGroups: {
merge: {
name: "merged",
test: /helper/,
layer: "server",
enforce: true
}
}
}
},
externals: {
byLayer: {
server: {
react: "react"
}
}
},
experiments: {
topLevelAwait: true,
layers: true,
asyncEntries: true
}
};

View File

@ -19,6 +19,8 @@ const { createArrayToSetDeprecationSet } = require("./util/deprecation");
const { mergeRuntime } = require("./util/runtime"); const { mergeRuntime } = require("./util/runtime");
/** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").ChunkFormatType} ChunkFormatType */
/** @typedef {import("../declarations/WebpackOptions").FilenameTemplate} FilenameTemplate */
/** @typedef {import("./ChunkGraph").ChunkFilterPredicate} ChunkFilterPredicate */ /** @typedef {import("./ChunkGraph").ChunkFilterPredicate} ChunkFilterPredicate */
/** @typedef {import("./ChunkGraph").ChunkSizeOptions} ChunkSizeOptions */ /** @typedef {import("./ChunkGraph").ChunkSizeOptions} ChunkSizeOptions */
/** @typedef {import("./ChunkGraph").ModuleFilterPredicate} ModuleFilterPredicate */ /** @typedef {import("./ChunkGraph").ModuleFilterPredicate} ModuleFilterPredicate */
@ -34,6 +36,46 @@ const { mergeRuntime } = require("./util/runtime");
const ChunkFilesSet = createArrayToSetDeprecationSet("chunk.files"); const ChunkFilesSet = createArrayToSetDeprecationSet("chunk.files");
/** @type {ChunkOptions} */
const EMPTY_CHUNK_OPTIONS = {};
/**
* @typedef {Object} ChunkOptions
* @property {FilenameTemplate=} initialChunkFilename
* @property {FilenameTemplate=} chunkFilename
* @property {ChunkFormatType=} chunkFormat
*/
/**
* @param {Set<ChunkGroup>} set set
* @returns {EntryOptions} the entrypoint
*/
const getEntryOptions = set => {
for (const chunkGroup of set) {
if (chunkGroup instanceof Entrypoint) {
return chunkGroup.options;
}
}
return undefined;
};
/**
* @param {Chunk} chunk the current chunk
* @param {Set<ChunkGroup>} set set
* @returns {boolean} the entrypoint
*/
const hasRuntime = (chunk, set) => {
for (const chunkGroup of set) {
if (
chunkGroup instanceof Entrypoint &&
chunkGroup.getRuntimeChunk() === chunk
) {
return true;
}
}
return false;
};
/** /**
* @typedef {Object} WithId an object who has an id property * * @typedef {Object} WithId an object who has an id property *
* @property {string | number} id the id of the object * @property {string | number} id the id of the object
@ -63,8 +105,9 @@ let debugId = 1000;
class Chunk { class Chunk {
/** /**
* @param {string=} name of chunk being created, is optional (for subclasses) * @param {string=} name of chunk being created, is optional (for subclasses)
* @param {ChunkOptions=} options chunk options
*/ */
constructor(name) { constructor(name, options = EMPTY_CHUNK_OPTIONS) {
/** @type {number | string | null} */ /** @type {number | string | null} */
this.id = null; this.id = null;
/** @type {(number|string)[] | null} */ /** @type {(number|string)[] | null} */
@ -99,6 +142,10 @@ class Chunk {
this.chunkReason = undefined; this.chunkReason = undefined;
/** @type {boolean} */ /** @type {boolean} */
this.extraAsync = false; this.extraAsync = false;
/** @type {ChunkOptions} */
this.options = options;
this._hasRuntime = hasRuntime.bind(null, this);
} }
// TODO remove in webpack 6 // TODO remove in webpack 6
@ -426,15 +473,7 @@ class Chunk {
* @returns {boolean} whether or not the Chunk will have a runtime * @returns {boolean} whether or not the Chunk will have a runtime
*/ */
hasRuntime() { hasRuntime() {
for (const chunkGroup of this._groups) { return this._groups.getFromUnorderedCache(this._hasRuntime);
if (
chunkGroup instanceof Entrypoint &&
chunkGroup.getRuntimeChunk() === this
) {
return true;
}
}
return false;
} }
/** /**
@ -462,12 +501,7 @@ class Chunk {
* @returns {EntryOptions | undefined} the entry options for this chunk * @returns {EntryOptions | undefined} the entry options for this chunk
*/ */
getEntryOptions() { getEntryOptions() {
for (const chunkGroup of this._groups) { return this._groups.getFromUnorderedCache(getEntryOptions);
if (chunkGroup instanceof Entrypoint) {
return chunkGroup.options;
}
}
return undefined;
} }
/** /**
@ -807,4 +841,5 @@ class Chunk {
} }
} }
Chunk.EMPTY_CHUNK_OPTIONS = EMPTY_CHUNK_OPTIONS;
module.exports = Chunk; module.exports = Chunk;

View File

@ -88,6 +88,7 @@ const { isSourceEqual } = require("./util/source");
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("./Cache")} Cache */ /** @typedef {import("./Cache")} Cache */
/** @typedef {import("./CacheFacade")} CacheFacade */ /** @typedef {import("./CacheFacade")} CacheFacade */
/** @typedef {import("./Chunk").ChunkOptions} ChunkOptions */
/** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */ /** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */
/** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */ /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
@ -1007,6 +1008,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
) )
}; };
/** @type {Map<string, ChunkOptions>} */
this._chunkOptionsCache = new Map();
this._chunkOptionsCache.set("||", Chunk.EMPTY_CHUNK_OPTIONS);
this._modulesCache = this.getCache("Compilation/modules"); this._modulesCache = this.getCache("Compilation/modules");
this._assetsCache = this.getCache("Compilation/assets"); this._assetsCache = this.getCache("Compilation/assets");
this._codeGenerationCache = this.getCache("Compilation/codeGeneration"); this._codeGenerationCache = this.getCache("Compilation/codeGeneration");
@ -1373,11 +1378,12 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
const dependencies = new Map(); const dependencies = new Map();
/** /**
* @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>} * @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null, contextInfo: Partial<ModuleFactoryCreateDataContextInfo>}>}
*/ */
const sortedDependencies = []; const sortedDependencies = [];
let currentBlock = module; let currentBlock = module;
let currentLayer = undefined;
let factoryCacheKey; let factoryCacheKey;
let factoryCacheValue; let factoryCacheValue;
@ -1395,8 +1401,12 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
const category = dep.category; const category = dep.category;
const cacheKey = const cacheKey =
category === esmDependencyCategory category === esmDependencyCategory
? resourceIdent ? currentLayer === undefined
: `${category}${resourceIdent}`; ? resourceIdent
: `${resourceIdent}${currentLayer}`
: currentLayer === undefined
? `${category}${resourceIdent}`
: `${category}${resourceIdent}${currentLayer}`;
const constructor = dep.constructor; const constructor = dep.constructor;
let innerMap; let innerMap;
let factory; let factory;
@ -1427,7 +1437,11 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
sortedDependencies.push({ sortedDependencies.push({
factory: factoryCacheValue2, factory: factoryCacheValue2,
dependencies: list, dependencies: list,
originModule: module originModule: module,
contextInfo:
currentLayer !== undefined
? { issuerLayer: currentLayer }
: undefined
}); });
} }
list.push(dep); list.push(dep);
@ -1437,6 +1451,15 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
}; };
const processDependenciesBlock = block => { const processDependenciesBlock = block => {
const oldLayer = currentLayer;
const { groupOptions } = block;
if (
groupOptions &&
groupOptions.entryOptions &&
groupOptions.entryOptions.layer
) {
currentLayer = groupOptions.entryOptions.layer;
}
if (block.dependencies) { if (block.dependencies) {
currentBlock = block; currentBlock = block;
for (const dep of block.dependencies) processDependency(dep); for (const dep of block.dependencies) processDependency(dep);
@ -1444,6 +1467,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
if (block.blocks) { if (block.blocks) {
for (const b of block.blocks) processDependenciesBlock(b); for (const b of block.blocks) processDependenciesBlock(b);
} }
currentLayer = oldLayer;
}; };
try { try {
@ -1804,7 +1828,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
this.processDependenciesQueue.stop(); this.processDependenciesQueue.stop();
this.factorizeQueue.stop(); this.factorizeQueue.stop();
} else { } else {
callback(); callback(err);
} }
} }
); );
@ -2224,11 +2248,15 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
const chunkGraphInit = new Map(); const chunkGraphInit = new Map();
for (const [name, { dependencies, includeDependencies, options }] of this for (const [name, { dependencies, includeDependencies, options }] of this
.entries) { .entries) {
const chunk = this.addChunk(name); const chunkOptions = this._getChunkOptionsFromEntryOptions(options);
const chunk = this.addChunk(name, chunkOptions);
if (options.filename) { if (options.filename) {
chunk.filenameTemplate = options.filename; chunk.filenameTemplate = options.filename;
} }
const entrypoint = new Entrypoint(options); const entrypoint = new Entrypoint({
...options,
layer: options.layer || null
});
if (!options.dependOn && !options.runtime) { if (!options.dependOn && !options.runtime) {
entrypoint.setRuntimeChunk(chunk); entrypoint.setRuntimeChunk(chunk);
} }
@ -2335,7 +2363,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
continue; continue;
} }
} else { } else {
chunk = this.addChunk(runtime); const entryChunk = entry.getEntrypointChunk();
chunk = this.addChunk(runtime, entryChunk.options);
chunk.preventIntegration = true; chunk.preventIntegration = true;
runtimeChunks.add(chunk); runtimeChunks.add(chunk);
} }
@ -2555,6 +2584,26 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
} }
} }
/**
* @param {EntryOptions} entryOptions entry options
* @returns {ChunkOptions} chunk options
*/
_getChunkOptionsFromEntryOptions(entryOptions) {
/** @type {ChunkOptions} */
const chunkOptions = {
chunkFilename: entryOptions.chunkFilename,
initialChunkFilename: entryOptions.initialChunkFilename,
chunkFormat: entryOptions.chunkFormat
};
const key = `${chunkOptions.chunkFilename || ""}|${
chunkOptions.initialChunkFilename || ""
}|${chunkOptions.chunkFormat || ""}`;
const cacheEntry = this._chunkOptionsCache.get(key);
if (cacheEntry !== undefined) return cacheEntry;
this._chunkOptionsCache.set(key, chunkOptions);
return chunkOptions;
}
/** /**
* @param {Module} module module to report from * @param {Module} module module to report from
* @param {DependenciesBlock[]} blocks blocks to report from * @param {DependenciesBlock[]} blocks blocks to report from
@ -2961,7 +3010,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
); );
} }
} }
const chunk = this.addChunk(name); const chunkOptions = this._getChunkOptionsFromEntryOptions(options);
const chunk = this.addChunk(name, chunkOptions);
if (options.filename) { if (options.filename) {
chunk.filenameTemplate = options.filename; chunk.filenameTemplate = options.filename;
} }
@ -2976,7 +3026,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
if (runtime) { if (runtime) {
let chunk = this.namedChunks.get(runtime); let chunk = this.namedChunks.get(runtime);
if (!chunk) { if (!chunk) {
chunk = this.addChunk(runtime); chunk = this.addChunk(runtime, chunkOptions);
chunk.preventIntegration = true; chunk.preventIntegration = true;
} }
entrypoint.unshiftChunk(chunk); entrypoint.unshiftChunk(chunk);
@ -2996,16 +3046,22 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
* and first looks to see if any named chunks already exist and reuse that chunk instead. * and first looks to see if any named chunks already exist and reuse that chunk instead.
* *
* @param {string=} name optional chunk name to be provided * @param {string=} name optional chunk name to be provided
* @returns {Chunk} create a chunk (invoked during seal event) * @param {ChunkOptions=} options optional chunk options
* @returns {Chunk} created chunk (invoked during seal event)
*/ */
addChunk(name) { addChunk(name, options) {
if (name) { if (name) {
const chunk = this.namedChunks.get(name); const chunk = this.namedChunks.get(name);
if (chunk !== undefined) { if (chunk !== undefined) {
if (options !== undefined && chunk.options !== options) {
throw new Error(
"Compilation.addChunk was called for an existing chunk with incompatible chunk options"
);
}
return chunk; return chunk;
} }
} }
const chunk = new Chunk(name); const chunk = new Chunk(name, options);
this.chunks.add(chunk); this.chunks.add(chunk);
ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph); ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph);
if (name) { if (name) {

View File

@ -59,11 +59,14 @@ class EntryOptionPlugin {
const options = { const options = {
name, name,
filename: desc.filename, filename: desc.filename,
initialChunkFilename: desc.initialChunkFilename,
chunkFilename: desc.chunkFilename,
runtime: desc.runtime, runtime: desc.runtime,
runtimeName: desc.runtimeName, runtimeName: desc.runtimeName,
layer: desc.layer, layer: desc.layer,
dependOn: desc.dependOn, dependOn: desc.dependOn,
chunkLoading: desc.chunkLoading, chunkLoading: desc.chunkLoading,
chunkFormat: desc.chunkFormat,
wasmLoading: desc.wasmLoading, wasmLoading: desc.wasmLoading,
library: desc.library library: desc.library
}; };
@ -76,6 +79,10 @@ class EntryOptionPlugin {
const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin"); const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
EnableChunkLoadingPlugin.checkEnabled(compiler, desc.chunkLoading); EnableChunkLoadingPlugin.checkEnabled(compiler, desc.chunkLoading);
} }
if (desc.chunkFormat) {
const EnableChunkFormatPlugin = require("./javascript/EnableChunkFormatPlugin");
EnableChunkFormatPlugin.checkEnabled(compiler, desc.chunkFormat);
}
if (desc.wasmLoading) { if (desc.wasmLoading) {
const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin"); const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
EnableWasmLoadingPlugin.checkEnabled(compiler, desc.wasmLoading); EnableWasmLoadingPlugin.checkEnabled(compiler, desc.wasmLoading);

View File

@ -591,7 +591,9 @@ class HotModuleReplacementPlugin {
(newModules && newModules.length > 0) || (newModules && newModules.length > 0) ||
(newRuntimeModules && newRuntimeModules.length > 0) (newRuntimeModules && newRuntimeModules.length > 0)
) { ) {
const hotUpdateChunk = new HotUpdateChunk(); const hotUpdateChunk = new HotUpdateChunk(
currentChunk && currentChunk.options
);
ChunkGraph.setChunkGraphForChunk(hotUpdateChunk, chunkGraph); ChunkGraph.setChunkGraphForChunk(hotUpdateChunk, chunkGraph);
hotUpdateChunk.id = chunkId; hotUpdateChunk.id = chunkId;
hotUpdateChunk.runtime = newRuntime; hotUpdateChunk.runtime = newRuntime;

View File

@ -7,12 +7,14 @@
const Chunk = require("./Chunk"); const Chunk = require("./Chunk");
/** @typedef {import("./ChunkGraph")} ChunkGraph */ /** @typedef {import("./Chunk").ChunkOptions} ChunkOptions */
/** @typedef {import("./util/Hash")} Hash */
class HotUpdateChunk extends Chunk { class HotUpdateChunk extends Chunk {
constructor() { /**
super(); * @param {ChunkOptions=} options chunk options
*/
constructor(options = Chunk.EMPTY_CHUNK_OPTIONS) {
super(undefined, options);
} }
} }

View File

@ -0,0 +1,43 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Sean Larkin @thelarkinn
*/
"use strict";
const WebpackError = require("./WebpackError");
/** @typedef {import("./Chunk").ChunkOptions} ChunkOptions */
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Module")} Module */
class IncompatibleChunkOptionsError extends WebpackError {
/**
* Creates an instance of IncompatibleChunkOptionsError.
* @param {string} chunkName Name of Chunk
* @param {ChunkOptions} chunkOptions1 chunkOptions1
* @param {ChunkOptions} chunkOptions2 chunkOptions2
* @param {Module=} module module tied to dependency
* @param {DependencyLocation=} loc location of dependency
*/
constructor(chunkName, chunkOptions1, chunkOptions2, module, loc) {
super(
`${
chunkName ? `The chunk "${chunkName}"` : "A chunk"
} is referenced by multiple runtimes with different chunk options (e. g. chunkFormat, chunkFilename or initialChunkFilename).
Prevent chunk sharing by using layers, e. g. add 'layer: "..."' to the place where the different chunk options are specified.
Avoid to force chunk sharing by using 'splitChunk.cacheGroups.*.name' without filtering by layer (with 'splitChunk.cacheGroups.*.layer').
${JSON.stringify(chunkOptions1, null, 2)}
vs.
${JSON.stringify(chunkOptions2, null, 2)}`
);
this.name = "IncompatibleChunkOptionsError";
this.module = module;
this.loc = loc;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = IncompatibleChunkOptionsError;

View File

@ -127,46 +127,30 @@ class WebpackOptionsApply extends OptionsApply {
new ChunkPrefetchPreloadPlugin().apply(compiler); new ChunkPrefetchPreloadPlugin().apply(compiler);
if (typeof options.output.chunkFormat === "string") {
switch (options.output.chunkFormat) {
case "array-push": {
const ArrayPushCallbackChunkFormatPlugin = require("./javascript/ArrayPushCallbackChunkFormatPlugin");
new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
break;
}
case "commonjs": {
const CommonJsChunkFormatPlugin = require("./javascript/CommonJsChunkFormatPlugin");
new CommonJsChunkFormatPlugin().apply(compiler);
break;
}
case "module":
throw new Error(
"EcmaScript Module Chunk Format is not implemented yet"
);
default:
throw new Error(
"Unsupported chunk format '" + options.output.chunkFormat + "'."
);
}
}
if (options.output.enabledChunkLoadingTypes.length > 0) { if (options.output.enabledChunkLoadingTypes.length > 0) {
const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
for (const type of options.output.enabledChunkLoadingTypes) { for (const type of options.output.enabledChunkLoadingTypes) {
const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
new EnableChunkLoadingPlugin(type).apply(compiler); new EnableChunkLoadingPlugin(type).apply(compiler);
} }
} }
if (options.output.enabledChunkFormatTypes.length > 0) {
const EnableChunkFormatPlugin = require("./javascript/EnableChunkFormatPlugin");
for (const type of options.output.enabledChunkFormatTypes) {
new EnableChunkFormatPlugin(type).apply(compiler);
}
}
if (options.output.enabledWasmLoadingTypes.length > 0) { if (options.output.enabledWasmLoadingTypes.length > 0) {
const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
for (const type of options.output.enabledWasmLoadingTypes) { for (const type of options.output.enabledWasmLoadingTypes) {
const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
new EnableWasmLoadingPlugin(type).apply(compiler); new EnableWasmLoadingPlugin(type).apply(compiler);
} }
} }
if (options.output.enabledLibraryTypes.length > 0) { if (options.output.enabledLibraryTypes.length > 0) {
const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
for (const type of options.output.enabledLibraryTypes) { for (const type of options.output.enabledLibraryTypes) {
const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
new EnableLibraryPlugin(type).apply(compiler); new EnableLibraryPlugin(type).apply(compiler);
} }
} }
@ -320,6 +304,11 @@ class WebpackOptionsApply extends OptionsApply {
options.output.workerWasmLoading options.output.workerWasmLoading
).apply(compiler); ).apply(compiler);
if (options.experiments.asyncEntries) {
const AsyncEntriesPlugin = require("./dependencies/AsyncEntriesPlugin");
new AsyncEntriesPlugin().apply(compiler);
}
new DefaultStatsFactoryPlugin().apply(compiler); new DefaultStatsFactoryPlugin().apply(compiler);
new DefaultStatsPresetPlugin().apply(compiler); new DefaultStatsPresetPlugin().apply(compiler);
new DefaultStatsPrinterPlugin().apply(compiler); new DefaultStatsPrinterPlugin().apply(compiler);

View File

@ -7,6 +7,7 @@
const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError"); const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError");
const { connectChunkGroupParentAndChild } = require("./GraphHelpers"); const { connectChunkGroupParentAndChild } = require("./GraphHelpers");
const IncompatibleChunkOptionsError = require("./IncompatibleChunkOptionsError");
const ModuleGraphConnection = require("./ModuleGraphConnection"); const ModuleGraphConnection = require("./ModuleGraphConnection");
const { getEntryRuntime, mergeRuntime } = require("./util/runtime"); const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
@ -343,7 +344,8 @@ const visitModules = (
let entrypoint; let entrypoint;
const entryOptions = b.groupOptions && b.groupOptions.entryOptions; const entryOptions = b.groupOptions && b.groupOptions.entryOptions;
if (cgi === undefined) { if (cgi === undefined) {
const chunkName = (b.groupOptions && b.groupOptions.name) || b.chunkName; const { groupOptions } = b;
const chunkName = groupOptions.name || b.chunkName;
if (entryOptions) { if (entryOptions) {
cgi = namedAsyncEntrypoints.get(chunkName); cgi = namedAsyncEntrypoints.get(chunkName);
if (!cgi) { if (!cgi) {
@ -397,7 +399,7 @@ const visitModules = (
cgi = namedChunkGroups.get(chunkName); cgi = namedChunkGroups.get(chunkName);
if (!cgi) { if (!cgi) {
c = compilation.addChunkInGroup( c = compilation.addChunkInGroup(
b.groupOptions || b.chunkName, groupOptions,
module, module,
b.loc, b.loc,
b.request b.request
@ -422,6 +424,9 @@ const visitModules = (
if (chunkName) { if (chunkName) {
namedChunkGroups.set(chunkName, cgi); namedChunkGroups.set(chunkName, cgi);
} }
// Inherit chunk options
const newChunk = c.chunks[0];
newChunk.options = chunk.options;
} else { } else {
c = cgi.chunkGroup; c = cgi.chunkGroup;
if (c.isInitial()) { if (c.isInitial()) {
@ -432,6 +437,18 @@ const visitModules = (
} }
c.addOptions(b.groupOptions); c.addOptions(b.groupOptions);
c.addOrigin(module, b.loc, b.request); c.addOrigin(module, b.loc, b.request);
const newChunk = c.chunks[0];
if (newChunk.options !== chunk.options) {
compilation.errors.push(
new IncompatibleChunkOptionsError(
chunkName,
chunk.options,
newChunk.options,
module,
b.loc
)
);
}
} }
blockConnections.set(b, []); blockConnections.set(b, []);
} }

View File

@ -16,7 +16,7 @@ const {
} = require("./target"); } = require("./target");
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */ /** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */
/** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */ /** @typedef {import("../../declarations/WebpackOptions").EntryDescriptionOptions} EntryDescriptionOptions */
/** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */ /** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
/** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */ /** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
/** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */ /** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
@ -732,13 +732,27 @@ const applyOutputDefaults = (
F(output.environment, "module", () => tp && tp.module); F(output.environment, "module", () => tp && tp.module);
/** /**
* @param {function(EntryDescription): void} fn iterator * @param {function(EntryDescriptionOptions): void} fn iterator
* @returns {void} * @returns {void}
*/ */
const forEachEntry = fn => { const forEachEntry = fn => {
for (const name of Object.keys(entry)) { for (const name of Object.keys(entry)) {
fn(entry[name]); fn(entry[name]);
} }
for (const javascriptParserOptions of [
module.parser["javascript"],
module.parser["javascript/auto"],
module.parser["javascript/dynamic"],
module.parser["javascript/esm"]
]) {
if (!javascriptParserOptions) continue;
const entries = javascriptParserOptions.entries;
if (!entries) continue;
for (const name of Object.keys(entries)) {
const desc = entries[name];
if (desc && desc.entryOptions) fn(desc.entryOptions);
}
}
}; };
A(output, "enabledLibraryTypes", () => { A(output, "enabledLibraryTypes", () => {
const enabledLibraryTypes = []; const enabledLibraryTypes = [];
@ -769,6 +783,19 @@ const applyOutputDefaults = (
return Array.from(enabledChunkLoadingTypes); return Array.from(enabledChunkLoadingTypes);
}); });
A(output, "enabledChunkFormatTypes", () => {
const enabledChunkFormatTypes = new Set();
if (output.chunkFormat) {
enabledChunkFormatTypes.add(output.chunkFormat);
}
forEachEntry(desc => {
if (desc.chunkFormat) {
enabledChunkFormatTypes.add(desc.chunkFormat);
}
});
return Array.from(enabledChunkFormatTypes);
});
A(output, "enabledWasmLoadingTypes", () => { A(output, "enabledWasmLoadingTypes", () => {
const enabledWasmLoadingTypes = new Set(); const enabledWasmLoadingTypes = new Set();
if (output.wasmLoading) { if (output.wasmLoading) {

View File

@ -292,6 +292,9 @@ const getNormalizedWebpackOptions = config => {
enabledChunkLoadingTypes: output.enabledChunkLoadingTypes enabledChunkLoadingTypes: output.enabledChunkLoadingTypes
? [...output.enabledChunkLoadingTypes] ? [...output.enabledChunkLoadingTypes]
: ["..."], : ["..."],
enabledChunkFormatTypes: output.enabledChunkFormatTypes
? [...output.enabledChunkFormatTypes]
: ["..."],
enabledLibraryTypes: output.enabledLibraryTypes enabledLibraryTypes: output.enabledLibraryTypes
? [...output.enabledLibraryTypes] ? [...output.enabledLibraryTypes]
: ["..."], : ["..."],
@ -457,6 +460,8 @@ const getNormalizedEntryStatic = entry => {
value.import && value.import &&
(Array.isArray(value.import) ? value.import : [value.import]), (Array.isArray(value.import) ? value.import : [value.import]),
filename: value.filename, filename: value.filename,
chunkFilename: value.chunkFilename,
initialChunkFilename: value.initialChunkFilename,
layer: value.layer, layer: value.layer,
runtime: value.runtime, runtime: value.runtime,
runtimeName: value.runtimeName, runtimeName: value.runtimeName,

View File

@ -0,0 +1,146 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { WebpackError } = require("..");
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const EntryOptionPlugin = require("../EntryOptionPlugin");
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
const formatLocation = require("../formatLocation");
const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
const { resolveByProperty } = require("../util/cleverMerge");
const { contextify } = require("../util/identifier");
const AsyncEntryDependency = require("./AsyncEntryDependency");
/** @typedef {import("estree").Expression} Expression */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserAsyncEntryDescription} JavascriptParserAsyncEntryDescription */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Entrypoint").EntryOptions} EntryOptions */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("./HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */
const DEFAULT_ENTRIES = {};
class AsyncEntriesPlugin {
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const cachedContextify = contextify.bindContextCache(
compiler.context,
compiler.root
);
compiler.hooks.thisCompilation.tap(
"AsyncEntriesPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
AsyncEntryDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
AsyncEntryDependency,
new AsyncEntryDependency.Template()
);
/**
* @param {JavascriptParser} parser the parser
* @param {object} parserOptions options
*/
const parserPlugin = (parser, parserOptions) => {
if (parserOptions.entries === false) return;
const entries = /** @type {Record<string, JavascriptParserAsyncEntryDescription>} */ (parserOptions.entries);
for (const key of Object.keys({
...DEFAULT_ENTRIES,
...entries
})) {
const userOptions = entries[key];
parser.hooks.call.for(key).tap("AsyncEntriesPlugin", expr => {
const evaluatedArgs = expr.arguments.map(arg =>
arg.type === "SpreadElement"
? new BasicEvaluatedExpression()
: parser.evaluateExpression(arg)
);
if (!evaluatedArgs.every(arg => arg.isCompileTimeValue())) {
const error = new UnsupportedFeatureWarning(
`Call to async entrypoint function ${key} has non-constant values`,
expr.loc
);
parser.state.module.addError(error);
return;
}
const args = evaluatedArgs.map(arg => arg.asCompileTimeValue());
const options = resolveByProperty(
userOptions,
"byArguments",
{ expression: expr },
...args
);
if (options === false) return;
const {
request = args[0],
dependencyType = "import",
entryOptions: entryDescription,
return: returnValue,
value
} = options;
if (value !== undefined && returnValue !== undefined) {
const err = new WebpackError(
`'value' and 'return' specified for options for async entrypoint '${key}'`
);
err.loc = expr.loc;
throw err;
}
const entryOptions = EntryOptionPlugin.entryDescriptionToOptions(
compiler,
entryDescription.name,
entryDescription
);
if (!entryOptions.runtime && !entryOptions.runtimeName) {
entryOptions.runtimeName = `${cachedContextify(
parser.state.module.identifier()
)}|${formatLocation(expr.loc)}`;
}
const block = new AsyncDependenciesBlock({
name: entryOptions.name,
entryOptions
});
block.loc = expr.loc;
const dep = new AsyncEntryDependency(
request,
dependencyType,
expr.range,
returnValue !== undefined
? returnValue
: typeof value === "string"
? `value ${value}`
: value
);
dep.loc = expr.loc;
block.addDependency(dep);
parser.state.module.addBlock(block);
return true;
});
}
};
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("AsyncEntriesPlugin", parserPlugin);
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("AsyncEntriesPlugin", parserPlugin);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap("AsyncEntriesPlugin", parserPlugin);
}
);
}
}
module.exports = AsyncEntriesPlugin;

View File

@ -0,0 +1,149 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const Dependency = require("../Dependency");
const RuntimeGlobals = require("../RuntimeGlobals");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../Entrypoint")} Entrypoint */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
class AsyncEntryDependency extends ModuleDependency {
/**
* @param {string} request request
* @param {string} category category
* @param {[number, number]} range range
* @param {string} returnValue returned value
*/
constructor(request, category, range, returnValue) {
super(request);
this._category = category;
this.range = range;
this.returnValue = returnValue;
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph, runtime) {
return Dependency.EXPORTS_OBJECT_REFERENCED;
}
get type() {
return "async entry";
}
get category() {
return this._category;
}
serialize(context) {
context.write(this._category);
context.write(this.returnValue);
super.serialize(context);
}
deserialize(context) {
this._category = context.read();
this.returnValue = context.read();
super.deserialize(context);
}
}
AsyncEntryDependency.Template = class AsyncEntryDependencyTemplate extends (
ModuleDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, templateContext) {
const {
chunkGraph,
moduleGraph,
runtimeRequirements,
runtimeTemplate
} = templateContext;
const dep = /** @type {AsyncEntryDependency} */ (dependency);
const block = /** @type {AsyncDependenciesBlock} */ (moduleGraph.getParentBlock(
dependency
));
const entrypoint = /** @type {Entrypoint} */ (chunkGraph.getBlockChunkGroup(
block
));
if (!entrypoint) return;
let result;
if (typeof dep.returnValue !== "string") {
result = JSON.stringify(dep.returnValue);
} else {
switch (dep.returnValue) {
case undefined:
case "void":
result = "undefined";
break;
case "files": {
const chunks = entrypoint.chunks;
// TODO allow non-js types to return files too
runtimeRequirements.add(RuntimeGlobals.getChunkScriptFilename);
result = `/* async entry files */ ${JSON.stringify(
chunks.map(chunk => chunk.id)
)}.map(${RuntimeGlobals.getChunkScriptFilename})`;
break;
}
case "urls": {
const chunks = entrypoint.chunks;
runtimeRequirements.add(RuntimeGlobals.publicPath);
runtimeRequirements.add(RuntimeGlobals.baseURI);
runtimeRequirements.add(RuntimeGlobals.getChunkScriptFilename);
result = `/* async entry urls */ ${JSON.stringify(
chunks.map(chunk => chunk.id)
)}.map(${runtimeTemplate.returningFunction(
`new URL(${JSON.stringify(RuntimeGlobals.publicPath)} + ${
RuntimeGlobals.getChunkScriptFilename
}(id), ${RuntimeGlobals.baseURI})`,
"id"
)})`;
break;
}
default:
if (dep.returnValue.startsWith("value ")) {
result = JSON.stringify(dep.returnValue.slice(6));
} else {
throw new Error(`Unexpected returnValue '${dep.returnValue}'`);
}
break;
}
}
source.replace(dep.range[0], dep.range[1] - 1, result);
}
};
makeSerializable(
AsyncEntryDependency,
"webpack/lib/dependencies/AsyncEntryDependency"
);
module.exports = AsyncEntryDependency;

View File

@ -27,10 +27,18 @@ class ArrayPushCallbackChunkFormatPlugin {
compiler.hooks.thisCompilation.tap( compiler.hooks.thisCompilation.tap(
"ArrayPushCallbackChunkFormatPlugin", "ArrayPushCallbackChunkFormatPlugin",
compilation => { compilation => {
const globalChunkFormat = compilation.outputOptions.chunkFormat;
const isEnabledForChunk = chunk => {
const options = chunk.getEntryOptions();
const chunkFormat =
(options && options.chunkFormat) || globalChunkFormat;
return chunkFormat === "array-push";
};
compilation.hooks.additionalChunkRuntimeRequirements.tap( compilation.hooks.additionalChunkRuntimeRequirements.tap(
"ArrayPushCallbackChunkFormatPlugin", "ArrayPushCallbackChunkFormatPlugin",
(chunk, set, { chunkGraph }) => { (chunk, set, { chunkGraph }) => {
if (chunk.hasRuntime()) return; if (chunk.hasRuntime()) return;
if (!isEnabledForChunk(chunk)) return;
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
set.add(RuntimeGlobals.onChunksLoaded); set.add(RuntimeGlobals.onChunksLoaded);
set.add(RuntimeGlobals.require); set.add(RuntimeGlobals.require);
@ -43,6 +51,7 @@ class ArrayPushCallbackChunkFormatPlugin {
"ArrayPushCallbackChunkFormatPlugin", "ArrayPushCallbackChunkFormatPlugin",
(modules, renderContext) => { (modules, renderContext) => {
const { chunk, chunkGraph, runtimeTemplate } = renderContext; const { chunk, chunkGraph, runtimeTemplate } = renderContext;
if (!isEnabledForChunk(chunk)) return modules;
const hotUpdateChunk = const hotUpdateChunk =
chunk instanceof HotUpdateChunk ? chunk : null; chunk instanceof HotUpdateChunk ? chunk : null;
const globalObject = runtimeTemplate.outputOptions.globalObject; const globalObject = runtimeTemplate.outputOptions.globalObject;
@ -138,6 +147,7 @@ class ArrayPushCallbackChunkFormatPlugin {
"ArrayPushCallbackChunkFormatPlugin", "ArrayPushCallbackChunkFormatPlugin",
(chunk, hash, { chunkGraph, runtimeTemplate }) => { (chunk, hash, { chunkGraph, runtimeTemplate }) => {
if (chunk.hasRuntime()) return; if (chunk.hasRuntime()) return;
if (!isEnabledForChunk(chunk)) return;
hash.update("ArrayPushCallbackChunkFormatPlugin"); hash.update("ArrayPushCallbackChunkFormatPlugin");
hash.update("1"); hash.update("1");
hash.update(`${runtimeTemplate.outputOptions.chunkLoadingGlobal}`); hash.update(`${runtimeTemplate.outputOptions.chunkLoadingGlobal}`);

View File

@ -29,10 +29,18 @@ class CommonJsChunkFormatPlugin {
compiler.hooks.thisCompilation.tap( compiler.hooks.thisCompilation.tap(
"CommonJsChunkFormatPlugin", "CommonJsChunkFormatPlugin",
compilation => { compilation => {
const globalChunkFormat = compilation.outputOptions.chunkFormat;
const isEnabledForChunk = chunk => {
const options = chunk.getEntryOptions();
const chunkFormat =
(options && options.chunkFormat) || globalChunkFormat;
return chunkFormat === "commonjs";
};
compilation.hooks.additionalChunkRuntimeRequirements.tap( compilation.hooks.additionalChunkRuntimeRequirements.tap(
"CommonJsChunkLoadingPlugin", "CommonJsChunkLoadingPlugin",
(chunk, set, { chunkGraph }) => { (chunk, set, { chunkGraph }) => {
if (chunk.hasRuntime()) return; if (chunk.hasRuntime()) return;
if (!isEnabledForChunk(chunk)) return;
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
set.add(RuntimeGlobals.require); set.add(RuntimeGlobals.require);
set.add(RuntimeGlobals.startupEntrypoint); set.add(RuntimeGlobals.startupEntrypoint);
@ -45,6 +53,7 @@ class CommonJsChunkFormatPlugin {
"CommonJsChunkFormatPlugin", "CommonJsChunkFormatPlugin",
(modules, renderContext) => { (modules, renderContext) => {
const { chunk, chunkGraph, runtimeTemplate } = renderContext; const { chunk, chunkGraph, runtimeTemplate } = renderContext;
if (!isEnabledForChunk(chunk)) return modules;
const source = new ConcatSource(); const source = new ConcatSource();
source.add(`exports.id = ${JSON.stringify(chunk.id)};\n`); source.add(`exports.id = ${JSON.stringify(chunk.id)};\n`);
source.add(`exports.ids = ${JSON.stringify(chunk.ids)};\n`); source.add(`exports.ids = ${JSON.stringify(chunk.ids)};\n`);
@ -157,6 +166,7 @@ class CommonJsChunkFormatPlugin {
"CommonJsChunkFormatPlugin", "CommonJsChunkFormatPlugin",
(chunk, hash, { chunkGraph }) => { (chunk, hash, { chunkGraph }) => {
if (chunk.hasRuntime()) return; if (chunk.hasRuntime()) return;
if (!isEnabledForChunk(chunk)) return;
hash.update("CommonJsChunkFormatPlugin"); hash.update("CommonJsChunkFormatPlugin");
hash.update("1"); hash.update("1");
const entries = Array.from( const entries = Array.from(

View File

@ -0,0 +1,97 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("../../declarations/WebpackOptions").ChunkFormatType} ChunkFormatType */
/** @typedef {import("../Compiler")} Compiler */
/** @type {WeakMap<Compiler, Set<ChunkFormatType>>} */
const enabledTypes = new WeakMap();
const getEnabledTypes = compiler => {
let set = enabledTypes.get(compiler);
if (set === undefined) {
set = new Set();
enabledTypes.set(compiler, set);
}
return set;
};
class EnableChunkFormatPlugin {
/**
* @param {ChunkFormatType} type library type that should be available
*/
constructor(type) {
this.type = type;
}
/**
* @param {Compiler} compiler the compiler instance
* @param {ChunkFormatType} type type of library
* @returns {void}
*/
static setEnabled(compiler, type) {
getEnabledTypes(compiler).add(type);
}
/**
* @param {Compiler} compiler the compiler instance
* @param {ChunkFormatType} type type of library
* @returns {void}
*/
static checkEnabled(compiler, type) {
if (!getEnabledTypes(compiler).has(type)) {
throw new Error(
`Chunk format type "${type}" is not enabled. ` +
"EnableChunkFormatPlugin need to be used to enable this type of chunk format. " +
'This usually happens through the "output.enabledChunkFormatTypes" option. ' +
'If you are using a function as entry which sets "chunkFormat", you need to add all potential chunk format types to "output.enabledChunkFormatTypes". ' +
"These types are enabled: " +
Array.from(getEnabledTypes(compiler)).join(", ")
);
}
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const { type } = this;
// Only enable once
const enabled = getEnabledTypes(compiler);
if (enabled.has(type)) return;
enabled.add(type);
switch (type) {
case "array-push": {
const ArrayPushCallbackChunkFormatPlugin = require("./ArrayPushCallbackChunkFormatPlugin");
new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
break;
}
case "commonjs": {
const CommonJsChunkFormatPlugin = require("./CommonJsChunkFormatPlugin");
new CommonJsChunkFormatPlugin().apply(compiler);
break;
}
case "module":
// TODO implement import chunk format
throw new Error(
"EcmaScript Module Chunk Format is not implemented yet"
);
case "universal":
// TODO implement universal chunk loading
throw new Error("Universal Chunk Format is not implemented yet");
default:
throw new Error(`Unsupported chunk format type ${type}.
Plugins which provide custom chunk format types must call EnableChunkFormatPlugin.setEnabled(compiler, type) to disable this error.`);
}
}
}
module.exports = EnableChunkFormatPlugin;

View File

@ -432,9 +432,16 @@ class JavascriptModulesPlugin {
} else if (chunk instanceof HotUpdateChunk) { } else if (chunk instanceof HotUpdateChunk) {
return outputOptions.hotUpdateChunkFilename; return outputOptions.hotUpdateChunkFilename;
} else if (chunk.canBeInitial()) { } else if (chunk.canBeInitial()) {
return outputOptions.initialChunkFilename || outputOptions.filename; return (
(chunk.options && chunk.options.initialChunkFilename) ||
outputOptions.initialChunkFilename ||
outputOptions.filename
);
} else { } else {
return outputOptions.chunkFilename; return (
(chunk.options && chunk.options.chunkFilename) ||
outputOptions.chunkFilename
);
} }
} }

View File

@ -242,7 +242,7 @@ class JavascriptParser extends Parser {
importCall: new SyncBailHook(["expression"]), importCall: new SyncBailHook(["expression"]),
/** @type {SyncBailHook<[ExpressionNode], boolean | void>} */ /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
topLevelAwait: new SyncBailHook(["expression"]), topLevelAwait: new SyncBailHook(["expression"]),
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */ /** @type {HookMap<SyncBailHook<[CallExpressionNode], boolean | void>>} */
call: new HookMap(() => new SyncBailHook(["expression"])), call: new HookMap(() => new SyncBailHook(["expression"])),
/** Something like "a.b()" */ /** Something like "a.b()" */
/** @type {HookMap<SyncBailHook<[CallExpressionNode, string[]], boolean | void>>} */ /** @type {HookMap<SyncBailHook<[CallExpressionNode, string[]], boolean | void>>} */

View File

@ -6,6 +6,7 @@
"use strict"; "use strict";
const Chunk = require("../Chunk"); const Chunk = require("../Chunk");
const IncompatibleChunkOptionsError = require("../IncompatibleChunkOptionsError");
const { STAGE_ADVANCED } = require("../OptimizationStages"); const { STAGE_ADVANCED } = require("../OptimizationStages");
const WebpackError = require("../WebpackError"); const WebpackError = require("../WebpackError");
const { requestToId } = require("../ids/IdHelpers"); const { requestToId } = require("../ids/IdHelpers");
@ -1426,10 +1427,24 @@ module.exports = class SplitChunksPlugin {
// Create the new chunk if not reusing one // Create the new chunk if not reusing one
if (newChunk === undefined) { if (newChunk === undefined) {
newChunk = compilation.addChunk(chunkName); newChunk = compilation.addChunk(
chunkName,
usedChunks.values().next().value.options
);
} }
// Walk through all chunks // Walk through all chunks
let hasError = false;
for (const chunk of usedChunks) { for (const chunk of usedChunks) {
if (!hasError && chunk.options !== newChunk.options) {
compilation.errors.push(
new IncompatibleChunkOptionsError(
newChunk.name,
newChunk.options,
chunk.options
)
);
hasError = true;
}
// Add graph connections for splitted chunk // Add graph connections for splitted chunk
chunk.split(newChunk); chunk.split(newChunk);
} }

View File

@ -1352,6 +1352,7 @@ const SIMPLE_EXTRACTORS = {
size: chunkGraph.getChunkModulesSize(chunk), size: chunkGraph.getChunkModulesSize(chunk),
sizes: chunkGraph.getChunkModulesSizes(chunk), sizes: chunkGraph.getChunkModulesSizes(chunk),
names: chunk.name ? [chunk.name] : [], names: chunk.name ? [chunk.name] : [],
chunkFormat: chunk.options.chunkFormat,
idHints: Array.from(chunk.idNameHints), idHints: Array.from(chunk.idNameHints),
runtime: runtime:
chunk.runtime === undefined chunk.runtime === undefined

View File

@ -451,6 +451,8 @@ const SIMPLE_PRINTERS = {
"chunk.files[]": (file, { formatFilename }) => formatFilename(file), "chunk.files[]": (file, { formatFilename }) => formatFilename(file),
"chunk.names[]": name => name, "chunk.names[]": name => name,
"chunk.idHints[]": name => name, "chunk.idHints[]": name => name,
"chunk.chunkFormat": (chunkFormat, { formatFlag, cyan }) =>
cyan(formatFlag(`chunk format ${chunkFormat}`)),
"chunk.runtime[]": name => name, "chunk.runtime[]": name => name,
"chunk.sizes": (sizes, context) => printSizes(sizes, context), "chunk.sizes": (sizes, context) => printSizes(sizes, context),
"chunk.parents[]": (parents, context) => "chunk.parents[]": (parents, context) =>
@ -753,6 +755,7 @@ const PREFERRED_ORDERS = {
"files", "files",
"names", "names",
"idHints", "idHints",
"chunkFormat",
"sizes", "sizes",
"parents", "parents",
"siblings", "siblings",

View File

@ -43,6 +43,8 @@ module.exports = {
require("../dependencies/AMDRequireDependency"), require("../dependencies/AMDRequireDependency"),
"dependencies/AMDRequireItemDependency": () => "dependencies/AMDRequireItemDependency": () =>
require("../dependencies/AMDRequireItemDependency"), require("../dependencies/AMDRequireItemDependency"),
"dependencies/AsyncEntryDependency": () =>
require("../dependencies/AsyncEntryDependency"),
"dependencies/CachedConstDependency": () => "dependencies/CachedConstDependency": () =>
require("../dependencies/CachedConstDependency"), require("../dependencies/CachedConstDependency"),
"dependencies/CommonJsRequireContextDependency": () => "dependencies/CommonJsRequireContextDependency": () =>

View File

@ -12,42 +12,41 @@ const DID_YOU_MEAN = {
rules: "module.rules", rules: "module.rules",
loaders: "module.rules or module.rules.*.use", loaders: "module.rules or module.rules.*.use",
query: "module.rules.*.options (BREAKING CHANGE since webpack 5)", query: "module.rules.*.options (BREAKING CHANGE since webpack 5)",
noParse: "module.noParse", noparse: "module.noParse",
filename: "output.filename or module.rules.*.generator.filename", filename:
"output.filename, entry.*.filename or module.rules.*.generator.filename",
file: "output.filename", file: "output.filename",
chunkFilename: "output.chunkFilename", chunkfilename: "output.chunkFilename or entry.*.chunkFilename",
chunkfilename: "output.chunkFilename", initialchunkfilename:
ecmaVersion: "output.initialChunkFilename or entry.*.initialChunkFilename",
"output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
ecmaversion: ecmaversion:
"output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)", "output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
ecma: ecma:
"output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)", "output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)",
path: "output.path", path: "output.path",
pathinfo: "output.pathinfo", pathinfo: "output.pathinfo",
pathInfo: "output.pathinfo", jsonpfunction: "output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)",
jsonpFunction: "output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)", chunkcallbackname:
chunkCallbackName:
"output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)", "output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)",
jsonpScriptType: "output.scriptType (BREAKING CHANGE since webpack 5)", jsonpscripttype: "output.scriptType (BREAKING CHANGE since webpack 5)",
hotUpdateFunction: "output.hotUpdateGlobal (BREAKING CHANGE since webpack 5)", hotupdatefunction: "output.hotUpdateGlobal (BREAKING CHANGE since webpack 5)",
splitChunks: "optimization.splitChunks", splitchunks: "optimization.splitChunks",
immutablePaths: "snapshot.immutablePaths", immutablepaths: "snapshot.immutablePaths",
managedPaths: "snapshot.managedPaths", managedpaths: "snapshot.managedPaths",
maxModules: "stats.modulesSpace (BREAKING CHANGE since webpack 5)", maxmodules: "stats.modulesSpace (BREAKING CHANGE since webpack 5)",
hashedModuleIds: hashedmoduleids:
'optimization.moduleIds: "hashed" (BREAKING CHANGE since webpack 5)', 'optimization.moduleIds: "hashed" (BREAKING CHANGE since webpack 5)',
namedChunks: namedchunks:
'optimization.chunkIds: "named" (BREAKING CHANGE since webpack 5)', 'optimization.chunkIds: "named" (BREAKING CHANGE since webpack 5)',
namedModules: namedmodules:
'optimization.moduleIds: "named" (BREAKING CHANGE since webpack 5)', 'optimization.moduleIds: "named" (BREAKING CHANGE since webpack 5)',
occurrenceOrder: occurrenceorder:
'optimization.chunkIds: "size" and optimization.moduleIds: "size" (BREAKING CHANGE since webpack 5)', 'optimization.chunkIds: "size" and optimization.moduleIds: "size" (BREAKING CHANGE since webpack 5)',
automaticNamePrefix: automaticnameprefix:
"optimization.splitChunks.[cacheGroups.*].idHint (BREAKING CHANGE since webpack 5)", "optimization.splitChunks.[cacheGroups.*].idHint (BREAKING CHANGE since webpack 5)",
noEmitOnErrors: noemitonerrors:
"optimization.emitOnErrors (BREAKING CHANGE since webpack 5: logic is inverted to avoid negative flags)", "optimization.emitOnErrors (BREAKING CHANGE since webpack 5: logic is inverted to avoid negative flags)",
Buffer: buffer:
"to use the ProvidePlugin to process the Buffer variable to modules as polyfill\n" + "to use the ProvidePlugin to process the Buffer variable to modules as polyfill\n" +
"BREAKING CHANGE: webpack 5 no longer provided Node.js polyfills by default.\n" + "BREAKING CHANGE: webpack 5 no longer provided Node.js polyfills by default.\n" +
"Note: if you are using 'node.Buffer: false', you can just remove that as this is the default behavior now.\n" + "Note: if you are using 'node.Buffer: false', you can just remove that as this is the default behavior now.\n" +
@ -113,11 +112,11 @@ const validateSchema = (schema, options, validationConfiguration) => {
if ( if (
Object.prototype.hasOwnProperty.call( Object.prototype.hasOwnProperty.call(
DID_YOU_MEAN, DID_YOU_MEAN,
params.additionalProperty params.additionalProperty.toLowerCase()
) )
) { ) {
return `${formattedError}\nDid you mean ${ return `${formattedError}\nDid you mean ${
DID_YOU_MEAN[params.additionalProperty] DID_YOU_MEAN[params.additionalProperty.toLowerCase()]
}?`; }?`;
} }

View File

@ -246,7 +246,18 @@
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).", "description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"anyOf": [ "anyOf": [
{ {
"enum": ["array-push", "commonjs", false] "enum": [false]
},
{
"$ref": "#/definitions/ChunkFormatType"
}
]
},
"ChunkFormatType": {
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"anyOf": [
{
"enum": ["array-push", "commonjs"]
}, },
{ {
"type": "string" "type": "string"
@ -397,6 +408,13 @@
"type": "object", "type": "object",
"additionalProperties": false "additionalProperties": false
}, },
"EnabledChunkFormatTypes": {
"description": "List of chunk format types enabled for use by entry points.",
"type": "array",
"items": {
"$ref": "#/definitions/ChunkFormatType"
}
},
"EnabledChunkLoadingTypes": { "EnabledChunkLoadingTypes": {
"description": "List of chunk loading types enabled for use by entry points.", "description": "List of chunk loading types enabled for use by entry points.",
"type": "array", "type": "array",
@ -432,10 +450,17 @@
"EntryDescription": { "EntryDescription": {
"description": "An object with entry point description.", "description": "An object with entry point description.",
"type": "object", "type": "object",
"implements": "#/definitions/EntryDescriptionOptions",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"chunkFilename": {
"$ref": "#/definitions/ChunkFilename"
},
"chunkFormat": {
"$ref": "#/definitions/ChunkFormatType"
},
"chunkLoading": { "chunkLoading": {
"$ref": "#/definitions/ChunkLoading" "$ref": "#/definitions/ChunkLoadingType"
}, },
"dependOn": { "dependOn": {
"description": "The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.", "description": "The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.",
@ -464,6 +489,9 @@
"import": { "import": {
"$ref": "#/definitions/EntryItem" "$ref": "#/definitions/EntryItem"
}, },
"initialChunkFilename": {
"$ref": "#/definitions/InitialChunkFilename"
},
"layer": { "layer": {
"$ref": "#/definitions/Layer" "$ref": "#/definitions/Layer"
}, },
@ -482,13 +510,62 @@
}, },
"required": ["import"] "required": ["import"]
}, },
"EntryDescriptionNamed": {
"description": "An object with entry point description.",
"type": "object",
"implements": "#/definitions/EntryDescriptionOptions",
"additionalProperties": false,
"properties": {
"chunkFilename": {
"$ref": "#/definitions/ChunkFilename"
},
"chunkFormat": {
"$ref": "#/definitions/ChunkFormatType"
},
"chunkLoading": {
"$ref": "#/definitions/ChunkLoadingType"
},
"filename": {
"$ref": "#/definitions/EntryFilename"
},
"initialChunkFilename": {
"$ref": "#/definitions/InitialChunkFilename"
},
"layer": {
"$ref": "#/definitions/Layer"
},
"library": {
"$ref": "#/definitions/LibraryOptions"
},
"name": {
"description": "Name of this entrypoint.",
"type": "string",
"minLength": 1
},
"runtime": {
"$ref": "#/definitions/EntryRuntime"
},
"runtimeName": {
"$ref": "#/definitions/EntryRuntimeName"
},
"wasmLoading": {
"$ref": "#/definitions/WasmLoading"
}
}
},
"EntryDescriptionNormalized": { "EntryDescriptionNormalized": {
"description": "An object with entry point description.", "description": "An object with entry point description.",
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"chunkFilename": {
"$ref": "#/definitions/ChunkFilename"
},
"chunkFormat": {
"$ref": "#/definitions/ChunkFormatType"
},
"chunkLoading": { "chunkLoading": {
"$ref": "#/definitions/ChunkLoading" "$ref": "#/definitions/ChunkLoadingType"
}, },
"dependOn": { "dependOn": {
"description": "The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.", "description": "The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.",
@ -502,7 +579,7 @@
"uniqueItems": true "uniqueItems": true
}, },
"filename": { "filename": {
"$ref": "#/definitions/Filename" "$ref": "#/definitions/EntryFilename"
}, },
"import": { "import": {
"description": "Module(s) that are loaded upon startup. The last one is exported.", "description": "Module(s) that are loaded upon startup. The last one is exported.",
@ -515,6 +592,46 @@
"minItems": 1, "minItems": 1,
"uniqueItems": true "uniqueItems": true
}, },
"initialChunkFilename": {
"$ref": "#/definitions/InitialChunkFilename"
},
"layer": {
"$ref": "#/definitions/Layer"
},
"library": {
"$ref": "#/definitions/LibraryOptions"
},
"runtime": {
"$ref": "#/definitions/EntryRuntime"
},
"runtimeName": {
"$ref": "#/definitions/EntryRuntimeName"
},
"wasmLoading": {
"$ref": "#/definitions/WasmLoading"
}
}
},
"EntryDescriptionOptions": {
"description": "An object with entry point description.",
"type": "object",
"additionalProperties": false,
"properties": {
"chunkFilename": {
"$ref": "#/definitions/ChunkFilename"
},
"chunkFormat": {
"$ref": "#/definitions/ChunkFormatType"
},
"chunkLoading": {
"$ref": "#/definitions/ChunkLoadingType"
},
"filename": {
"$ref": "#/definitions/EntryFilename"
},
"initialChunkFilename": {
"$ref": "#/definitions/InitialChunkFilename"
},
"layer": { "layer": {
"$ref": "#/definitions/Layer" "$ref": "#/definitions/Layer"
}, },
@ -682,6 +799,10 @@
"description": "Allow module type 'asset' to generate assets.", "description": "Allow module type 'asset' to generate assets.",
"type": "boolean" "type": "boolean"
}, },
"asyncEntries": {
"description": "Allow to configure that async entries can be parsed.",
"type": "boolean"
},
"asyncWebAssembly": { "asyncWebAssembly": {
"description": "Support WebAssembly as asynchronous EcmaScript Module.", "description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean" "type": "boolean"
@ -1268,6 +1389,37 @@
} }
] ]
}, },
"JavascriptParserAsyncEntryDescription": {
"description": "Options for any async entrypoint.",
"type": "object",
"additionalProperties": false,
"properties": {
"byArguments": {
"description": "Determine values based on custom logic. First argument is an context object, second and following arguments are values passed in source code. Return value is merged with the static values.",
"instanceof": "Function",
"tsType": "((info: { expression: import('estree').Expression }, ...args: any[]) => false | JavascriptParserAsyncEntryDescription)"
},
"dependencyType": {
"description": "Specify the dependency type of the request that is used for resolving.",
"type": "string"
},
"entryOptions": {
"$ref": "#/definitions/EntryDescriptionNamed"
},
"request": {
"description": "Specify the request to reference a module.",
"type": "string"
},
"return": {
"description": "Specify the returned value (void: returns undefined, files: returns an array of filenames, urls: returns an array of URLs).",
"enum": ["void", "files", "urls"]
},
"value": {
"description": "Any JSON value that should be returned.",
"tsType": "any"
}
}
},
"JavascriptParserOptions": { "JavascriptParserOptions": {
"description": "Parser options for javascript modules.", "description": "Parser options for javascript modules.",
"type": "object", "type": "object",
@ -1288,6 +1440,28 @@
"description": "Enable/disable parsing of magic comments in CommonJs syntax.", "description": "Enable/disable parsing of magic comments in CommonJs syntax.",
"type": "boolean" "type": "boolean"
}, },
"entries": {
"description": "Disable or configure handling of async entrypoints specified in source code.",
"anyOf": [
{
"enum": [false]
},
{
"type": "object",
"additionalProperties": {
"description": "Specify behavior of this async entrypoint.",
"anyOf": [
{
"enum": [false]
},
{
"$ref": "#/definitions/JavascriptParserAsyncEntryDescription"
}
]
}
}
]
},
"exprContextCritical": { "exprContextCritical": {
"description": "Enable warnings for full dynamic dependencies.", "description": "Enable warnings for full dynamic dependencies.",
"type": "boolean" "type": "boolean"
@ -2593,6 +2767,9 @@
"devtoolNamespace": { "devtoolNamespace": {
"$ref": "#/definitions/DevtoolNamespace" "$ref": "#/definitions/DevtoolNamespace"
}, },
"enabledChunkFormatTypes": {
"$ref": "#/definitions/EnabledChunkFormatTypes"
},
"enabledChunkLoadingTypes": { "enabledChunkLoadingTypes": {
"$ref": "#/definitions/EnabledChunkLoadingTypes" "$ref": "#/definitions/EnabledChunkLoadingTypes"
}, },
@ -2769,6 +2946,9 @@
"devtoolNamespace": { "devtoolNamespace": {
"$ref": "#/definitions/DevtoolNamespace" "$ref": "#/definitions/DevtoolNamespace"
}, },
"enabledChunkFormatTypes": {
"$ref": "#/definitions/EnabledChunkFormatTypes"
},
"enabledChunkLoadingTypes": { "enabledChunkLoadingTypes": {
"$ref": "#/definitions/EnabledChunkLoadingTypes" "$ref": "#/definitions/EnabledChunkLoadingTypes"
}, },

View File

@ -288,6 +288,9 @@ describe("Defaults", () => {
"devtoolFallbackModuleFilenameTemplate": undefined, "devtoolFallbackModuleFilenameTemplate": undefined,
"devtoolModuleFilenameTemplate": undefined, "devtoolModuleFilenameTemplate": undefined,
"devtoolNamespace": "webpack", "devtoolNamespace": "webpack",
"enabledChunkFormatTypes": Array [
"array-push",
],
"enabledChunkLoadingTypes": Array [ "enabledChunkLoadingTypes": Array [
"jsonp", "jsonp",
"import-scripts", "import-scripts",
@ -1039,6 +1042,9 @@ describe("Defaults", () => {
- "chunkLoading": "jsonp", - "chunkLoading": "jsonp",
+ "chunkLoading": "require", + "chunkLoading": "require",
@@ ... @@ @@ ... @@
- "array-push",
+ "commonjs",
@@ ... @@
- "jsonp", - "jsonp",
- "import-scripts", - "import-scripts",
+ "require", + "require",
@ -1180,6 +1186,9 @@ describe("Defaults", () => {
- "chunkLoading": "jsonp", - "chunkLoading": "jsonp",
+ "chunkLoading": "require", + "chunkLoading": "require",
@@ ... @@ @@ ... @@
- "array-push",
+ "commonjs",
@@ ... @@
- "jsonp", - "jsonp",
- "import-scripts", - "import-scripts",
+ "require", + "require",
@ -1303,6 +1312,9 @@ describe("Defaults", () => {
- "chunkLoading": "jsonp", - "chunkLoading": "jsonp",
+ "chunkLoading": "require", + "chunkLoading": "require",
@@ ... @@ @@ ... @@
- "array-push",
+ "commonjs",
@@ ... @@
- "jsonp", - "jsonp",
- "import-scripts", - "import-scripts",
+ "require", + "require",

View File

@ -496,7 +496,7 @@ describe("Validation", () => {
expect(msg).toMatchInlineSnapshot(` expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. "Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.output has an unknown property 'ecmaVersion'. These properties are valid: - configuration.output has an unknown property 'ecmaVersion'. These properties are valid:
object { assetModuleFilename?, auxiliaryComment?, charset?, chunkFilename?, chunkFormat?, chunkLoadTimeout?, chunkLoading?, chunkLoadingGlobal?, clean?, compareBeforeEmit?, crossOriginLoading?, devtoolFallbackModuleFilenameTemplate?, devtoolModuleFilenameTemplate?, devtoolNamespace?, enabledChunkLoadingTypes?, enabledLibraryTypes?, enabledWasmLoadingTypes?, environment?, filename?, globalObject?, hashDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateGlobal?, hotUpdateMainFilename?, iife?, importFunctionName?, importMetaName?, initialChunkFilename?, library?, libraryExport?, libraryTarget?, module?, path?, pathinfo?, publicPath?, scriptType?, sourceMapFilename?, sourcePrefix?, strictModuleErrorHandling?, strictModuleExceptionHandling?, umdNamedDefine?, uniqueName?, wasmLoading?, webassemblyModuleFilename?, workerChunkLoading?, workerWasmLoading? } object { assetModuleFilename?, auxiliaryComment?, charset?, chunkFilename?, chunkFormat?, chunkLoadTimeout?, chunkLoading?, chunkLoadingGlobal?, clean?, compareBeforeEmit?, crossOriginLoading?, devtoolFallbackModuleFilenameTemplate?, devtoolModuleFilenameTemplate?, devtoolNamespace?, enabledChunkFormatTypes?, enabledChunkLoadingTypes?, enabledLibraryTypes?, enabledWasmLoadingTypes?, environment?, filename?, globalObject?, hashDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateGlobal?, hotUpdateMainFilename?, iife?, importFunctionName?, importMetaName?, initialChunkFilename?, library?, libraryExport?, libraryTarget?, module?, path?, pathinfo?, publicPath?, scriptType?, sourceMapFilename?, sourcePrefix?, strictModuleErrorHandling?, strictModuleExceptionHandling?, umdNamedDefine?, uniqueName?, wasmLoading?, webassemblyModuleFilename?, workerChunkLoading?, workerWasmLoading? }
-> Options affecting the output of the compilation. \`output\` options tell webpack how to write the compiled files to disk. -> Options affecting the output of the compilation. \`output\` options tell webpack how to write the compiled files to disk.
Did you mean output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)?" Did you mean output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)?"
`) `)

View File

@ -380,6 +380,19 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "boolean", "simpleType": "boolean",
}, },
"experiments-async-entries": Object {
"configs": Array [
Object {
"description": "Allow to configure that async entries can be parsed.",
"multiple": false,
"path": "experiments.asyncEntries",
"type": "boolean",
},
],
"description": "Allow to configure that async entries can be parsed.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-async-web-assembly": Object { "experiments-async-web-assembly": Object {
"configs": Array [ "configs": Array [
Object { Object {
@ -1179,6 +1192,22 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "boolean", "simpleType": "boolean",
}, },
"module-parser-javascript-auto-entries": Object {
"configs": Array [
Object {
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"path": "module.parser.javascript/auto.entries",
"type": "enum",
"values": Array [
false,
],
},
],
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-auto-expr-context-critical": Object { "module-parser-javascript-auto-expr-context-critical": Object {
"configs": Array [ "configs": Array [
Object { Object {
@ -1666,6 +1695,22 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "boolean", "simpleType": "boolean",
}, },
"module-parser-javascript-dynamic-entries": Object {
"configs": Array [
Object {
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"path": "module.parser.javascript/dynamic.entries",
"type": "enum",
"values": Array [
false,
],
},
],
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-expr-context-critical": Object { "module-parser-javascript-dynamic-expr-context-critical": Object {
"configs": Array [ "configs": Array [
Object { Object {
@ -2059,6 +2104,22 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "string", "simpleType": "string",
}, },
"module-parser-javascript-entries": Object {
"configs": Array [
Object {
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"path": "module.parser.javascript.entries",
"type": "enum",
"values": Array [
false,
],
},
],
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-amd": Object { "module-parser-javascript-esm-amd": Object {
"configs": Array [ "configs": Array [
Object { Object {
@ -2114,6 +2175,22 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "boolean", "simpleType": "boolean",
}, },
"module-parser-javascript-esm-entries": Object {
"configs": Array [
Object {
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"path": "module.parser.javascript/esm.entries",
"type": "enum",
"values": Array [
false,
],
},
],
"description": "Disable or configure handling of async entrypoints specified in source code.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-expr-context-critical": Object { "module-parser-javascript-esm-expr-context-critical": Object {
"configs": Array [ "configs": Array [
Object { Object {
@ -4171,6 +4248,15 @@ Object {
}, },
"output-chunk-format": Object { "output-chunk-format": Object {
"configs": Array [ "configs": Array [
Object {
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"multiple": false,
"path": "output.chunkFormat",
"type": "enum",
"values": Array [
false,
],
},
Object { Object {
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).", "description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"multiple": false, "multiple": false,
@ -4179,7 +4265,6 @@ Object {
"values": Array [ "values": Array [
"array-push", "array-push",
"commonjs", "commonjs",
false,
], ],
}, },
Object { Object {
@ -4368,6 +4453,42 @@ Object {
"multiple": false, "multiple": false,
"simpleType": "string", "simpleType": "string",
}, },
"output-enabled-chunk-format-types": Object {
"configs": Array [
Object {
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"multiple": true,
"path": "output.enabledChunkFormatTypes[]",
"type": "enum",
"values": Array [
"array-push",
"commonjs",
],
},
Object {
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"multiple": true,
"path": "output.enabledChunkFormatTypes[]",
"type": "string",
},
],
"description": "The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).",
"multiple": true,
"simpleType": "string",
},
"output-enabled-chunk-format-types-reset": Object {
"configs": Array [
Object {
"description": "Clear all items provided in configuration. List of chunk format types enabled for use by entry points.",
"multiple": false,
"path": "output.enabledChunkFormatTypes",
"type": "reset",
},
],
"description": "Clear all items provided in configuration. List of chunk format types enabled for use by entry points.",
"multiple": false,
"simpleType": "boolean",
},
"output-enabled-chunk-loading-types": Object { "output-enabled-chunk-loading-types": Object {
"configs": Array [ "configs": Array [
Object { Object {

172
types.d.ts vendored
View File

@ -679,7 +679,7 @@ declare interface CallbackWebpack<T> {
} }
type Cell<T> = undefined | T; type Cell<T> = undefined | T;
declare class Chunk { declare class Chunk {
constructor(name?: string); constructor(name?: string, options?: ChunkOptions);
id: null | string | number; id: null | string | number;
ids: null | (string | number)[]; ids: null | (string | number)[];
debugId: number; debugId: number;
@ -699,6 +699,7 @@ declare class Chunk {
renderedHash?: string; renderedHash?: string;
chunkReason?: string; chunkReason?: string;
extraAsync: boolean; extraAsync: boolean;
options: ChunkOptions;
readonly entryModule?: Module; readonly entryModule?: Module;
hasEntryModule(): boolean; hasEntryModule(): boolean;
addModule(module: Module): boolean; addModule(module: Module): boolean;
@ -752,6 +753,7 @@ declare class Chunk {
includeDirectChildren?: boolean, includeDirectChildren?: boolean,
filterFn?: (c: Chunk, chunkGraph: ChunkGraph) => boolean filterFn?: (c: Chunk, chunkGraph: ChunkGraph) => boolean
): Record<string | number, Record<string, (string | number)[]>>; ): Record<string | number, Record<string, (string | number)[]>>;
static EMPTY_CHUNK_OPTIONS: ChunkOptions;
} }
declare class ChunkGraph { declare class ChunkGraph {
constructor(moduleGraph: ModuleGraph); constructor(moduleGraph: ModuleGraph);
@ -1042,6 +1044,15 @@ declare interface ChunkModuleMaps {
id: Record<string | number, (string | number)[]>; id: Record<string | number, (string | number)[]>;
hash: Record<string | number, string>; hash: Record<string | number, string>;
} }
declare interface ChunkOptions {
initialChunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
chunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
chunkFormat?: string;
}
declare interface ChunkPathData { declare interface ChunkPathData {
id: string | number; id: string | number;
name?: string; name?: string;
@ -1576,7 +1587,7 @@ declare class Compilation {
* This method first looks to see if a name is provided for a new chunk, * This method first looks to see if a name is provided for a new chunk,
* and first looks to see if any named chunks already exist and reuse that chunk instead. * and first looks to see if any named chunks already exist and reuse that chunk instead.
*/ */
addChunk(name?: string): Chunk; addChunk(name?: string, options?: ChunkOptions): Chunk;
assignDepth(module: Module): void; assignDepth(module: Module): void;
getDependencyReferencedExports( getDependencyReferencedExports(
dependency: Dependency, dependency: Dependency,
@ -2891,30 +2902,77 @@ declare interface EntryData {
options: EntryOptions; options: EntryOptions;
} }
declare abstract class EntryDependency extends ModuleDependency {} declare abstract class EntryDependency extends ModuleDependency {}
type EntryDescription = EntryDescriptionOptions & EntryDescriptionExtra;
/** /**
* An object with entry point description. * An object with entry point description.
*/ */
declare interface EntryDescription { declare interface EntryDescriptionExtra {
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
chunkLoading?: string | false;
/** /**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded. * The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/ */
dependOn?: string | string[]; dependOn?: string | string[];
/**
* Module(s) that are loaded upon startup.
*/
import: EntryItem;
}
type EntryDescriptionNamed = EntryDescriptionOptions &
EntryDescriptionNamedExtra;
/**
* An object with entry point description.
*/
declare interface EntryDescriptionNamedExtra {
/**
* Name of this entrypoint.
*/
name?: string;
}
/**
* An object with entry point description.
*/
declare interface EntryDescriptionNormalized {
/**
* Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
chunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/
chunkFormat?: string;
/**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/
chunkLoading?: string;
/**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/
dependOn?: string[];
/** /**
* Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk. * Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/ */
filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string); filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
/** /**
* Module(s) that are loaded upon startup. * Module(s) that are loaded upon startup. The last one is exported.
*/ */
import: EntryItem; import?: string[];
/**
* Specifies the filename template of output files of initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
initialChunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/** /**
* Specifies the layer in which modules of this entrypoint are placed. * Specifies the layer in which modules of this entrypoint are placed.
@ -2945,26 +3003,35 @@ declare interface EntryDescription {
/** /**
* An object with entry point description. * An object with entry point description.
*/ */
declare interface EntryDescriptionNormalized { declare interface EntryDescriptionOptions {
/**
* Specifies the filename template of output files of non-initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
chunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* The format of chunks (formats included by default are 'array-push' (web/WebWorker), 'commonjs' (node.js), but others might be added by plugins).
*/
chunkFormat?: string;
/** /**
* The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins). * The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
*/ */
chunkLoading?: string | false; chunkLoading?: string;
/** /**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded. * Specifies the filename of the output file on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
dependOn?: string[];
/**
* Specifies the filename of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/ */
filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string); filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
/** /**
* Module(s) that are loaded upon startup. The last one is exported. * Specifies the filename template of output files of initial chunks on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/ */
import?: string[]; initialChunkFilename?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/** /**
* Specifies the layer in which modules of this entrypoint are placed. * Specifies the layer in which modules of this entrypoint are placed.
@ -3177,6 +3244,11 @@ declare interface Experiments {
*/ */
asset?: boolean; asset?: boolean;
/**
* Allow to configure that async entries can be parsed.
*/
asyncEntries?: boolean;
/** /**
* Support WebAssembly as asynchronous EcmaScript Module. * Support WebAssembly as asynchronous EcmaScript Module.
*/ */
@ -4195,7 +4267,8 @@ declare class HotModuleReplacementPlugin {
static getParserHooks(parser: JavascriptParser): HMRJavascriptParserHooks; static getParserHooks(parser: JavascriptParser): HMRJavascriptParserHooks;
} }
declare class HotUpdateChunk extends Chunk { declare class HotUpdateChunk extends Chunk {
constructor(); constructor(options?: ChunkOptions);
static EMPTY_CHUNK_OPTIONS: ChunkOptions;
} }
declare class HttpUriPlugin { declare class HttpUriPlugin {
constructor(); constructor();
@ -4657,7 +4730,7 @@ declare class JavascriptParser extends Parser {
typeof: HookMap<SyncBailHook<[Expression], boolean | void>>; typeof: HookMap<SyncBailHook<[Expression], boolean | void>>;
importCall: SyncBailHook<[Expression], boolean | void>; importCall: SyncBailHook<[Expression], boolean | void>;
topLevelAwait: SyncBailHook<[Expression], boolean | void>; topLevelAwait: SyncBailHook<[Expression], boolean | void>;
call: HookMap<SyncBailHook<[Expression], boolean | void>>; call: HookMap<SyncBailHook<[CallExpression], boolean | void>>;
callMemberChain: HookMap< callMemberChain: HookMap<
SyncBailHook<[CallExpression, string[]], boolean | void> SyncBailHook<[CallExpression, string[]], boolean | void>
>; >;
@ -4998,6 +5071,44 @@ declare class JavascriptParser extends Parser {
static ALLOWED_MEMBER_TYPES_CALL_EXPRESSION: 1; static ALLOWED_MEMBER_TYPES_CALL_EXPRESSION: 1;
} }
/**
* Options for any async entrypoint.
*/
declare interface JavascriptParserAsyncEntryDescription {
/**
* Determine values based on custom logic. First argument is an context object, second and following arguments are values passed in source code. Return value is merged with the static values.
*/
byArguments?: (
info: { expression: Expression },
...args: any[]
) => false | JavascriptParserAsyncEntryDescription;
/**
* Specify the dependency type of the request that is used for resolving.
*/
dependencyType?: string;
/**
* An object with entry point description.
*/
entryOptions?: EntryDescriptionNamed;
/**
* Specify the request to reference a module.
*/
request?: string;
/**
* Specify the returned value (void: returns undefined, files: returns an array of filenames, urls: returns an array of URLs).
*/
return?: "files" | "void" | "urls";
/**
* Any JSON value that should be returned.
*/
value?: any;
}
/** /**
* Parser options for javascript modules. * Parser options for javascript modules.
*/ */
@ -5024,6 +5135,13 @@ declare interface JavascriptParserOptions {
*/ */
commonjsMagicComments?: boolean; commonjsMagicComments?: boolean;
/**
* Disable or configure handling of async entrypoints specified in source code.
*/
entries?:
| false
| { [index: string]: false | JavascriptParserAsyncEntryDescription };
/** /**
* Enable warnings for full dynamic dependencies. * Enable warnings for full dynamic dependencies.
*/ */
@ -7489,6 +7607,11 @@ declare interface Output {
*/ */
devtoolNamespace?: string; devtoolNamespace?: string;
/**
* List of chunk format types enabled for use by entry points.
*/
enabledChunkFormatTypes?: string[];
/** /**
* List of chunk loading types enabled for use by entry points. * List of chunk loading types enabled for use by entry points.
*/ */
@ -7768,6 +7891,11 @@ declare interface OutputNormalized {
*/ */
devtoolNamespace?: string; devtoolNamespace?: string;
/**
* List of chunk format types enabled for use by entry points.
*/
enabledChunkFormatTypes?: string[];
/** /**
* List of chunk loading types enabled for use by entry points. * List of chunk loading types enabled for use by entry points.
*/ */