webpack 5.102.0 → 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 (146) hide show
  1. package/README.md +121 -134
  2. package/lib/ChunkGraph.js +2 -2
  3. package/lib/CodeGenerationResults.js +1 -1
  4. package/lib/CompatibilityPlugin.js +25 -2
  5. package/lib/Compilation.js +30 -13
  6. package/lib/ConcatenationScope.js +0 -15
  7. package/lib/ContextModule.js +3 -1
  8. package/lib/CssModule.js +6 -1
  9. package/lib/DefinePlugin.js +12 -12
  10. package/lib/Dependency.js +8 -1
  11. package/lib/DependencyTemplate.js +1 -0
  12. package/lib/DependencyTemplates.js +1 -1
  13. package/lib/DotenvPlugin.js +457 -0
  14. package/lib/EnvironmentPlugin.js +19 -16
  15. package/lib/EvalSourceMapDevToolPlugin.js +16 -0
  16. package/lib/ExportsInfo.js +6 -2
  17. package/lib/ExternalModule.js +20 -28
  18. package/lib/ExternalModuleFactoryPlugin.js +10 -8
  19. package/lib/ExternalsPlugin.js +2 -1
  20. package/lib/FileSystemInfo.js +9 -12
  21. package/lib/ManifestPlugin.js +235 -0
  22. package/lib/Module.js +3 -0
  23. package/lib/ModuleFilenameHelpers.js +1 -1
  24. package/lib/ModuleGraph.js +2 -1
  25. package/lib/ModuleSourceTypesConstants.js +0 -6
  26. package/lib/MultiCompiler.js +1 -1
  27. package/lib/NodeStuffPlugin.js +419 -121
  28. package/lib/NormalModule.js +18 -17
  29. package/lib/NormalModuleFactory.js +75 -4
  30. package/lib/RuntimeGlobals.js +22 -4
  31. package/lib/RuntimePlugin.js +27 -6
  32. package/lib/RuntimeTemplate.js +125 -57
  33. package/lib/SourceMapDevToolPlugin.js +26 -8
  34. package/lib/WebpackOptionsApply.js +33 -9
  35. package/lib/asset/AssetBytesGenerator.js +2 -1
  36. package/lib/asset/AssetGenerator.js +3 -5
  37. package/lib/asset/AssetSourceGenerator.js +1 -1
  38. package/lib/cache/getLazyHashedEtag.js +1 -1
  39. package/lib/config/browserslistTargetHandler.js +82 -76
  40. package/lib/config/defaults.js +105 -20
  41. package/lib/config/normalization.js +2 -1
  42. package/lib/config/target.js +7 -1
  43. package/lib/css/CssGenerator.js +283 -57
  44. package/lib/css/CssLoadingRuntimeModule.js +2 -0
  45. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
  46. package/lib/css/CssModulesPlugin.js +86 -40
  47. package/lib/css/CssParser.js +1174 -667
  48. package/lib/css/walkCssTokens.js +98 -1
  49. package/lib/dependencies/CommonJsImportsParserPlugin.js +0 -9
  50. package/lib/dependencies/CommonJsPlugin.js +12 -0
  51. package/lib/dependencies/ContextElementDependency.js +2 -2
  52. package/lib/dependencies/CssIcssExportDependency.js +247 -8
  53. package/lib/dependencies/CssIcssFromIdentifierDependency.js +124 -0
  54. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +48 -0
  55. package/lib/dependencies/CssIcssImportDependency.js +60 -54
  56. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +61 -0
  57. package/lib/dependencies/{CssSelfLocalIdentifierDependency.js → CssIcssSelfLocalIdentifierDependency.js} +88 -10
  58. package/lib/dependencies/CssIcssSymbolDependency.js +31 -29
  59. package/lib/dependencies/CssImportDependency.js +15 -5
  60. package/lib/dependencies/ExternalModuleInitFragment.js +1 -1
  61. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +95 -0
  62. package/lib/dependencies/HarmonyAcceptDependency.js +6 -1
  63. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -1
  64. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +12 -1
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +32 -21
  66. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +12 -8
  67. package/lib/dependencies/HarmonyImportDependency.js +27 -28
  68. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +28 -69
  69. package/lib/dependencies/HarmonyImportSideEffectDependency.js +4 -3
  70. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -8
  71. package/lib/dependencies/ImportContextDependency.js +13 -0
  72. package/lib/dependencies/ImportDependency.js +10 -4
  73. package/lib/dependencies/ImportEagerDependency.js +6 -3
  74. package/lib/dependencies/ImportMetaPlugin.js +98 -10
  75. package/lib/dependencies/ImportParserPlugin.js +19 -21
  76. package/lib/dependencies/ImportPhase.js +121 -0
  77. package/lib/dependencies/ImportWeakDependency.js +6 -3
  78. package/lib/dependencies/ModuleDependency.js +5 -1
  79. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
  80. package/lib/dependencies/WorkerPlugin.js +1 -3
  81. package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -8
  82. package/lib/hmr/LazyCompilationPlugin.js +1 -0
  83. package/lib/ids/HashedModuleIdsPlugin.js +5 -7
  84. package/lib/ids/IdHelpers.js +5 -2
  85. package/lib/index.js +6 -0
  86. package/lib/javascript/ChunkHelpers.js +16 -5
  87. package/lib/javascript/JavascriptGenerator.js +101 -101
  88. package/lib/javascript/JavascriptModulesPlugin.js +25 -16
  89. package/lib/javascript/JavascriptParser.js +143 -39
  90. package/lib/json/JsonParser.js +7 -1
  91. package/lib/library/ModuleLibraryPlugin.js +0 -10
  92. package/lib/library/SystemLibraryPlugin.js +19 -5
  93. package/lib/library/UmdLibraryPlugin.js +1 -1
  94. package/lib/node/NodeTargetPlugin.js +9 -1
  95. package/lib/node/ReadFileCompileWasmPlugin.js +0 -2
  96. package/lib/optimize/ConcatenatedModule.js +161 -135
  97. package/lib/optimize/RealContentHashPlugin.js +5 -3
  98. package/lib/runtime/AsyncModuleRuntimeModule.js +28 -18
  99. package/lib/runtime/AutoPublicPathRuntimeModule.js +8 -3
  100. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +89 -55
  101. package/lib/serialization/FileMiddleware.js +1 -1
  102. package/lib/serialization/ObjectMiddleware.js +1 -1
  103. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -1
  104. package/lib/util/Hash.js +35 -5
  105. package/lib/util/comparators.js +4 -3
  106. package/lib/util/create-schema-validation.js +1 -1
  107. package/lib/util/createHash.js +85 -15
  108. package/lib/util/hash/BatchedHash.js +47 -8
  109. package/lib/util/hash/wasm-hash.js +53 -13
  110. package/lib/util/internalSerializables.js +4 -4
  111. package/lib/util/jsonParseEvenBetterErrors.js +10 -0
  112. package/lib/wasm/EnableWasmLoadingPlugin.js +10 -4
  113. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +8 -5
  114. package/lib/wasm-async/AsyncWebAssemblyParser.js +0 -9
  115. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +8 -4
  116. package/lib/wasm-sync/WebAssemblyParser.js +0 -9
  117. package/lib/web/FetchCompileWasmPlugin.js +0 -2
  118. package/lib/web/JsonpChunkLoadingRuntimeModule.js +1 -1
  119. package/lib/webpack.js +85 -82
  120. package/module.d.ts +5 -0
  121. package/package.json +28 -26
  122. package/schemas/WebpackOptions.check.js +1 -1
  123. package/schemas/WebpackOptions.json +110 -15
  124. package/schemas/plugins/{HashedModuleIdsPlugin.check.d.ts → ManifestPlugin.check.d.ts} +1 -1
  125. package/schemas/plugins/ManifestPlugin.check.js +6 -0
  126. package/schemas/plugins/ManifestPlugin.json +98 -0
  127. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  128. package/schemas/plugins/SourceMapDevToolPlugin.json +16 -3
  129. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  130. package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
  131. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  132. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  133. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
  134. package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
  135. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  136. package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
  137. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  138. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  139. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  140. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +7 -0
  141. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +6 -0
  142. package/schemas/plugins/{HashedModuleIdsPlugin.json → ids/HashedModuleIdsPlugin.json} +15 -2
  143. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -1
  144. package/types.d.ts +788 -127
  145. package/lib/dependencies/CssLocalIdentifierDependency.js +0 -252
  146. package/schemas/plugins/HashedModuleIdsPlugin.check.js +0 -6
@@ -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 (;;) {
@@ -28,6 +28,7 @@ const propertyAccess = require("./util/propertyAccess");
28
28
  const { register } = require("./util/serialization");
29
29
 
30
30
  /** @typedef {import("webpack-sources").Source} Source */
31
+ /** @typedef {import("../declarations/WebpackOptions").ExternalsType} ExternalsType */
31
32
  /** @typedef {import("../declarations/WebpackOptions").HashFunction} HashFunction */
32
33
  /** @typedef {import("./config/defaults").WebpackOptionsNormalizedWithDefaults} WebpackOptions */
33
34
  /** @typedef {import("./Chunk")} Chunk */
@@ -442,10 +443,6 @@ const getSourceForModuleExternal = (
442
443
  dependencyMeta,
443
444
  concatenationScope
444
445
  ) => {
445
- if (!Array.isArray(moduleAndSpecifiers)) {
446
- moduleAndSpecifiers = [moduleAndSpecifiers];
447
- }
448
-
449
446
  /** @type {Imported} */
450
447
  let imported = true;
451
448
  if (concatenationScope) {
@@ -465,6 +462,15 @@ const getSourceForModuleExternal = (
465
462
  }
466
463
  }
467
464
 
465
+ if (!Array.isArray(moduleAndSpecifiers)) {
466
+ moduleAndSpecifiers = [moduleAndSpecifiers];
467
+ }
468
+
469
+ // Return to `namespace` when the external request includes a specific export
470
+ if (moduleAndSpecifiers.length > 1) {
471
+ imported = true;
472
+ }
473
+
468
474
  const initFragment = new ModuleExternalInitFragment(
469
475
  moduleAndSpecifiers[0],
470
476
  imported,
@@ -473,22 +479,6 @@ const getSourceForModuleExternal = (
473
479
  runtimeTemplate.outputOptions.hashFunction
474
480
  );
475
481
  const normalizedImported = initFragment.getImported();
476
- const specifiers =
477
- normalizedImported === true
478
- ? undefined
479
- : /** @type {[string, string][]} */ (
480
- normalizedImported.map(([name, rawFinalName]) => {
481
- let finalName = rawFinalName;
482
- let counter = 0;
483
-
484
- if (concatenationScope) {
485
- while (!concatenationScope.registerUsedName(finalName)) {
486
- finalName = `${finalName}_${counter++}`;
487
- }
488
- }
489
- return [name, finalName];
490
- })
491
- );
492
482
 
493
483
  const baseAccess = `${initFragment.getNamespaceIdentifier()}${propertyAccess(
494
484
  moduleAndSpecifiers,
@@ -518,7 +508,7 @@ const getSourceForModuleExternal = (
518
508
  "x"
519
509
  )}`
520
510
  : undefined,
521
- specifiers,
511
+ specifiers: normalizedImported === true ? undefined : normalizedImported,
522
512
  runtimeRequirements: moduleRemapping
523
513
  ? RUNTIME_REQUIREMENTS_FOR_MODULE
524
514
  : undefined,
@@ -632,7 +622,7 @@ const getSourceForDefaultCase = (optional, request, runtimeTemplate) => {
632
622
  class ExternalModule extends Module {
633
623
  /**
634
624
  * @param {ExternalModuleRequest} request request
635
- * @param {string} type type
625
+ * @param {ExternalsType} type type
636
626
  * @param {string} userRequest user request
637
627
  * @param {DependencyMeta=} dependencyMeta dependency meta
638
628
  */
@@ -642,7 +632,7 @@ class ExternalModule extends Module {
642
632
  // Info from Factory
643
633
  /** @type {ExternalModuleRequest} */
644
634
  this.request = request;
645
- /** @type {string} */
635
+ /** @type {ExternalsType} */
646
636
  this.externalType = type;
647
637
  /** @type {string} */
648
638
  this.userRequest = userRequest;
@@ -821,6 +811,10 @@ class ExternalModule extends Module {
821
811
  return undefined;
822
812
  }
823
813
 
814
+ /**
815
+ * @private
816
+ * @returns {{ request: string | string[], externalType: ExternalsType }} the request and external type
817
+ */
824
818
  _getRequestAndExternalType() {
825
819
  let { request, externalType } = this;
826
820
  if (typeof request === "object" && !Array.isArray(request)) {
@@ -833,8 +827,8 @@ class ExternalModule extends Module {
833
827
  /**
834
828
  * Resolve the detailed external type from the raw external type.
835
829
  * e.g. resolve "module" or "import" from "module-import" type
836
- * @param {string} externalType raw external type
837
- * @returns {string} resolved external type
830
+ * @param {ExternalsType} externalType raw external type
831
+ * @returns {ExternalsType} resolved external type
838
832
  */
839
833
  _resolveExternalType(externalType) {
840
834
  if (externalType === "module-import") {
@@ -866,7 +860,7 @@ class ExternalModule extends Module {
866
860
  /**
867
861
  * @private
868
862
  * @param {string | string[]} request request
869
- * @param {string} externalType the external type
863
+ * @param {ExternalsType} externalType the external type
870
864
  * @param {RuntimeTemplate} runtimeTemplate the runtime template
871
865
  * @param {ModuleGraph} moduleGraph the module graph
872
866
  * @param {ChunkGraph} chunkGraph the chunk graph
@@ -959,8 +953,6 @@ class ExternalModule extends Module {
959
953
  }
960
954
  case "var":
961
955
  case "promise":
962
- case "const":
963
- case "let":
964
956
  case "assign":
965
957
  default:
966
958
  return getSourceForDefaultCase(