webpack 5.102.1 → 5.103.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +121 -134
  2. package/lib/CompatibilityPlugin.js +25 -2
  3. package/lib/Compilation.js +25 -2
  4. package/lib/ConcatenationScope.js +0 -15
  5. package/lib/CssModule.js +6 -1
  6. package/lib/DefinePlugin.js +11 -11
  7. package/lib/Dependency.js +8 -1
  8. package/lib/DependencyTemplate.js +1 -0
  9. package/lib/DotenvPlugin.js +457 -0
  10. package/lib/EnvironmentPlugin.js +19 -16
  11. package/lib/EvalSourceMapDevToolPlugin.js +16 -0
  12. package/lib/ExportsInfo.js +6 -2
  13. package/lib/ExternalModule.js +20 -28
  14. package/lib/ExternalModuleFactoryPlugin.js +10 -8
  15. package/lib/ExternalsPlugin.js +2 -1
  16. package/lib/ManifestPlugin.js +235 -0
  17. package/lib/Module.js +3 -0
  18. package/lib/ModuleGraph.js +2 -1
  19. package/lib/ModuleSourceTypesConstants.js +0 -6
  20. package/lib/MultiCompiler.js +1 -1
  21. package/lib/NodeStuffPlugin.js +419 -121
  22. package/lib/NormalModule.js +17 -16
  23. package/lib/RuntimeGlobals.js +22 -4
  24. package/lib/RuntimePlugin.js +27 -6
  25. package/lib/RuntimeTemplate.js +115 -56
  26. package/lib/SourceMapDevToolPlugin.js +20 -0
  27. package/lib/WebpackOptionsApply.js +33 -9
  28. package/lib/asset/AssetBytesGenerator.js +1 -1
  29. package/lib/asset/AssetGenerator.js +1 -2
  30. package/lib/asset/AssetSourceGenerator.js +1 -1
  31. package/lib/config/browserslistTargetHandler.js +5 -0
  32. package/lib/config/defaults.js +98 -18
  33. package/lib/config/normalization.js +2 -1
  34. package/lib/config/target.js +6 -0
  35. package/lib/css/CssGenerator.js +283 -57
  36. package/lib/css/CssLoadingRuntimeModule.js +2 -0
  37. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
  38. package/lib/css/CssModulesPlugin.js +84 -34
  39. package/lib/css/CssParser.js +1174 -667
  40. package/lib/css/walkCssTokens.js +97 -0
  41. package/lib/dependencies/CommonJsImportsParserPlugin.js +0 -9
  42. package/lib/dependencies/CommonJsPlugin.js +12 -0
  43. package/lib/dependencies/CssIcssExportDependency.js +247 -8
  44. package/lib/dependencies/CssIcssFromIdentifierDependency.js +124 -0
  45. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +48 -0
  46. package/lib/dependencies/CssIcssImportDependency.js +60 -54
  47. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +61 -0
  48. package/lib/dependencies/{CssSelfLocalIdentifierDependency.js → CssIcssSelfLocalIdentifierDependency.js} +88 -10
  49. package/lib/dependencies/CssIcssSymbolDependency.js +31 -29
  50. package/lib/dependencies/CssImportDependency.js +15 -5
  51. package/lib/dependencies/ExternalModuleInitFragment.js +1 -1
  52. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +95 -0
  53. package/lib/dependencies/HarmonyAcceptDependency.js +6 -1
  54. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -1
  55. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +12 -1
  56. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +32 -21
  57. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +12 -8
  58. package/lib/dependencies/HarmonyImportDependency.js +23 -27
  59. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +28 -69
  60. package/lib/dependencies/HarmonyImportSideEffectDependency.js +4 -3
  61. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -8
  62. package/lib/dependencies/ImportDependency.js +8 -2
  63. package/lib/dependencies/ImportEagerDependency.js +6 -3
  64. package/lib/dependencies/ImportMetaPlugin.js +97 -9
  65. package/lib/dependencies/ImportParserPlugin.js +19 -21
  66. package/lib/dependencies/ImportPhase.js +121 -0
  67. package/lib/dependencies/ImportWeakDependency.js +6 -3
  68. package/lib/dependencies/ModuleDependency.js +5 -1
  69. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
  70. package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -8
  71. package/lib/hmr/LazyCompilationPlugin.js +1 -0
  72. package/lib/ids/IdHelpers.js +4 -1
  73. package/lib/index.js +6 -0
  74. package/lib/javascript/ChunkHelpers.js +16 -5
  75. package/lib/javascript/JavascriptGenerator.js +101 -101
  76. package/lib/javascript/JavascriptModulesPlugin.js +23 -13
  77. package/lib/javascript/JavascriptParser.js +142 -38
  78. package/lib/json/JsonParser.js +7 -1
  79. package/lib/library/ModuleLibraryPlugin.js +0 -10
  80. package/lib/library/SystemLibraryPlugin.js +4 -0
  81. package/lib/library/UmdLibraryPlugin.js +1 -1
  82. package/lib/node/NodeTargetPlugin.js +9 -1
  83. package/lib/node/ReadFileCompileWasmPlugin.js +0 -2
  84. package/lib/optimize/ConcatenatedModule.js +161 -135
  85. package/lib/runtime/AsyncModuleRuntimeModule.js +28 -18
  86. package/lib/runtime/AutoPublicPathRuntimeModule.js +8 -3
  87. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +89 -55
  88. package/lib/util/comparators.js +4 -3
  89. package/lib/util/internalSerializables.js +4 -4
  90. package/lib/util/jsonParseEvenBetterErrors.js +10 -0
  91. package/lib/wasm/EnableWasmLoadingPlugin.js +10 -4
  92. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +8 -5
  93. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +8 -4
  94. package/lib/web/FetchCompileWasmPlugin.js +0 -2
  95. package/lib/webpack.js +85 -82
  96. package/module.d.ts +5 -0
  97. package/package.json +16 -14
  98. package/schemas/WebpackOptions.check.js +1 -1
  99. package/schemas/WebpackOptions.json +109 -27
  100. package/schemas/plugins/ManifestPlugin.check.d.ts +7 -0
  101. package/schemas/plugins/ManifestPlugin.check.js +6 -0
  102. package/schemas/plugins/ManifestPlugin.json +98 -0
  103. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  104. package/schemas/plugins/SourceMapDevToolPlugin.json +16 -3
  105. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  106. package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
  107. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  108. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  109. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
  110. package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
  111. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  112. package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
  113. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  114. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  115. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  116. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -1
  117. package/types.d.ts +560 -293
  118. package/lib/dependencies/CssLocalIdentifierDependency.js +0 -250
package/lib/CssModule.js CHANGED
@@ -30,9 +30,13 @@ class CssModule extends NormalModule {
30
30
  super(options);
31
31
 
32
32
  // Avoid override `layer` for `Module` class, because it is a feature to run module in specific layer
33
+ /** @type {CSSModuleCreateData['cssLayer']} */
33
34
  this.cssLayer = options.cssLayer;
35
+ /** @type {CSSModuleCreateData['supports']} */
34
36
  this.supports = options.supports;
37
+ /** @type {CSSModuleCreateData['media']} */
35
38
  this.media = options.media;
39
+ /** @type {CSSModuleCreateData['inheritance']} */
36
40
  this.inheritance = options.inheritance;
37
41
  }
38
42
 
@@ -150,7 +154,8 @@ class CssModule extends NormalModule {
150
154
  cssLayer: /** @type {EXPECTED_ANY} */ (null),
151
155
  supports: /** @type {EXPECTED_ANY} */ (null),
152
156
  media: /** @type {EXPECTED_ANY} */ (null),
153
- inheritance: /** @type {EXPECTED_ANY} */ (null)
157
+ inheritance: /** @type {EXPECTED_ANY} */ (null),
158
+ extractSourceMap: /** @type {EXPECTED_ANY} */ (null)
154
159
  });
155
160
  obj.deserialize(context);
156
161
  return obj;
@@ -354,20 +354,20 @@ class DefinePlugin {
354
354
  * @returns {void}
355
355
  */
356
356
  apply(compiler) {
357
- const definitions = this.definitions;
358
-
359
- /**
360
- * @type {Map<string, Set<string>>}
361
- */
362
- const finalByNestedKey = new Map();
363
- /**
364
- * @type {Map<string, Set<string>>}
365
- */
366
- const nestedByFinalKey = new Map();
367
-
368
357
  compiler.hooks.compilation.tap(
369
358
  PLUGIN_NAME,
370
359
  (compilation, { normalModuleFactory }) => {
360
+ const definitions = this.definitions;
361
+
362
+ /**
363
+ * @type {Map<string, Set<string>>}
364
+ */
365
+ const finalByNestedKey = new Map();
366
+ /**
367
+ * @type {Map<string, Set<string>>}
368
+ */
369
+ const nestedByFinalKey = new Map();
370
+
371
371
  const logger = compilation.getLogger("webpack.DefinePlugin");
372
372
  compilation.dependencyTemplates.set(
373
373
  ConstDependency,
package/lib/Dependency.js CHANGED
@@ -19,7 +19,7 @@ const memoize = require("./util/memoize");
19
19
  /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
20
20
  /** @typedef {import("./util/Hash")} Hash */
21
21
  /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
22
-
22
+ /** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
23
23
  /**
24
24
  * @typedef {object} UpdateHashContext
25
25
  * @property {ChunkGraph} chunkGraph
@@ -360,6 +360,13 @@ Object.defineProperty(Dependency.prototype, "module", {
360
360
  }
361
361
  });
362
362
 
363
+ /**
364
+ * @param {Dependency} dependency dep
365
+ * @returns {boolean} true if the dependency is a low priority dependency
366
+ */
367
+ Dependency.isLowPriorityDependency = (dependency) =>
368
+ /** @type {ModuleDependency} */ (dependency).sourceOrder === Infinity;
369
+
363
370
  // TODO remove in webpack 6
364
371
  Object.defineProperty(Dependency.prototype, "disconnect", {
365
372
  /**
@@ -41,6 +41,7 @@
41
41
  /**
42
42
  * @typedef {object} CssDependencyTemplateContextExtras
43
43
  * @property {CssData} cssData the css exports data
44
+ * @property {string} type the css exports data
44
45
  */
45
46
 
46
47
  /**
@@ -0,0 +1,457 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Natsu @xiaoxiaojx
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const FileSystemInfo = require("./FileSystemInfo");
9
+ const createSchemaValidation = require("./util/create-schema-validation");
10
+ const { join } = require("./util/fs");
11
+
12
+ /** @typedef {import("../declarations/WebpackOptions").DotenvPluginOptions} DotenvPluginOptions */
13
+ /** @typedef {import("./Compiler")} Compiler */
14
+ /** @typedef {import("./CacheFacade").ItemCacheFacade} ItemCacheFacade */
15
+ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
16
+ /** @typedef {import("./FileSystemInfo").Snapshot} Snapshot */
17
+
18
+ /** @typedef {Exclude<DotenvPluginOptions["prefix"], string | undefined>} Prefix */
19
+ /** @typedef {Record<string, string>} Env */
20
+
21
+ /** @type {DotenvPluginOptions} */
22
+ const DEFAULT_OPTIONS = {
23
+ prefix: "WEBPACK_",
24
+ template: [".env", ".env.local", ".env.[mode]", ".env.[mode].local"]
25
+ };
26
+
27
+ // Regex for parsing .env files
28
+ // ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L32
29
+ const LINE =
30
+ /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
31
+
32
+ const PLUGIN_NAME = "DotenvPlugin";
33
+
34
+ const validate = createSchemaValidation(
35
+ undefined,
36
+ () => {
37
+ const { definitions } = require("../schemas/WebpackOptions.json");
38
+
39
+ return {
40
+ definitions,
41
+ oneOf: [{ $ref: "#/definitions/DotenvPluginOptions" }]
42
+ };
43
+ },
44
+ {
45
+ name: "Dotenv Plugin",
46
+ baseDataPath: "options"
47
+ }
48
+ );
49
+
50
+ /**
51
+ * Parse .env file content
52
+ * ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L49
53
+ * @param {string | Buffer} src the source content to parse
54
+ * @returns {Env} parsed environment variables object
55
+ */
56
+ function parse(src) {
57
+ const obj = /** @type {Env} */ ({});
58
+
59
+ // Convert buffer to string
60
+ let lines = src.toString();
61
+
62
+ // Convert line breaks to same format
63
+ lines = lines.replace(/\r\n?/gm, "\n");
64
+
65
+ let match;
66
+ while ((match = LINE.exec(lines)) !== null) {
67
+ const key = match[1];
68
+
69
+ // Default undefined or null to empty string
70
+ let value = match[2] || "";
71
+
72
+ // Remove whitespace
73
+ value = value.trim();
74
+
75
+ // Check if double quoted
76
+ const maybeQuote = value[0];
77
+
78
+ // Remove surrounding quotes
79
+ value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
80
+
81
+ // Expand newlines if double quoted
82
+ if (maybeQuote === '"') {
83
+ value = value.replace(/\\n/g, "\n");
84
+ value = value.replace(/\\r/g, "\r");
85
+ }
86
+
87
+ // Add to object
88
+ obj[key] = value;
89
+ }
90
+
91
+ return obj;
92
+ }
93
+
94
+ /**
95
+ * Resolve escape sequences
96
+ * ported from https://github.com/motdotla/dotenv-expand
97
+ * @param {string} value value to resolve
98
+ * @returns {string} resolved value
99
+ */
100
+ function _resolveEscapeSequences(value) {
101
+ return value.replace(/\\\$/g, "$");
102
+ }
103
+
104
+ /**
105
+ * Expand environment variable value
106
+ * ported from https://github.com/motdotla/dotenv-expand
107
+ * @param {string} value value to expand
108
+ * @param {Record<string, string | undefined>} processEnv process.env object
109
+ * @param {Env} runningParsed running parsed object
110
+ * @returns {string} expanded value
111
+ */
112
+ function expandValue(value, processEnv, runningParsed) {
113
+ const env = { ...runningParsed, ...processEnv }; // process.env wins
114
+
115
+ const regex = /(?<!\\)\$\{([^{}]+)\}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
116
+
117
+ let result = value;
118
+ let match;
119
+ const seen = new Set(); // self-referential checker
120
+
121
+ while ((match = regex.exec(result)) !== null) {
122
+ seen.add(result);
123
+
124
+ const [template, bracedExpression, unbracedExpression] = match;
125
+ const expression = bracedExpression || unbracedExpression;
126
+
127
+ // match the operators `:+`, `+`, `:-`, and `-`
128
+ const opRegex = /(:\+|\+|:-|-)/;
129
+ // find first match
130
+ const opMatch = expression.match(opRegex);
131
+ const splitter = opMatch ? opMatch[0] : null;
132
+
133
+ const r = expression.split(/** @type {string} */ (splitter));
134
+ // const r = splitter ? expression.split(splitter) : [expression];
135
+
136
+ let defaultValue;
137
+ let value;
138
+
139
+ const key = r.shift();
140
+
141
+ if ([":+", "+"].includes(splitter || "")) {
142
+ defaultValue = env[key || ""] ? r.join(splitter || "") : "";
143
+ value = null;
144
+ } else {
145
+ defaultValue = r.join(splitter || "");
146
+ value = env[key || ""];
147
+ }
148
+
149
+ if (value) {
150
+ // self-referential check
151
+ result = seen.has(value)
152
+ ? result.replace(template, defaultValue)
153
+ : result.replace(template, value);
154
+ } else {
155
+ result = result.replace(template, defaultValue);
156
+ }
157
+
158
+ // if the result equaled what was in process.env and runningParsed then stop expanding
159
+ if (result === runningParsed[key || ""]) {
160
+ break;
161
+ }
162
+
163
+ regex.lastIndex = 0; // reset regex search position to re-evaluate after each replacement
164
+ }
165
+
166
+ return result;
167
+ }
168
+
169
+ /**
170
+ * Expand environment variables in parsed object
171
+ * ported from https://github.com/motdotla/dotenv-expand
172
+ * @param {{ parsed: Env, processEnv: Record<string, string | undefined> }} options expand options
173
+ * @returns {{ parsed: Env }} expanded options
174
+ */
175
+ function expand(options) {
176
+ // for use with progressive expansion
177
+ const runningParsed = /** @type {Env} */ ({});
178
+ const processEnv = options.processEnv;
179
+
180
+ // dotenv.config() ran before this so the assumption is process.env has already been set
181
+ for (const key in options.parsed) {
182
+ let value = options.parsed[key];
183
+
184
+ // short-circuit scenario: process.env was already set prior to the file value
185
+ value =
186
+ processEnv[key] && processEnv[key] !== value
187
+ ? /** @type {string} */ (processEnv[key])
188
+ : expandValue(value, processEnv, runningParsed);
189
+
190
+ const resolvedValue = _resolveEscapeSequences(value);
191
+
192
+ options.parsed[key] = resolvedValue;
193
+ // for use with progressive expansion
194
+ runningParsed[key] = resolvedValue;
195
+ }
196
+
197
+ // Part of `dotenv-expand` code, but we don't need it because of we don't modify `process.env`
198
+ // for (const processKey in options.parsed) {
199
+ // if (processEnv) {
200
+ // processEnv[processKey] = options.parsed[processKey];
201
+ // }
202
+ // }
203
+
204
+ return options;
205
+ }
206
+
207
+ /**
208
+ * Format environment variables as DefinePlugin definitions
209
+ * @param {Env} env environment variables
210
+ * @returns {Record<string, string>} formatted definitions
211
+ */
212
+ const envToDefinitions = (env) => {
213
+ const definitions = /** @type {Record<string, string>} */ ({});
214
+
215
+ for (const [key, value] of Object.entries(env)) {
216
+ const defValue = JSON.stringify(value);
217
+ definitions[`process.env.${key}`] = defValue;
218
+ definitions[`import.meta.env.${key}`] = defValue;
219
+ }
220
+
221
+ return definitions;
222
+ };
223
+
224
+ class DotenvPlugin {
225
+ /**
226
+ * @param {DotenvPluginOptions=} options options object
227
+ */
228
+ constructor(options = {}) {
229
+ validate(options);
230
+ this.options = { ...DEFAULT_OPTIONS, ...options };
231
+ }
232
+
233
+ /**
234
+ * @param {Compiler} compiler the compiler instance
235
+ * @returns {void}
236
+ */
237
+ apply(compiler) {
238
+ const definePlugin = new compiler.webpack.DefinePlugin({});
239
+ const prefixes = Array.isArray(this.options.prefix)
240
+ ? this.options.prefix
241
+ : [this.options.prefix || "WEBPACK_"];
242
+ /** @type {string | false} */
243
+ const dir =
244
+ typeof this.options.dir === "string"
245
+ ? this.options.dir
246
+ : typeof this.options.dir === "undefined"
247
+ ? compiler.context
248
+ : this.options.dir;
249
+
250
+ /** @type {undefined | Snapshot} */
251
+ let snapshot;
252
+
253
+ const cache = compiler.getCache(PLUGIN_NAME);
254
+ const identifier = JSON.stringify(this.options.template);
255
+ const itemCache = cache.getItemCache(identifier, null);
256
+
257
+ compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, async () => {
258
+ const { parsed, snapshot: newSnapshot } = dir
259
+ ? await this._loadEnv(compiler, itemCache, dir)
260
+ : { parsed: {} };
261
+ const env = this._getEnv(prefixes, parsed);
262
+
263
+ definePlugin.definitions = envToDefinitions(env || {});
264
+ snapshot = newSnapshot;
265
+ });
266
+
267
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
268
+ if (snapshot) {
269
+ compilation.fileDependencies.addAll(snapshot.getFileIterable());
270
+ compilation.missingDependencies.addAll(snapshot.getMissingIterable());
271
+ }
272
+ });
273
+
274
+ definePlugin.apply(compiler);
275
+ }
276
+
277
+ /**
278
+ * Get list of env files to load based on mode and template
279
+ * Similar to Vite's getEnvFilesForMode
280
+ * @private
281
+ * @param {InputFileSystem} inputFileSystem the input file system
282
+ * @param {string | false} dir the directory containing .env files
283
+ * @param {string | undefined} mode the mode (e.g., 'production', 'development')
284
+ * @returns {string[]} array of file paths to load
285
+ */
286
+ _getEnvFilesForMode(inputFileSystem, dir, mode) {
287
+ if (!dir) {
288
+ return [];
289
+ }
290
+
291
+ const { template } = /** @type {DotenvPluginOptions} */ (this.options);
292
+ const templates = template || [];
293
+
294
+ return templates
295
+ .map((pattern) => pattern.replace(/\[mode\]/g, mode || "development"))
296
+ .map((file) => join(inputFileSystem, dir, file));
297
+ }
298
+
299
+ /**
300
+ * Get parsed env variables from `.env` files
301
+ * @private
302
+ * @param {InputFileSystem} fs input file system
303
+ * @param {string} dir dir to load `.env` files
304
+ * @param {string} mode mode
305
+ * @returns {Promise<{parsed: Env, fileDependencies: string[], missingDependencies: string[]}>} parsed env variables and dependencies
306
+ */
307
+ async _getParsed(fs, dir, mode) {
308
+ /** @type {string[]} */
309
+ const fileDependencies = [];
310
+ /** @type {string[]} */
311
+ const missingDependencies = [];
312
+
313
+ // Get env files to load
314
+ const envFiles = this._getEnvFilesForMode(fs, dir, mode);
315
+
316
+ // Read all files
317
+ const contents = await Promise.all(
318
+ envFiles.map((filePath) =>
319
+ this._loadFile(fs, filePath).then(
320
+ (content) => {
321
+ fileDependencies.push(filePath);
322
+ return content;
323
+ },
324
+ () => {
325
+ // File doesn't exist, add to missingDependencies (this is normal)
326
+ missingDependencies.push(filePath);
327
+ return "";
328
+ }
329
+ )
330
+ )
331
+ );
332
+
333
+ // Parse all files and merge (later files override earlier ones)
334
+ // Similar to Vite's implementation
335
+ const parsed = /** @type {Env} */ ({});
336
+
337
+ for (const content of contents) {
338
+ if (!content) continue;
339
+ const entries = parse(content);
340
+ for (const key in entries) {
341
+ parsed[key] = entries[key];
342
+ }
343
+ }
344
+
345
+ return { parsed, fileDependencies, missingDependencies };
346
+ }
347
+
348
+ /**
349
+ * @private
350
+ * @param {Compiler} compiler compiler
351
+ * @param {ItemCacheFacade} itemCache item cache facade
352
+ * @param {string} dir directory to read
353
+ * @returns {Promise<{ parsed: Env, snapshot: Snapshot }>} parsed result and snapshot
354
+ */
355
+ async _loadEnv(compiler, itemCache, dir) {
356
+ const fs = /** @type {InputFileSystem} */ (compiler.inputFileSystem);
357
+ const fileSystemInfo = new FileSystemInfo(fs, {
358
+ unmanagedPaths: compiler.unmanagedPaths,
359
+ managedPaths: compiler.managedPaths,
360
+ immutablePaths: compiler.immutablePaths,
361
+ hashFunction: compiler.options.output.hashFunction
362
+ });
363
+
364
+ const result = await itemCache.getPromise();
365
+
366
+ if (result) {
367
+ const isSnapshotValid = await new Promise((resolve, reject) => {
368
+ fileSystemInfo.checkSnapshotValid(result.snapshot, (error, isValid) => {
369
+ if (error) {
370
+ reject(error);
371
+
372
+ return;
373
+ }
374
+
375
+ resolve(isValid);
376
+ });
377
+ });
378
+
379
+ if (isSnapshotValid) {
380
+ return { parsed: result.parsed, snapshot: result.snapshot };
381
+ }
382
+ }
383
+
384
+ const { parsed, fileDependencies, missingDependencies } =
385
+ await this._getParsed(
386
+ fs,
387
+ dir,
388
+ /** @type {string} */
389
+ (compiler.options.mode)
390
+ );
391
+
392
+ const startTime = Date.now();
393
+ const newSnapshot = await new Promise((resolve, reject) => {
394
+ fileSystemInfo.createSnapshot(
395
+ startTime,
396
+ fileDependencies,
397
+ null,
398
+ missingDependencies,
399
+ // `.env` files are build dependencies
400
+ compiler.options.snapshot.buildDependencies,
401
+ (err, snapshot) => {
402
+ if (err) return reject(err);
403
+ resolve(snapshot);
404
+ }
405
+ );
406
+ });
407
+
408
+ await itemCache.storePromise({ parsed, snapshot: newSnapshot });
409
+
410
+ return { parsed, snapshot: newSnapshot };
411
+ }
412
+
413
+ /**
414
+ * Generate env variables
415
+ * @private
416
+ * @param {Prefix} prefixes expose only environment variables that start with these prefixes
417
+ * @param {Env} parsed parsed env variables
418
+ * @returns {Env} env variables
419
+ */
420
+ _getEnv(prefixes, parsed) {
421
+ // Always expand environment variables (like Vite does)
422
+ // Make a copy of process.env so that dotenv-expand doesn't modify global process.env
423
+ const processEnv = { ...process.env };
424
+ expand({ parsed, processEnv });
425
+ const env = /** @type {Env} */ ({});
426
+
427
+ // Get all keys from parser and process.env
428
+ const keys = [...Object.keys(parsed), ...Object.keys(process.env)];
429
+
430
+ // Prioritize actual env variables from `process.env`, fallback to parsed
431
+ for (const key of keys) {
432
+ if (prefixes.some((prefix) => key.startsWith(prefix))) {
433
+ env[key] = process.env[key] ? process.env[key] : parsed[key];
434
+ }
435
+ }
436
+
437
+ return env;
438
+ }
439
+
440
+ /**
441
+ * Load a file with proper path resolution
442
+ * @private
443
+ * @param {InputFileSystem} fs the input file system
444
+ * @param {string} file the file to load
445
+ * @returns {Promise<string>} the content of the file
446
+ */
447
+ _loadFile(fs, file) {
448
+ return new Promise((resolve, reject) => {
449
+ fs.readFile(file, (err, content) => {
450
+ if (err) reject(err);
451
+ else resolve(/** @type {Buffer} */ (content).toString() || "");
452
+ });
453
+ });
454
+ }
455
+ }
456
+
457
+ module.exports = DotenvPlugin;
@@ -39,16 +39,18 @@ class EnvironmentPlugin {
39
39
  * @returns {void}
40
40
  */
41
41
  apply(compiler) {
42
- /** @type {Record<string, CodeValue>} */
43
- const definitions = {};
44
- for (const key of this.keys) {
45
- const value =
46
- process.env[key] !== undefined
47
- ? process.env[key]
48
- : this.defaultValues[key];
42
+ const definePlugin = new DefinePlugin({});
49
43
 
50
- if (value === undefined) {
51
- compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
44
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
45
+ /** @type {Record<string, CodeValue>} */
46
+ const definitions = {};
47
+ for (const key of this.keys) {
48
+ const value =
49
+ process.env[key] !== undefined
50
+ ? process.env[key]
51
+ : this.defaultValues[key];
52
+
53
+ if (value === undefined) {
52
54
  const error = new WebpackError(
53
55
  `${PLUGIN_NAME} - ${key} environment variable is undefined.\n\n` +
54
56
  "You can pass an object with default values to suppress this warning.\n" +
@@ -57,14 +59,15 @@ class EnvironmentPlugin {
57
59
 
58
60
  error.name = "EnvVariableNotDefinedError";
59
61
  compilation.errors.push(error);
60
- });
62
+ }
63
+ const defValue =
64
+ value === undefined ? "undefined" : JSON.stringify(value);
65
+ definitions[`process.env.${key}`] = defValue;
66
+ definitions[`import.meta.env.${key}`] = defValue;
61
67
  }
62
-
63
- definitions[`process.env.${key}`] =
64
- value === undefined ? "undefined" : JSON.stringify(value);
65
- }
66
-
67
- new DefinePlugin(definitions).apply(compiler);
68
+ definePlugin.definitions = definitions;
69
+ });
70
+ definePlugin.apply(compiler);
68
71
  }
69
72
  }
70
73
 
@@ -18,6 +18,7 @@ const { makePathsAbsolute } = require("./util/identifier");
18
18
  /** @typedef {import("webpack-sources").RawSourceMap} RawSourceMap */
19
19
  /** @typedef {import("webpack-sources").Source} Source */
20
20
  /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */
21
+ /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").Rules} Rules */
21
22
  /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
22
23
  /** @typedef {import("./Compiler")} Compiler */
23
24
 
@@ -163,6 +164,21 @@ class EvalSourceMapDevToolPlugin {
163
164
  }
164
165
  );
165
166
  sourceMap.sources = moduleFilenames;
167
+ sourceMap.ignoreList = options.ignoreList
168
+ ? sourceMap.sources.reduce(
169
+ /** @type {(acc: number[], sourceName: string, idx: number) => number[]} */ (
170
+ (acc, sourceName, idx) => {
171
+ const rule = /** @type {Rules} */ (options.ignoreList);
172
+ if (ModuleFilenameHelpers.matchPart(sourceName, rule)) {
173
+ acc.push(idx);
174
+ }
175
+ return acc;
176
+ }
177
+ ),
178
+ []
179
+ )
180
+ : [];
181
+
166
182
  if (options.noSources) {
167
183
  sourceMap.sourcesContent = undefined;
168
184
  }
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const { ImportPhaseUtils } = require("./dependencies/ImportPhase");
8
9
  const { equals } = require("./util/ArrayHelpers");
9
10
  const SortableSet = require("./util/SortableSet");
10
11
  const makeSerializable = require("./util/makeSerializable");
@@ -1345,8 +1346,11 @@ class ExportInfo {
1345
1346
  export: rawTarget.export,
1346
1347
  deferred: Boolean(
1347
1348
  rawTarget.connection.dependency &&
1348
- /** @type {HarmonyImportDependency} */
1349
- (rawTarget.connection.dependency).defer
1349
+ ImportPhaseUtils.isDefer(
1350
+ /** @type {HarmonyImportDependency} */ (
1351
+ rawTarget.connection.dependency
1352
+ ).phase
1353
+ )
1350
1354
  )
1351
1355
  };
1352
1356
  for (;;) {