add parser options for dynamic import

- add dynamicImportMode for ContextModule
- add dynamicImportPrefetch for prefetch order
- add dynamicImportPreload for preload order
This commit is contained in:
Ivan Kopeykin 2022-03-09 10:27:02 +03:00
parent 770dea1fb4
commit 62d50bad4b
16 changed files with 300 additions and 13 deletions

View File

@ -2929,6 +2929,24 @@ export interface JavascriptParserOptions {
* Enable/disable parsing of magic comments in CommonJs syntax.
*/
commonjsMagicComments?: boolean;
/**
* Specifies global mode for dynamic import.
*/
dynamicImportMode?:
| "sync"
| "eager"
| "weak"
| "async-weak"
| "lazy"
| "lazy-once";
/**
* Specifies global prefetch for dynamic import.
*/
dynamicImportPrefetch?: boolean;
/**
* Specifies global preload for dynamic import.
*/
dynamicImportPreload?: boolean;
/**
* Specifies the behavior of invalid export names in "import ... from ..." and "export ... from ...".
*/

View File

@ -45,7 +45,7 @@ const makeSerializable = require("./util/makeSerializable");
/** @template T @typedef {import("./util/LazySet")<T>} LazySet<T> */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */
/** @typedef {import("../declarations/WebpackOptions").JavascriptParserOptions["dynamicImportMode"]} ContextMode Context mode */
/**
* @typedef {Object} ContextOptions

View File

@ -470,6 +470,8 @@ const applyJavascriptParserOptionsDefaults = (
D(parserOptions, "wrappedContextCritical", false);
D(parserOptions, "strictThisContextOnImports", false);
D(parserOptions, "importMeta", true);
D(parserOptions, "dynamicImportPrefetch", false);
D(parserOptions, "dynamicImportPreload", false);
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
};

View File

@ -13,6 +13,7 @@ const ImportMetaContextDependency = require("./ImportMetaContextDependency");
/** @typedef {import("estree").Expression} ExpressionNode */
/** @typedef {import("estree").ObjectExpression} ObjectExpressionNode */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../ContextModule").ContextModuleOptions} ContextModuleOptions */
/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
@ -35,6 +36,13 @@ function createError(msg, loc) {
}
module.exports = class ImportMetaContextDependencyParserPlugin {
/**
* @param {JavascriptParserOptions} options options
*/
constructor(options) {
this.options = options;
}
apply(parser) {
parser.hooks.evaluateIdentifier
.for("import.meta.webpackContext")
@ -59,7 +67,7 @@ module.exports = class ImportMetaContextDependencyParserPlugin {
let regExp = /^\.\/.*$/;
let recursive = true;
/** @type {ContextModuleOptions["mode"]} */
let mode = "sync";
let mode = this.options.dynamicImportMode || "sync";
/** @type {ContextModuleOptions["include"]} */
let include;
/** @type {ContextModuleOptions["exclude"]} */
@ -70,6 +78,9 @@ module.exports = class ImportMetaContextDependencyParserPlugin {
let chunkName;
/** @type {ContextModuleOptions["referencedExports"]} */
let exports;
if (this.options.dynamicImportPrefetch) groupOptions.prefetchOrder = 0;
if (this.options.dynamicImportPreload) groupOptions.preloadOrder = 0;
if (optionsNode) {
for (const prop of optionsNode.properties) {
if (prop.type !== "Property" || prop.key.type !== "Identifier") {

View File

@ -42,7 +42,9 @@ class ImportMetaContextPlugin {
)
return;
new ImportMetaContextDependencyParserPlugin().apply(parser);
new ImportMetaContextDependencyParserPlugin(parserOptions).apply(
parser
);
};
normalModuleFactory.hooks.parser

View File

@ -14,10 +14,14 @@ const ImportDependency = require("./ImportDependency");
const ImportEagerDependency = require("./ImportEagerDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
/** @typedef {import("../ContextModule").ContextMode} ContextMode */
class ImportParserPlugin {
/**
* @param {JavascriptParserOptions} options options
*/
constructor(options) {
this.options = options;
}
@ -28,7 +32,7 @@ class ImportParserPlugin {
let chunkName = null;
/** @type {ContextMode} */
let mode = "lazy";
let mode = this.options.dynamicImportMode || "lazy";
let include = null;
let exclude = null;
/** @type {string[][] | null} */
@ -36,6 +40,9 @@ class ImportParserPlugin {
/** @type {RawChunkGroupOptions} */
const groupOptions = {};
if (this.options.dynamicImportPreload) groupOptions.preloadOrder = 0;
if (this.options.dynamicImportPrefetch) groupOptions.prefetchOrder = 0;
const { options: importOptions, errors: commentErrors } =
parser.parseCommentOptions(expr.range);

File diff suppressed because one or more lines are too long

View File

@ -1580,6 +1580,18 @@
"description": "Enable/disable parsing of magic comments in CommonJs syntax.",
"type": "boolean"
},
"dynamicImportMode": {
"description": "Specifies global mode for dynamic import.",
"enum": ["sync", "eager", "weak", "async-weak", "lazy", "lazy-once"]
},
"dynamicImportPrefetch": {
"description": "Specifies global prefetch for dynamic import.",
"type": "boolean"
},
"dynamicImportPreload": {
"description": "Specifies global preload for dynamic import.",
"type": "boolean"
},
"exportsPresence": {
"description": "Specifies the behavior of invalid export names in \"import ... from ...\" and \"export ... from ...\".",
"enum": ["error", "warn", "auto", false]

View File

@ -214,6 +214,8 @@ describe("snapshots", () => {
},
},
"javascript": Object {
"dynamicImportPrefetch": false,
"dynamicImportPreload": false,
"exprContextCritical": true,
"exprContextRecursive": true,
"exprContextRegExp": false,

View File

@ -1503,6 +1503,53 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-auto-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportMode",
"type": "enum",
"values": Array [
"sync",
"eager",
"weak",
"async-weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-auto-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-auto-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-auto-exports-presence": Object {
"configs": Array [
Object {
@ -2080,6 +2127,53 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportMode",
"type": "enum",
"values": Array [
"sync",
"eager",
"weak",
"async-weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-exports-presence": Object {
"configs": Array [
Object {
@ -2228,6 +2322,53 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportMode",
"type": "enum",
"values": Array [
"sync",
"eager",
"weak",
"async-weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-node": Object {
"configs": Array [
Object {
@ -2618,6 +2759,53 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportMode",
"type": "enum",
"values": Array [
"sync",
"eager",
"weak",
"async-weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-esm-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-exports-presence": Object {
"configs": Array [
Object {

View File

@ -1176,6 +1176,17 @@ cacheable modules 142 bytes
webpack x.x.x compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for import-weak-parser-option 1`] = `
"asset entry.js 13 KiB [emitted] (name: entry)
asset 836.js 138 bytes [emitted]
runtime modules 7.68 KiB 10 modules
orphan modules 37 bytes [orphan] 1 module
cacheable modules 116 bytes
./entry.js 94 bytes [built] [code generated]
./modules/b.js 22 bytes [built] [code generated]
webpack x.x.x compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for import-with-invalid-options-comments 1`] = `
"runtime modules 8.6 KiB 12 modules
cacheable modules 559 bytes

View File

@ -0,0 +1,3 @@
import("./modules/a");
import("./modules/b");
import(/* webpackMode: "lazy" */"./modules/b");

View File

@ -0,0 +1,2 @@
import("./b");
module.exports = "a";

View File

@ -0,0 +1 @@
module.exports = "b";

View File

@ -0,0 +1,14 @@
/** @type {import("../../../").Configuration} */
module.exports = {
mode: "production",
entry: {
entry: "./entry"
},
module: {
parser: {
javascript: {
dynamicImportMode: "weak"
}
}
}
};

30
types.d.ts vendored
View File

@ -2481,13 +2481,6 @@ declare interface ContextHash {
resolved?: string;
symlinks?: Set<string>;
}
type ContextMode =
| "weak"
| "sync"
| "eager"
| "async-weak"
| "lazy"
| "lazy-once";
declare abstract class ContextModuleFactory extends ModuleFactory {
hooks: Readonly<{
beforeResolve: AsyncSeriesWaterfallHook<[any]>;
@ -2515,7 +2508,7 @@ declare abstract class ContextModuleFactory extends ModuleFactory {
}
declare interface ContextModuleOptions {
mode: ContextMode;
mode?: "weak" | "sync" | "eager" | "async-weak" | "lazy" | "lazy-once";
recursive: boolean;
regExp: RegExp;
namespaceObject?: boolean | "strict";
@ -5468,6 +5461,27 @@ declare interface JavascriptParserOptions {
*/
commonjsMagicComments?: boolean;
/**
* Specifies global mode for dynamic import.
*/
dynamicImportMode?:
| "weak"
| "sync"
| "eager"
| "async-weak"
| "lazy"
| "lazy-once";
/**
* Specifies global prefetch for dynamic import.
*/
dynamicImportPrefetch?: boolean;
/**
* Specifies global preload for dynamic import.
*/
dynamicImportPreload?: boolean;
/**
* Specifies the behavior of invalid export names in "import ... from ..." and "export ... from ...".
*/