- add new config section importMeta

- use it in ImportMetaPlugin to switch it off as necessary
This commit is contained in:
pavelsavara 2022-01-25 16:08:56 +01:00
parent 4abe329dcd
commit 73bb43139d
11 changed files with 117 additions and 9 deletions

View File

@ -351,6 +351,10 @@ export type RuleSetRules = ("..." | RuleSetRule)[];
*/ */
export type GeneratorOptionsByModuleType = GeneratorOptionsByModuleTypeKnown & export type GeneratorOptionsByModuleType = GeneratorOptionsByModuleTypeKnown &
GeneratorOptionsByModuleTypeUnknown; GeneratorOptionsByModuleTypeUnknown;
/**
* Options object for es6 import.meta features.
*/
export type ImportMeta = false | ImportMetaOptions;
/** /**
* Don't parse files matching. It's matched against the full resolved request. * Don't parse files matching. It's matched against the full resolved request.
*/ */
@ -1242,6 +1246,10 @@ export interface ModuleOptions {
* Specify options for each generator. * Specify options for each generator.
*/ */
generator?: GeneratorOptionsByModuleType; generator?: GeneratorOptionsByModuleType;
/**
* Options object for es6 import.meta features.
*/
importMeta?: ImportMeta;
/** /**
* Don't parse files matching. It's matched against the full resolved request. * Don't parse files matching. It's matched against the full resolved request.
*/ */
@ -1584,6 +1592,15 @@ export interface ResolvePluginInstance {
apply: (resolver: import("enhanced-resolve").Resolver) => void; apply: (resolver: import("enhanced-resolve").Resolver) => void;
[k: string]: any; [k: string]: any;
} }
/**
* Options object for es6 import.meta features.
*/
export interface ImportMetaOptions {
/**
* Include a polyfill for the 'import.meta.url' variable.
*/
url?: false | true;
}
/** /**
* Options object for node compatibility features. * Options object for node compatibility features.
*/ */
@ -3095,6 +3112,10 @@ export interface ModuleOptionsNormalized {
* Specify options for each generator. * Specify options for each generator.
*/ */
generator: GeneratorOptionsByModuleType; generator: GeneratorOptionsByModuleType;
/**
* Options object for es6 import.meta features.
*/
importMeta?: ImportMeta;
/** /**
* Don't parse files matching. It's matched against the full resolved request. * Don't parse files matching. It's matched against the full resolved request.
*/ */

View File

@ -362,7 +362,7 @@ class WebpackOptionsApply extends OptionsApply {
new RequireContextPlugin().apply(compiler); new RequireContextPlugin().apply(compiler);
new ImportPlugin().apply(compiler); new ImportPlugin().apply(compiler);
new SystemPlugin().apply(compiler); new SystemPlugin().apply(compiler);
new ImportMetaPlugin().apply(compiler); new ImportMetaPlugin(options.module.importMeta).apply(compiler);
new URLPlugin().apply(compiler); new URLPlugin().apply(compiler);
new WorkerPlugin( new WorkerPlugin(
options.output.workerChunkLoading, options.output.workerChunkLoading,

View File

@ -23,6 +23,7 @@ const {
/** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */ /** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */
/** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */ /** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
/** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */ /** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */
/** @typedef {import("../../declarations/WebpackOptions").ImportMeta} ImportMeta */
/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */ /** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */ /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../../declarations/WebpackOptions").Library} Library */ /** @typedef {import("../../declarations/WebpackOptions").Library} Library */
@ -495,6 +496,9 @@ const applyModuleDefaults = (
D(module, "unsafeCache", false); D(module, "unsafeCache", false);
} }
D(module.parser, "importMeta", {});
applyMetaDefaults(module.parser.importMeta);
F(module.parser, "asset", () => ({})); F(module.parser, "asset", () => ({}));
F(module.parser.asset, "dataUrlCondition", () => ({})); F(module.parser.asset, "dataUrlCondition", () => ({}));
if (typeof module.parser.asset.dataUrlCondition === "object") { if (typeof module.parser.asset.dataUrlCondition === "object") {
@ -1082,6 +1086,15 @@ const applyNodeDefaults = (node, { futureDefaults, targetProperties }) => {
}); });
}; };
/**
* @param {ImportMeta} meta options
* @returns {void}
*/
const applyMetaDefaults = meta => {
if (meta === false) return;
D(meta, "url", true);
};
/** /**
* @param {Performance} performance options * @param {Performance} performance options
* @param {Object} options options * @param {Object} options options

View File

@ -219,6 +219,7 @@ const getNormalizedWebpackOptions = config => {
module: nestedConfig(config.module, module => ({ module: nestedConfig(config.module, module => ({
noParse: module.noParse, noParse: module.noParse,
unsafeCache: module.unsafeCache, unsafeCache: module.unsafeCache,
importMeta: nestedConfig(module.importMeta, importMeta => importMeta),
parser: keyedNestedConfig(module.parser, cloneObject, { parser: keyedNestedConfig(module.parser, cloneObject, {
javascript: parserOptions => ({ javascript: parserOptions => ({
unknownContextRequest: module.unknownContextRequest, unknownContextRequest: module.unknownContextRequest,

View File

@ -29,10 +29,18 @@ const getCriticalDependencyWarning = memoize(() =>
); );
class ImportMetaPlugin { class ImportMetaPlugin {
/**
* @param {import("../../declarations/WebpackOptions").ImportMeta} options options
*/
constructor(options) {
this.options = options;
}
/** /**
* @param {Compiler} compiler compiler * @param {Compiler} compiler compiler
*/ */
apply(compiler) { apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap( compiler.hooks.compilation.tap(
"ImportMetaPlugin", "ImportMetaPlugin",
(compilation, { normalModuleFactory }) => { (compilation, { normalModuleFactory }) => {
@ -49,6 +57,8 @@ class ImportMetaPlugin {
* @returns {void} * @returns {void}
*/ */
const parserHandler = (parser, parserOptions) => { const parserHandler = (parser, parserOptions) => {
if (options === false) return;
/// import.meta direct /// /// import.meta direct ///
parser.hooks.typeof parser.hooks.typeof
.for("import.meta") .for("import.meta")
@ -106,14 +116,16 @@ class ImportMetaPlugin {
parser.hooks.evaluateTypeof parser.hooks.evaluateTypeof
.for("import.meta.url") .for("import.meta.url")
.tap("ImportMetaPlugin", evaluateToString("string")); .tap("ImportMetaPlugin", evaluateToString("string"));
parser.hooks.evaluateIdentifier
.for("import.meta.url")
.tap("ImportMetaPlugin", expr => {
return new BasicEvaluatedExpression()
.setString(getUrl(parser.state.module))
.setRange(expr.range);
});
if (options.url) {
parser.hooks.evaluateIdentifier
.for("import.meta.url")
.tap("ImportMetaPlugin", expr => {
return new BasicEvaluatedExpression()
.setString(getUrl(parser.state.module))
.setRange(expr.range);
});
}
/// import.meta.webpack /// /// import.meta.webpack ///
const webpackVersion = parseInt( const webpackVersion = parseInt(
require("../../package.json").version, require("../../package.json").version,

File diff suppressed because one or more lines are too long

View File

@ -1505,10 +1505,32 @@
"description": "The name of the native import() function (can be exchanged for a polyfill).", "description": "The name of the native import() function (can be exchanged for a polyfill).",
"type": "string" "type": "string"
}, },
"ImportMeta": {
"description": "Options object for es6 import.meta features.",
"anyOf": [
{
"enum": [false]
},
{
"$ref": "#/definitions/ImportMetaOptions"
}
]
},
"ImportMetaName": { "ImportMetaName": {
"description": "The name of the native import.meta object (can be exchanged for a polyfill).", "description": "The name of the native import.meta object (can be exchanged for a polyfill).",
"type": "string" "type": "string"
}, },
"ImportMetaOptions": {
"description": "Options object for es6 import.meta features.",
"type": "object",
"additionalProperties": false,
"properties": {
"url": {
"description": "Include a polyfill for the 'import.meta.url' variable.",
"enum": [false, true]
}
}
},
"InfrastructureLogging": { "InfrastructureLogging": {
"description": "Options for infrastructure level logging.", "description": "Options for infrastructure level logging.",
"type": "object", "type": "object",
@ -2103,6 +2125,9 @@
"generator": { "generator": {
"$ref": "#/definitions/GeneratorOptionsByModuleType" "$ref": "#/definitions/GeneratorOptionsByModuleType"
}, },
"importMeta": {
"$ref": "#/definitions/ImportMeta"
},
"noParse": { "noParse": {
"$ref": "#/definitions/NoParse" "$ref": "#/definitions/NoParse"
}, },
@ -2195,6 +2220,9 @@
"generator": { "generator": {
"$ref": "#/definitions/GeneratorOptionsByModuleType" "$ref": "#/definitions/GeneratorOptionsByModuleType"
}, },
"importMeta": {
"$ref": "#/definitions/ImportMeta"
},
"noParse": { "noParse": {
"$ref": "#/definitions/NoParse" "$ref": "#/definitions/NoParse"
}, },

View File

@ -1,7 +1,13 @@
import imported from "./imported.mjs"; import imported from "./imported.mjs";
import value from "./module"; import value from "./module";
import { metaUrl } from "./meta";
it("should allow to use externals in concatenated modules", () => { it("should allow to use externals in concatenated modules", () => {
expect(imported).toBe(42); expect(imported).toBe(42);
expect(value).toBe(40); expect(value).toBe(40);
}); });
it("all bundled files should have same url, when module.importMeta.url === false", () => {
export const localMetaUrl = import.meta.url;
expect(localMetaUrl).toBe(metaUrl)
});

View File

@ -0,0 +1 @@
export const metaUrl = import.meta.url;

View File

@ -1,5 +1,10 @@
/** @type {import("../../../../").Configuration} */ /** @type {import("../../../../").Configuration} */
module.exports = { module.exports = {
module: {
importMeta: {
url: false
}
},
entry: { entry: {
main: "./index.js", main: "./index.js",
imported: { imported: {

21
types.d.ts vendored
View File

@ -4628,6 +4628,16 @@ type IgnorePluginOptions =
*/ */
checkResource: (resource: string, context: string) => boolean; checkResource: (resource: string, context: string) => boolean;
}; };
/**
* Options object for es6 import.meta features.
*/
declare interface ImportMetaOptions {
/**
* Include a polyfill for the 'import.meta.url' variable.
*/
url?: boolean;
}
declare interface ImportModuleOptions { declare interface ImportModuleOptions {
/** /**
* the target layer * the target layer
@ -6392,6 +6402,7 @@ declare interface LoaderRunnerLoaderContext<OptionsType> {
/** /**
* An array of all the loaders. It is writeable in the pitch phase. * An array of all the loaders. It is writeable in the pitch phase.
* loaders = [{request: string, path: string, query: string, module: function}] * loaders = [{request: string, path: string, query: string, module: function}]
*
* In the example: * In the example:
* [ * [
* { request: "/abc/loader1.js?xyz", * { request: "/abc/loader1.js?xyz",
@ -7053,6 +7064,11 @@ declare interface ModuleOptions {
*/ */
generator?: GeneratorOptionsByModuleType; generator?: GeneratorOptionsByModuleType;
/**
* Options object for es6 import.meta features.
*/
importMeta?: false | ImportMetaOptions;
/** /**
* Don't parse files matching. It's matched against the full resolved request. * Don't parse files matching. It's matched against the full resolved request.
*/ */
@ -7133,6 +7149,11 @@ declare interface ModuleOptionsNormalized {
*/ */
generator: GeneratorOptionsByModuleType; generator: GeneratorOptionsByModuleType;
/**
* Options object for es6 import.meta features.
*/
importMeta?: false | ImportMetaOptions;
/** /**
* Don't parse files matching. It's matched against the full resolved request. * Don't parse files matching. It's matched against the full resolved request.
*/ */