mirror of https://github.com/webpack/webpack.git
Compare commits
10 Commits
cdab7e1729
...
ec78a303e6
Author | SHA1 | Date |
---|---|---|
|
ec78a303e6 | |
|
4c30c3ee83 | |
|
cf1065c50c | |
|
c7fc38d76f | |
|
4cccfafaeb | |
|
29feac18a4 | |
|
e1afcd4cc2 | |
|
d45073a2b3 | |
|
568bb1d789 | |
|
11144e4eec |
|
@ -314,7 +314,9 @@
|
|||
"Kumar",
|
||||
"spacek",
|
||||
"thelarkinn",
|
||||
"behaviour"
|
||||
"behaviour",
|
||||
"WHATWG",
|
||||
"systemvars"
|
||||
],
|
||||
"ignoreRegExpList": [
|
||||
"/Author.+/",
|
||||
|
|
|
@ -47,6 +47,21 @@ export type DevServer =
|
|||
* A developer tool to enhance debugging (false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map).
|
||||
*/
|
||||
export type DevTool = (false | "eval") | string;
|
||||
/**
|
||||
* Enable and configure the Dotenv plugin to load environment variables from .env files.
|
||||
*/
|
||||
export type Dotenv =
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string[] | string;
|
||||
};
|
||||
/**
|
||||
* The entry point(s) of the compilation.
|
||||
*/
|
||||
|
@ -884,6 +899,10 @@ export interface WebpackOptions {
|
|||
* A developer tool to enhance debugging (false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map).
|
||||
*/
|
||||
devtool?: DevTool;
|
||||
/**
|
||||
* Enable and configure the Dotenv plugin to load environment variables from .env files.
|
||||
*/
|
||||
dotenv?: Dotenv;
|
||||
/**
|
||||
* The entry point(s) of the compilation.
|
||||
*/
|
||||
|
@ -3061,6 +3080,19 @@ export interface CssParserOptions {
|
|||
*/
|
||||
url?: CssParserUrl;
|
||||
}
|
||||
/**
|
||||
* Options for Dotenv plugin.
|
||||
*/
|
||||
export interface DotenvPluginOptions {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string[] | string;
|
||||
}
|
||||
/**
|
||||
* No generator options are supported for this module type.
|
||||
*/
|
||||
|
@ -3798,6 +3830,10 @@ export interface WebpackOptionsNormalized {
|
|||
* A developer tool to enhance debugging (false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map).
|
||||
*/
|
||||
devtool?: DevTool;
|
||||
/**
|
||||
* Enable and configure the Dotenv plugin to load environment variables from .env files.
|
||||
*/
|
||||
dotenv?: Dotenv;
|
||||
/**
|
||||
* The entry point(s) of the compilation.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This file was automatically generated.
|
||||
* DO NOT MODIFY BY HAND.
|
||||
* Run `yarn fix:special` to update
|
||||
*/
|
||||
|
||||
export interface DotenvPluginOptions {
|
||||
/**
|
||||
* Whether to allow empty strings in safe mode. If false, will throw an error if any env variables are empty (but only if safe mode is enabled).
|
||||
*/
|
||||
allowEmptyValues?: boolean;
|
||||
/**
|
||||
* Adds support for dotenv-defaults. If set to true, uses ./.env.defaults. If a string, uses that location for a defaults file.
|
||||
*/
|
||||
defaults?: boolean | string;
|
||||
/**
|
||||
* Allows your variables to be "expanded" for reusability within your .env file.
|
||||
*/
|
||||
expand?: boolean;
|
||||
/**
|
||||
* The path to your environment variables. This same path applies to the .env.example and .env.defaults files.
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* The prefix to use before the name of your env variables.
|
||||
*/
|
||||
prefix?: string;
|
||||
/**
|
||||
* If true, load '.env.example' to verify the '.env' variables are all set. Can also be a string to a different file.
|
||||
*/
|
||||
safe?: boolean | string;
|
||||
/**
|
||||
* Set to true if you would rather load all system variables as well (useful for CI purposes).
|
||||
*/
|
||||
systemvars?: boolean;
|
||||
}
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Natsu @xiaoxiaojx
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const createSchemaValidation = require("./util/create-schema-validation");
|
||||
const { join } = require("./util/fs");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").DotenvPluginOptions} DotenvPluginOptions */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
prefixes: "WEBPACK_",
|
||||
envDir: true
|
||||
};
|
||||
|
||||
// Regex for parsing .env files
|
||||
// ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L32
|
||||
const LINE =
|
||||
/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
|
||||
|
||||
const PLUGIN_NAME = "DotenvPlugin";
|
||||
|
||||
const validate = createSchemaValidation(
|
||||
undefined,
|
||||
() => {
|
||||
const { definitions } = require("../schemas/WebpackOptions.json");
|
||||
|
||||
return {
|
||||
definitions,
|
||||
oneOf: [{ $ref: "#/definitions/DotenvPluginOptions" }]
|
||||
};
|
||||
},
|
||||
{
|
||||
name: "Dotenv Plugin",
|
||||
baseDataPath: "options"
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Parse .env file content
|
||||
* ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L49
|
||||
* @param {string|Buffer} src the source content to parse
|
||||
* @returns {Record<string, string>} parsed environment variables object
|
||||
*/
|
||||
function parse(src) {
|
||||
const obj = /** @type {Record<string, string>} */ ({});
|
||||
|
||||
// Convert buffer to string
|
||||
let lines = src.toString();
|
||||
|
||||
// Convert line breaks to same format
|
||||
lines = lines.replace(/\r\n?/gm, "\n");
|
||||
|
||||
let match;
|
||||
while ((match = LINE.exec(lines)) !== null) {
|
||||
const key = match[1];
|
||||
|
||||
// Default undefined or null to empty string
|
||||
let value = match[2] || "";
|
||||
|
||||
// Remove whitespace
|
||||
value = value.trim();
|
||||
|
||||
// Check if double quoted
|
||||
const maybeQuote = value[0];
|
||||
|
||||
// Remove surrounding quotes
|
||||
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
|
||||
|
||||
// Expand newlines if double quoted
|
||||
if (maybeQuote === '"') {
|
||||
value = value.replace(/\\n/g, "\n");
|
||||
value = value.replace(/\\r/g, "\r");
|
||||
}
|
||||
|
||||
// Add to object
|
||||
obj[key] = value;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve escape sequences
|
||||
* ported from https://github.com/motdotla/dotenv-expand
|
||||
* @param {string} value value to resolve
|
||||
* @returns {string} resolved value
|
||||
*/
|
||||
function _resolveEscapeSequences(value) {
|
||||
return value.replace(/\\\$/g, "$");
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand environment variable value
|
||||
* ported from https://github.com/motdotla/dotenv-expand
|
||||
* @param {string} value value to expand
|
||||
* @param {Record<string, string | undefined>} processEnv process.env object
|
||||
* @param {Record<string, string>} runningParsed running parsed object
|
||||
* @returns {string} expanded value
|
||||
*/
|
||||
function expandValue(value, processEnv, runningParsed) {
|
||||
const env = { ...runningParsed, ...processEnv }; // process.env wins
|
||||
|
||||
const regex = /(?<!\\)\$\{([^{}]+)\}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
||||
|
||||
let result = value;
|
||||
let match;
|
||||
const seen = new Set(); // self-referential checker
|
||||
|
||||
while ((match = regex.exec(result)) !== null) {
|
||||
seen.add(result);
|
||||
|
||||
const [template, bracedExpression, unbracedExpression] = match;
|
||||
const expression = bracedExpression || unbracedExpression;
|
||||
|
||||
// match the operators `:+`, `+`, `:-`, and `-`
|
||||
const opRegex = /(:\+|\+|:-|-)/;
|
||||
// find first match
|
||||
const opMatch = expression.match(opRegex);
|
||||
const splitter = opMatch ? opMatch[0] : null;
|
||||
|
||||
const r = expression.split(/** @type {string} */ (splitter));
|
||||
// const r = splitter ? expression.split(splitter) : [expression];
|
||||
|
||||
let defaultValue;
|
||||
let value;
|
||||
|
||||
const key = r.shift();
|
||||
|
||||
if ([":+", "+"].includes(splitter || "")) {
|
||||
defaultValue = env[key || ""] ? r.join(splitter || "") : "";
|
||||
value = null;
|
||||
} else {
|
||||
defaultValue = r.join(splitter || "");
|
||||
value = env[key || ""];
|
||||
}
|
||||
|
||||
if (value) {
|
||||
// self-referential check
|
||||
result = seen.has(value)
|
||||
? result.replace(template, defaultValue)
|
||||
: result.replace(template, value);
|
||||
} else {
|
||||
result = result.replace(template, defaultValue);
|
||||
}
|
||||
|
||||
// if the result equaled what was in process.env and runningParsed then stop expanding
|
||||
if (result === runningParsed[key || ""]) {
|
||||
break;
|
||||
}
|
||||
|
||||
regex.lastIndex = 0; // reset regex search position to re-evaluate after each replacement
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand environment variables in parsed object
|
||||
* ported from https://github.com/motdotla/dotenv-expand
|
||||
* @param {{ parsed: Record<string, string>, processEnv?: Record<string, string | undefined> }} options expand options
|
||||
* @returns {{ parsed: Record<string, string> }} expanded options
|
||||
*/
|
||||
function expand(options) {
|
||||
// for use with progressive expansion
|
||||
const runningParsed = /** @type {Record<string, string>} */ ({});
|
||||
|
||||
let processEnv = process.env;
|
||||
if (
|
||||
options &&
|
||||
options.processEnv !== null &&
|
||||
options.processEnv !== undefined
|
||||
) {
|
||||
processEnv = options.processEnv;
|
||||
}
|
||||
|
||||
// dotenv.config() ran before this so the assumption is process.env has already been set
|
||||
for (const key in options.parsed) {
|
||||
let value = options.parsed[key];
|
||||
|
||||
// short-circuit scenario: process.env was already set prior to the file value
|
||||
value =
|
||||
processEnv[key] && processEnv[key] !== value
|
||||
? /** @type {string} */ (processEnv[key])
|
||||
: expandValue(value, processEnv, runningParsed);
|
||||
|
||||
options.parsed[key] = _resolveEscapeSequences(value);
|
||||
|
||||
// for use with progressive expansion
|
||||
runningParsed[key] = _resolveEscapeSequences(value);
|
||||
}
|
||||
|
||||
for (const processKey in options.parsed) {
|
||||
if (processEnv) {
|
||||
processEnv[processKey] = options.parsed[processKey];
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve and validate env prefixes
|
||||
* Similar to Vite's resolveEnvPrefix
|
||||
* @param {string | string[] | undefined} rawPrefixes raw prefixes option
|
||||
* @returns {string[]} normalized prefixes array
|
||||
*/
|
||||
const resolveEnvPrefix = (rawPrefixes) => {
|
||||
const prefixes = Array.isArray(rawPrefixes)
|
||||
? rawPrefixes
|
||||
: [rawPrefixes || "WEBPACK_"];
|
||||
|
||||
// Check for empty prefix (security issue like Vite does)
|
||||
if (prefixes.includes("")) {
|
||||
throw new Error(
|
||||
"prefixes option contains value '', which could lead to unexpected exposure of sensitive information."
|
||||
);
|
||||
}
|
||||
|
||||
return prefixes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get list of env files to load based on mode
|
||||
* Similar to Vite's getEnvFilesForMode
|
||||
* @param {InputFileSystem} inputFileSystem the input file system
|
||||
* @param {string} envDir the directory containing .env files
|
||||
* @param {string | undefined} mode the mode (e.g., 'production', 'development')
|
||||
* @returns {string[]} array of file paths to load
|
||||
*/
|
||||
const getEnvFilesForMode = (inputFileSystem, envDir, mode) => {
|
||||
if (envDir) {
|
||||
return [
|
||||
/** default file */ ".env",
|
||||
/** local file */ ".env.local",
|
||||
/** mode file */ `.env.${mode}`,
|
||||
/** mode local file */ `.env.${mode}.local`
|
||||
].map((file) => join(inputFileSystem, envDir, file));
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Format environment variables as DefinePlugin definitions
|
||||
* @param {Record<string, string>} env environment variables
|
||||
* @returns {Record<string, string>} formatted definitions
|
||||
*/
|
||||
const formatDefinitions = (env) => {
|
||||
const definitions = /** @type {Record<string, string>} */ ({});
|
||||
|
||||
for (const [key, value] of Object.entries(env)) {
|
||||
// Always use process.env. prefix for DefinePlugin
|
||||
definitions[`process.env.${key}`] = JSON.stringify(value);
|
||||
}
|
||||
|
||||
return definitions;
|
||||
};
|
||||
|
||||
class DotenvPlugin {
|
||||
/**
|
||||
* @param {DotenvPluginOptions=} options options object
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
validate(options);
|
||||
this.config = { ...DEFAULT_OPTIONS, ...options };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
/** @type {string[] | undefined} */
|
||||
let fileDependenciesCache;
|
||||
|
||||
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, (_params, callback) => {
|
||||
const inputFileSystem = /** @type {InputFileSystem} */ (
|
||||
compiler.inputFileSystem
|
||||
);
|
||||
const context = compiler.context;
|
||||
// Use webpack mode or fallback to NODE_ENV
|
||||
const mode = /** @type {string | undefined} */ (
|
||||
compiler.options.mode || process.env.NODE_ENV
|
||||
);
|
||||
|
||||
this.loadEnv(
|
||||
inputFileSystem,
|
||||
mode,
|
||||
context,
|
||||
(err, env, fileDependencies) => {
|
||||
if (err) return callback(err);
|
||||
|
||||
const definitions = formatDefinitions(env || {});
|
||||
const DefinePlugin = compiler.webpack.DefinePlugin;
|
||||
|
||||
new DefinePlugin(definitions).apply(compiler);
|
||||
fileDependenciesCache = fileDependencies;
|
||||
|
||||
callback();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
||||
compilation.fileDependencies.addAll(fileDependenciesCache || []);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load environment variables from .env files
|
||||
* Similar to Vite's loadEnv implementation
|
||||
* @param {InputFileSystem} fs the input file system
|
||||
* @param {string | undefined} mode the mode
|
||||
* @param {string} context the compiler context
|
||||
* @param {(err: Error | null, env?: Record<string, string>, fileDependencies?: string[]) => void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
loadEnv(fs, mode, context, callback) {
|
||||
const { envDir: rawEnvDir, prefixes: rawPrefixes } =
|
||||
/** @type {DotenvPluginOptions} */ (this.config);
|
||||
|
||||
let prefixes;
|
||||
try {
|
||||
prefixes = resolveEnvPrefix(rawPrefixes);
|
||||
} catch (err) {
|
||||
return callback(/** @type {Error} */ (err));
|
||||
}
|
||||
|
||||
const getEnvDir = () => {
|
||||
if (typeof rawEnvDir === "string") {
|
||||
return join(fs, context, rawEnvDir);
|
||||
}
|
||||
if (rawEnvDir === true) {
|
||||
return context;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const envDir = getEnvDir();
|
||||
|
||||
// Get env files to load
|
||||
const envFiles = getEnvFilesForMode(fs, envDir, mode);
|
||||
/** @type {string[]} */
|
||||
const fileDependencies = [];
|
||||
|
||||
// Read all files
|
||||
const readPromises = envFiles.map((filePath) =>
|
||||
this.loadFile(fs, filePath).then(
|
||||
(content) => {
|
||||
fileDependencies.push(filePath);
|
||||
return { content, filePath };
|
||||
},
|
||||
() =>
|
||||
// File doesn't exist, skip it (this is normal)
|
||||
({ content: "", filePath })
|
||||
)
|
||||
);
|
||||
|
||||
Promise.all(readPromises)
|
||||
.then((results) => {
|
||||
// Parse all files and merge (later files override earlier ones)
|
||||
// Similar to Vite's implementation
|
||||
const parsed = /** @type {Record<string, string>} */ ({});
|
||||
for (const { content } of results) {
|
||||
if (!content) continue;
|
||||
const entries = parse(content);
|
||||
for (const key in entries) {
|
||||
parsed[key] = entries[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Always expand environment variables (like Vite does)
|
||||
// Make a copy of process.env so that dotenv-expand doesn't modify global process.env
|
||||
const processEnv = { ...process.env };
|
||||
expand({ parsed, processEnv });
|
||||
|
||||
// Filter by prefixes and prioritize process.env (like Vite)
|
||||
const env = /** @type {Record<string, string>} */ ({});
|
||||
|
||||
// First, add filtered vars from parsed .env files
|
||||
for (const [key, value] of Object.entries(parsed)) {
|
||||
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
||||
env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Then, prioritize actual env variables starting with prefixes
|
||||
// These are typically provided inline and should be prioritized (like Vite)
|
||||
for (const key in process.env) {
|
||||
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
||||
env[key] = /** @type {string} */ (process.env[key]);
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, env, fileDependencies);
|
||||
})
|
||||
.catch((err) => {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a file with proper path resolution
|
||||
* @param {InputFileSystem} fs the input file system
|
||||
* @param {string} file the file to load
|
||||
* @returns {Promise<string>} the content of the file
|
||||
*/
|
||||
loadFile(fs, file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(file, "utf8", (err, content) => {
|
||||
if (err) reject(err);
|
||||
else resolve(content || "");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DotenvPlugin;
|
|
@ -114,6 +114,7 @@ const {
|
|||
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_INLINE} ASSET_MODULE_TYPE_INLINE */
|
||||
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_RESOURCE} ASSET_MODULE_TYPE_RESOURCE */
|
||||
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_SOURCE} ASSET_MODULE_TYPE_SOURCE */
|
||||
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_BYTES} ASSET_MODULE_TYPE_BYTES */
|
||||
/** @typedef {import("./ModuleTypeConstants").WEBASSEMBLY_MODULE_TYPE_ASYNC} WEBASSEMBLY_MODULE_TYPE_ASYNC */
|
||||
/** @typedef {import("./ModuleTypeConstants").WEBASSEMBLY_MODULE_TYPE_SYNC} WEBASSEMBLY_MODULE_TYPE_SYNC */
|
||||
/** @typedef {import("./ModuleTypeConstants").CSS_MODULE_TYPE} CSS_MODULE_TYPE */
|
||||
|
@ -268,6 +269,76 @@ const ruleSetCompiler = new RuleSetCompiler([
|
|||
new UseEffectRulePlugin()
|
||||
]);
|
||||
|
||||
/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
|
||||
/** @typedef {import("../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
|
||||
/** @typedef {import("./javascript/JavascriptGenerator")} JavascriptGenerator */
|
||||
/** @typedef {import("../declarations/WebpackOptions").EmptyGeneratorOptions} EmptyGeneratorOptions */
|
||||
|
||||
/** @typedef {import("./json/JsonParser")} JsonParser */
|
||||
/** @typedef {import("../declarations/WebpackOptions").JsonParserOptions} JsonParserOptions */
|
||||
/** @typedef {import("./json/JsonGenerator")} JsonGenerator */
|
||||
/** @typedef {import("../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
|
||||
|
||||
/** @typedef {import("./asset/AssetParser")} AssetParser */
|
||||
/** @typedef {import("./asset/AssetSourceParser")} AssetSourceParser */
|
||||
/** @typedef {import("./asset/AssetBytesParser")} AssetBytesParser */
|
||||
/** @typedef {import("../declarations/WebpackOptions").AssetParserOptions} AssetParserOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").EmptyParserOptions} EmptyParserOptions */
|
||||
/** @typedef {import("./asset/AssetGenerator")} AssetGenerator */
|
||||
/** @typedef {import("../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").AssetInlineGeneratorOptions} AssetInlineGeneratorOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").AssetResourceGeneratorOptions} AssetResourceGeneratorOptions */
|
||||
/** @typedef {import("./asset/AssetSourceGenerator")} AssetSourceGenerator */
|
||||
/** @typedef {import("./asset/AssetBytesGenerator")} AssetBytesGenerator */
|
||||
|
||||
/** @typedef {import("./wasm-async/AsyncWebAssemblyParser")} AsyncWebAssemblyParser */
|
||||
/** @typedef {import("./wasm-sync/WebAssemblyParser")} WebAssemblyParser */
|
||||
|
||||
/** @typedef {import("./css/CssParser")} CssParser */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssParserOptions} CssParserOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssAutoParserOptions} CssAutoParserOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssGlobalParserOptions} CssGlobalParserOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssModuleParserOptions} CssModuleParserOptions */
|
||||
/** @typedef {import("./css/CssGenerator")} CssGenerator */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssGeneratorOptions} CssGeneratorOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssGlobalGeneratorOptions} CssGlobalGeneratorOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssModuleGeneratorOptions} CssModuleGeneratorOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").CssAutoGeneratorOptions} CssAutoGeneratorOptions */
|
||||
|
||||
/**
|
||||
* @typedef {[
|
||||
* [JAVASCRIPT_MODULE_TYPE_AUTO, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
||||
* [JAVASCRIPT_MODULE_TYPE_DYNAMIC, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
||||
* [JAVASCRIPT_MODULE_TYPE_ESM, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
||||
* [JSON_MODULE_TYPE, JsonParser, JsonParserOptions, JsonGenerator, JsonGeneratorOptions],
|
||||
* [ASSET_MODULE_TYPE, AssetParser, AssetParserOptions, AssetGenerator, AssetGeneratorOptions],
|
||||
* [ASSET_MODULE_TYPE_INLINE, AssetParser, EmptyParserOptions, AssetGenerator, AssetGeneratorOptions],
|
||||
* [ASSET_MODULE_TYPE_RESOURCE, AssetParser, EmptyParserOptions, AssetGenerator, AssetGeneratorOptions],
|
||||
* [ASSET_MODULE_TYPE_SOURCE, AssetSourceParser, EmptyParserOptions, AssetSourceGenerator, EmptyGeneratorOptions],
|
||||
* [ASSET_MODULE_TYPE_BYTES, AssetBytesParser, EmptyParserOptions, AssetBytesGenerator, EmptyGeneratorOptions],
|
||||
* [WEBASSEMBLY_MODULE_TYPE_ASYNC, AsyncWebAssemblyParser, EmptyParserOptions, Generator, EmptyParserOptions],
|
||||
* [WEBASSEMBLY_MODULE_TYPE_SYNC, WebAssemblyParser, EmptyParserOptions, Generator, EmptyParserOptions],
|
||||
* [CSS_MODULE_TYPE, CssParser, CssParserOptions, CssGenerator, CssGeneratorOptions],
|
||||
* [CSS_MODULE_TYPE_AUTO, CssParser, CssAutoParserOptions, CssGenerator, CssAutoGeneratorOptions],
|
||||
* [CSS_MODULE_TYPE_MODULE, CssParser, CssModuleParserOptions, CssGenerator, CssModuleGeneratorOptions],
|
||||
* [CSS_MODULE_TYPE_GLOBAL, CssParser, CssGlobalParserOptions, CssGenerator, CssGlobalGeneratorOptions],
|
||||
* [string, Parser, ParserOptions, Generator, GeneratorOptions],
|
||||
* ]} ParsersAndGeneratorsByTypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {unknown[]} T
|
||||
* @template {number[]} I
|
||||
* @typedef {{ [K in keyof I]: K extends keyof I ? I[K] extends keyof T ? T[I[K]] : never : never }} ExtractTupleElements
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {unknown[]} T
|
||||
* @template {number[]} A
|
||||
* @template [R=void]
|
||||
* @typedef {T extends [infer Head extends [string, ...unknown[]], ...infer Tail extends [string, ...unknown[]][]] ? Record<Head[0], SyncBailHook<ExtractTupleElements<Head, A>, R extends number ? Head[R] : R>> & RecordFactoryFromTuple<Tail, A, R> : unknown } RecordFactoryFromTuple
|
||||
*/
|
||||
|
||||
class NormalModuleFactory extends ModuleFactory {
|
||||
/**
|
||||
* @param {object} param params
|
||||
|
@ -306,15 +377,15 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
|
||||
/** @type {SyncWaterfallHook<[Module, CreateData, ResolveData]>} */
|
||||
module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
|
||||
/** @type {HookMap<SyncBailHook<[ParserOptions], Parser | void>>} */
|
||||
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [2], 1>>} */
|
||||
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
|
||||
/** @type {HookMap<SyncBailHook<[EXPECTED_ANY, ParserOptions], void>>} */
|
||||
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [1, 2]>>} */
|
||||
parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])),
|
||||
/** @type {HookMap<SyncBailHook<[GeneratorOptions], Generator | void>>} */
|
||||
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [4], 3>>} */
|
||||
createGenerator: new HookMap(
|
||||
() => new SyncBailHook(["generatorOptions"])
|
||||
),
|
||||
/** @type {HookMap<SyncBailHook<[EXPECTED_ANY, GeneratorOptions], void>>} */
|
||||
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [3, 4]>>} */
|
||||
generator: new HookMap(
|
||||
() => new SyncHook(["generator", "generatorOptions"])
|
||||
),
|
||||
|
|
|
@ -294,6 +294,14 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.dotenv) {
|
||||
const DotenvPlugin = require("./DotenvPlugin");
|
||||
|
||||
new DotenvPlugin(
|
||||
typeof options.dotenv === "boolean" ? {} : options.dotenv
|
||||
).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.devtool) {
|
||||
if (options.devtool.includes("source-map")) {
|
||||
const hidden = options.devtool.includes("hidden");
|
||||
|
|
|
@ -91,28 +91,6 @@ const resolve = (browsers) => {
|
|||
const anyBrowser = browsers.some((b) => /^(?!node)/.test(b));
|
||||
const browserProperty = !anyBrowser ? false : anyNode ? null : true;
|
||||
const nodeProperty = !anyNode ? false : anyBrowser ? null : true;
|
||||
// Internet Explorer Mobile, Blackberry browser and Opera Mini are very old browsers, they do not support new features
|
||||
const es6DynamicImport = rawChecker({
|
||||
/* eslint-disable camelcase */
|
||||
chrome: 63,
|
||||
and_chr: 63,
|
||||
edge: 79,
|
||||
firefox: 67,
|
||||
and_ff: 67,
|
||||
// ie: Not supported
|
||||
opera: 50,
|
||||
op_mob: 46,
|
||||
safari: [11, 1],
|
||||
ios_saf: [11, 3],
|
||||
samsung: [8, 2],
|
||||
android: 63,
|
||||
and_qq: [10, 4],
|
||||
baidu: [13, 18],
|
||||
and_uc: [15, 5],
|
||||
kaios: [3, 0],
|
||||
node: [12, 17]
|
||||
/* eslint-enable camelcase */
|
||||
});
|
||||
|
||||
return {
|
||||
/* eslint-disable camelcase */
|
||||
|
@ -175,9 +153,9 @@ const resolve = (browsers) => {
|
|||
ios_saf: 7,
|
||||
samsung: [3, 0],
|
||||
android: 38,
|
||||
// and_qq: Unknown support
|
||||
and_qq: [10, 4],
|
||||
// baidu: Unknown support
|
||||
// and_uc: Unknown support
|
||||
and_uc: [12, 12],
|
||||
kaios: [3, 0],
|
||||
node: [0, 12]
|
||||
}),
|
||||
|
@ -194,9 +172,9 @@ const resolve = (browsers) => {
|
|||
ios_saf: 8,
|
||||
samsung: [5, 0],
|
||||
android: 49,
|
||||
// and_qq: Unknown support
|
||||
and_qq: [10, 4],
|
||||
// baidu: Unknown support
|
||||
// and_uc: Unknown support
|
||||
and_uc: [12, 12],
|
||||
kaios: [2, 5],
|
||||
node: [6, 0]
|
||||
}),
|
||||
|
@ -240,8 +218,44 @@ const resolve = (browsers) => {
|
|||
kaios: [3, 0],
|
||||
node: [12, 17]
|
||||
}),
|
||||
dynamicImport: es6DynamicImport,
|
||||
dynamicImportInWorker: es6DynamicImport && !anyNode,
|
||||
dynamicImport: rawChecker({
|
||||
chrome: 63,
|
||||
and_chr: 63,
|
||||
edge: 79,
|
||||
firefox: 67,
|
||||
and_ff: 67,
|
||||
// ie: Not supported
|
||||
opera: 50,
|
||||
op_mob: 46,
|
||||
safari: [11, 1],
|
||||
ios_saf: [11, 3],
|
||||
samsung: [8, 2],
|
||||
android: 63,
|
||||
and_qq: [10, 4],
|
||||
baidu: [13, 18],
|
||||
and_uc: [15, 5],
|
||||
kaios: [3, 0],
|
||||
node: [12, 17]
|
||||
}),
|
||||
dynamicImportInWorker: rawChecker({
|
||||
chrome: 80,
|
||||
and_chr: 80,
|
||||
edge: 80,
|
||||
firefox: 114,
|
||||
and_ff: 114,
|
||||
// ie: Not supported
|
||||
opera: 67,
|
||||
op_mob: 57,
|
||||
safari: [15, 0],
|
||||
ios_saf: [15, 0],
|
||||
samsung: [13, 0],
|
||||
android: 80,
|
||||
and_qq: [10, 4],
|
||||
baidu: [13, 18],
|
||||
and_uc: [15, 5],
|
||||
kaios: [3, 0],
|
||||
node: [12, 17]
|
||||
}),
|
||||
// browserslist does not have info about globalThis
|
||||
// so this is based on mdn-browser-compat-data
|
||||
globalThis: rawChecker({
|
||||
|
@ -257,9 +271,9 @@ const resolve = (browsers) => {
|
|||
ios_saf: [12, 2],
|
||||
samsung: [10, 1],
|
||||
android: 71,
|
||||
// and_qq: Unknown support
|
||||
and_qq: [13, 1],
|
||||
// baidu: Unknown support
|
||||
// and_uc: Unknown support
|
||||
and_uc: [15, 5],
|
||||
kaios: [3, 0],
|
||||
node: 12
|
||||
}),
|
||||
|
@ -276,9 +290,9 @@ const resolve = (browsers) => {
|
|||
ios_saf: [13, 4],
|
||||
samsung: 13,
|
||||
android: 80,
|
||||
// and_qq: Not supported
|
||||
and_qq: [13, 1],
|
||||
// baidu: Not supported
|
||||
// and_uc: Not supported
|
||||
and_uc: [15, 5],
|
||||
kaios: [3, 0],
|
||||
node: 14
|
||||
}),
|
||||
|
@ -314,9 +328,9 @@ const resolve = (browsers) => {
|
|||
ios_saf: 11,
|
||||
samsung: [6, 2],
|
||||
android: 55,
|
||||
and_qq: [13, 1],
|
||||
and_qq: [10, 4],
|
||||
baidu: [13, 18],
|
||||
and_uc: [15, 5],
|
||||
and_uc: [12, 12],
|
||||
kaios: 3,
|
||||
node: [7, 6]
|
||||
}),
|
||||
|
@ -332,7 +346,7 @@ const resolve = (browsers) => {
|
|||
fetchWasm: browserProperty,
|
||||
global: nodeProperty,
|
||||
importScripts: false,
|
||||
importScriptsInWorker: true,
|
||||
importScriptsInWorker: Boolean(browserProperty),
|
||||
nodeBuiltins: nodeProperty,
|
||||
nodePrefixForCoreModules:
|
||||
nodeProperty &&
|
||||
|
|
|
@ -202,6 +202,7 @@ const {
|
|||
* & { performance: NonNullable<WebpackOptionsNormalized["performance"]> }
|
||||
* & { recordsInputPath: NonNullable<WebpackOptionsNormalized["recordsInputPath"]> }
|
||||
* & { recordsOutputPath: NonNullable<WebpackOptionsNormalized["recordsOutputPath"]>
|
||||
* & { dotenv: NonNullable<WebpackOptionsNormalized["dotenv"]> }
|
||||
* }} WebpackOptionsNormalizedWithDefaults
|
||||
*/
|
||||
|
||||
|
|
|
@ -178,6 +178,9 @@ const getNormalizedWebpackOptions = (config) => ({
|
|||
return { ...devServer };
|
||||
}),
|
||||
devtool: config.devtool,
|
||||
dotenv: optionalNestedConfig(config.dotenv, (dotenv) =>
|
||||
dotenv === true ? {} : dotenv
|
||||
),
|
||||
entry:
|
||||
config.entry === undefined
|
||||
? { main: {} }
|
||||
|
|
|
@ -232,6 +232,9 @@ module.exports = mergeExports(fn, {
|
|||
get DynamicEntryPlugin() {
|
||||
return require("./DynamicEntryPlugin");
|
||||
},
|
||||
get DotenvPlugin() {
|
||||
return require("./DotenvPlugin");
|
||||
},
|
||||
get EntryOptionPlugin() {
|
||||
return require("./EntryOptionPlugin");
|
||||
},
|
||||
|
|
|
@ -106,7 +106,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|||
/** @typedef {Set<DestructuringAssignmentProperty>} DestructuringAssignmentProperties */
|
||||
|
||||
// TODO remove cast when @types/estree has been updated to import assertions
|
||||
/** @typedef {import("estree").ImportExpression & { options?: Expression | null, phase?: "defer" }} ImportExpression */
|
||||
/** @typedef {import("estree").ImportExpression & { phase?: "defer" }} ImportExpression */
|
||||
|
||||
/** @type {string[]} */
|
||||
const EMPTY_ARRAY = [];
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
const memoize = require("./memoize");
|
||||
|
||||
/** @typedef {import("schema-utils").Schema} Schema */
|
||||
/** @typedef {import("schema-utils/declarations/validate").ValidationErrorConfiguration} ValidationErrorConfiguration */
|
||||
/** @typedef {import("schema-utils").ValidationErrorConfiguration} ValidationErrorConfiguration */
|
||||
|
||||
const getValidate = memoize(() => require("schema-utils").validate);
|
||||
|
||||
|
|
|
@ -26,15 +26,6 @@ const decoderOpts = {
|
|||
};
|
||||
|
||||
class WebAssemblyParser extends Parser {
|
||||
/**
|
||||
* @param {{}=} options parser options
|
||||
*/
|
||||
constructor(options) {
|
||||
super();
|
||||
this.hooks = Object.freeze({});
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | Buffer | PreparsedAst} source the source to parse
|
||||
* @param {ParserState} state the parser state
|
||||
|
|
|
@ -63,15 +63,6 @@ const decoderOpts = {
|
|||
};
|
||||
|
||||
class WebAssemblyParser extends Parser {
|
||||
/**
|
||||
* @param {{}=} options parser options
|
||||
*/
|
||||
constructor(options) {
|
||||
super();
|
||||
this.hooks = Object.freeze({});
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | Buffer | PreparsedAst} source the source to parse
|
||||
* @param {ParserState} state the parser state
|
||||
|
|
|
@ -69,7 +69,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
if (options && options.baseUri) {
|
||||
return `${RuntimeGlobals.baseURI} = ${JSON.stringify(options.baseUri)};`;
|
||||
}
|
||||
return `${RuntimeGlobals.baseURI} = (document && document.baseURI) || self.location.href;`;
|
||||
return `${RuntimeGlobals.baseURI} = (typeof document !== 'undefined' && document.baseURI) || self.location.href;`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -101,8 +101,8 @@
|
|||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^4.3.2",
|
||||
"tapable": "^2.2.3",
|
||||
"schema-utils": "^4.3.3",
|
||||
"tapable": "^2.3.0",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"watchpack": "^2.4.4",
|
||||
"webpack-sources": "^3.3.3"
|
||||
|
@ -184,7 +184,7 @@
|
|||
"toml": "^3.0.0",
|
||||
"tooling": "webpack/tooling#v1.24.3",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.9.2",
|
||||
"typescript": "^5.9.3",
|
||||
"url-loader": "^4.1.0",
|
||||
"wast-loader": "^1.12.1",
|
||||
"webassembly-feature": "1.3.0",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -629,6 +629,50 @@
|
|||
"description": "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.",
|
||||
"type": "string"
|
||||
},
|
||||
"Dotenv": {
|
||||
"description": "Enable and configure the Dotenv plugin to load environment variables from .env files.",
|
||||
"cli": {
|
||||
"exclude": false
|
||||
},
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Enable Dotenv plugin with default options.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/DotenvPluginOptions",
|
||||
"description": "Options for Dotenv plugin."
|
||||
}
|
||||
]
|
||||
},
|
||||
"DotenvPluginOptions": {
|
||||
"description": "Options for Dotenv plugin.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"envDir": {
|
||||
"description": "The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"prefixes": {
|
||||
"description": "Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"EmptyGeneratorOptions": {
|
||||
"description": "No generator options are supported for this module type.",
|
||||
"type": "object",
|
||||
|
@ -5800,6 +5844,9 @@
|
|||
"devtool": {
|
||||
"$ref": "#/definitions/DevTool"
|
||||
},
|
||||
"dotenv": {
|
||||
"$ref": "#/definitions/Dotenv"
|
||||
},
|
||||
"entry": {
|
||||
"$ref": "#/definitions/EntryNormalized"
|
||||
},
|
||||
|
@ -5950,6 +5997,9 @@
|
|||
"devtool": {
|
||||
"$ref": "#/definitions/DevTool"
|
||||
},
|
||||
"dotenv": {
|
||||
"$ref": "#/definitions/Dotenv"
|
||||
},
|
||||
"entry": {
|
||||
"$ref": "#/definitions/Entry"
|
||||
},
|
||||
|
|
|
@ -2909,12 +2909,6 @@ describe("Targets", () => {
|
|||
- Expected
|
||||
+ Received
|
||||
|
||||
@@ ... @@
|
||||
- "dynamicImportInWorker": true,
|
||||
+ "dynamicImportInWorker": false,
|
||||
@@ ... @@
|
||||
- "dynamicImportInWorker": true,
|
||||
+ "dynamicImportInWorker": false,
|
||||
@@ ... @@
|
||||
- "target": "node12.17",
|
||||
+ "target": "browserslist: node 12.17",
|
||||
|
|
|
@ -465,6 +465,58 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"dotenv": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Enable Dotenv plugin with default options.",
|
||||
"multiple": false,
|
||||
"path": "dotenv",
|
||||
"type": "boolean",
|
||||
},
|
||||
],
|
||||
"description": "Enable Dotenv plugin with default options.",
|
||||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"dotenv-env-dir": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.",
|
||||
"multiple": false,
|
||||
"path": "dotenv.envDir",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"description": "The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.",
|
||||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"dotenv-prefixes": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.",
|
||||
"multiple": true,
|
||||
"path": "dotenv.prefixes[]",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"description": "Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.",
|
||||
"multiple": true,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"dotenv-prefixes-reset": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Clear all items provided in 'dotenv.prefixes' configuration. Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.",
|
||||
"multiple": false,
|
||||
"path": "dotenv.prefixes",
|
||||
"type": "reset",
|
||||
},
|
||||
],
|
||||
"description": "Clear all items provided in 'dotenv.prefixes' configuration. Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.",
|
||||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"entry": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
|
|
@ -31,6 +31,37 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["and_chr 140","and_ff 142","and_qq 14.9","and_uc 15.5","android 140","chrome 140","chrome 139","chrome 138","chrome 137","chrome 112","chrome 109","chrome 105","edge 140","edge 139","edge 138","firefox 143","firefox 142","firefox 141","firefox 140","ios_saf 26.0","ios_saf 18.5-18.6","kaios 3.0-3.1","node 24.8.0","node 22.19.0","node 20.19.0","op_mob 80","opera 122","opera 121","opera 120","safari 26.0","safari 18.5-18.6","samsung 28","samsung 27"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
"asyncFunction": true,
|
||||
"bigIntLiteral": true,
|
||||
"browser": null,
|
||||
"const": true,
|
||||
"destructuring": true,
|
||||
"document": null,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": null,
|
||||
"forOf": true,
|
||||
"global": null,
|
||||
"globalThis": true,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": false,
|
||||
"module": true,
|
||||
"node": null,
|
||||
"nodeBuiltins": null,
|
||||
"nodePrefixForCoreModules": null,
|
||||
"nwjs": false,
|
||||
"optionalChaining": true,
|
||||
"require": null,
|
||||
"templateLiteral": true,
|
||||
"web": null,
|
||||
"webworker": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["and_ff 68"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
|
@ -41,7 +72,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -65,17 +96,17 @@ Object {
|
|||
exports[`browserslist target ["and_qq 10.4"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
"asyncFunction": false,
|
||||
"asyncFunction": true,
|
||||
"bigIntLiteral": false,
|
||||
"browser": true,
|
||||
"const": true,
|
||||
"destructuring": false,
|
||||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": false,
|
||||
"forOf": true,
|
||||
"global": false,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
|
@ -93,37 +124,6 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["and_uc 12.12"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
"asyncFunction": false,
|
||||
"bigIntLiteral": false,
|
||||
"browser": true,
|
||||
"const": true,
|
||||
"destructuring": false,
|
||||
"document": true,
|
||||
"dynamicImport": false,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": false,
|
||||
"global": false,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"module": false,
|
||||
"node": false,
|
||||
"nodeBuiltins": false,
|
||||
"nodePrefixForCoreModules": false,
|
||||
"nwjs": false,
|
||||
"optionalChaining": false,
|
||||
"require": false,
|
||||
"templateLiteral": true,
|
||||
"web": true,
|
||||
"webworker": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["android 4"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": false,
|
||||
|
@ -320,14 +320,45 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": null,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": null,
|
||||
"forOf": true,
|
||||
"global": null,
|
||||
"globalThis": true,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": true,
|
||||
"node": null,
|
||||
"nodeBuiltins": null,
|
||||
"nodePrefixForCoreModules": null,
|
||||
"nwjs": false,
|
||||
"optionalChaining": false,
|
||||
"require": null,
|
||||
"templateLiteral": true,
|
||||
"web": null,
|
||||
"webworker": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["chrome 80","node 13.12.0"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
"asyncFunction": true,
|
||||
"bigIntLiteral": true,
|
||||
"browser": null,
|
||||
"const": true,
|
||||
"destructuring": true,
|
||||
"document": null,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": null,
|
||||
"forOf": true,
|
||||
"global": null,
|
||||
"globalThis": true,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": false,
|
||||
"module": true,
|
||||
"node": null,
|
||||
"nodeBuiltins": null,
|
||||
|
@ -382,7 +413,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -413,7 +444,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -444,7 +475,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -537,7 +568,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -606,7 +637,7 @@ Object {
|
|||
"global": true,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": false,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
|
@ -637,7 +668,7 @@ Object {
|
|||
"global": true,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": false,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
|
@ -668,7 +699,7 @@ Object {
|
|||
"global": true,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": false,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
|
@ -699,7 +730,7 @@ Object {
|
|||
"global": true,
|
||||
"globalThis": false,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": false,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
|
@ -723,14 +754,45 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": false,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": false,
|
||||
"forOf": true,
|
||||
"global": true,
|
||||
"globalThis": true,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": true,
|
||||
"importScriptsInWorker": false,
|
||||
"module": true,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
"nodePrefixForCoreModules": false,
|
||||
"nwjs": false,
|
||||
"optionalChaining": false,
|
||||
"require": true,
|
||||
"templateLiteral": true,
|
||||
"web": false,
|
||||
"webworker": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`browserslist target ["node 13.12.0"] 1`] = `
|
||||
Object {
|
||||
"arrowFunction": true,
|
||||
"asyncFunction": true,
|
||||
"bigIntLiteral": true,
|
||||
"browser": false,
|
||||
"const": true,
|
||||
"destructuring": true,
|
||||
"document": false,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"electron": false,
|
||||
"fetchWasm": false,
|
||||
"forOf": true,
|
||||
"global": true,
|
||||
"globalThis": true,
|
||||
"importScripts": false,
|
||||
"importScriptsInWorker": false,
|
||||
"module": true,
|
||||
"node": true,
|
||||
"nodeBuiltins": true,
|
||||
|
@ -785,7 +847,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -816,7 +878,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -909,7 +971,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -940,7 +1002,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -971,7 +1033,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -1064,7 +1126,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
@ -1095,7 +1157,7 @@ Object {
|
|||
"destructuring": true,
|
||||
"document": true,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"electron": false,
|
||||
"fetchWasm": true,
|
||||
"forOf": true,
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
"destructuring": true,
|
||||
"document": false,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"dynamicImportInWorker": true,
|
||||
"forOf": true,
|
||||
"globalThis": true,
|
||||
"module": true,
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
"destructuring": true,
|
||||
"document": false,
|
||||
"dynamicImport": true,
|
||||
"dynamicImportInWorker": false,
|
||||
"dynamicImportInWorker": true,
|
||||
"forOf": true,
|
||||
"globalThis": true,
|
||||
"module": true,
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as style from "./style.css";
|
|||
import * as text1 from "./text-with-bom.txt";
|
||||
import * as text2 from "./test-without-bom.text";
|
||||
|
||||
it("should remove BOM", function() {
|
||||
it("should remove BOM", async function() {
|
||||
const url = new URL("./resource-with-bom.ext", import.meta.url);
|
||||
|
||||
expect(mod).toBeDefined();
|
||||
|
@ -13,7 +13,7 @@ it("should remove BOM", function() {
|
|||
expect(url).toBeDefined();
|
||||
|
||||
const module = "module.js"
|
||||
const modules = import("./dir/" + module);
|
||||
const modules = await import("./dir/" + module);
|
||||
|
||||
expect(modules).toBeDefined();
|
||||
});
|
||||
|
|
|
@ -4,6 +4,9 @@ const fs = require("fs");
|
|||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
findBundle() {
|
||||
return ["dir_module_js.bundle0.js", "bundle0.js"];
|
||||
},
|
||||
afterExecute(options) {
|
||||
const outputPath = options.output.path;
|
||||
const files = fs.readdirSync(outputPath);
|
||||
|
|
|
@ -6,6 +6,9 @@ module.exports = {
|
|||
output: {
|
||||
assetModuleFilename: "[name][ext]"
|
||||
},
|
||||
optimization: {
|
||||
chunkIds: "named"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# Basic test
|
||||
WEBPACK_API_URL=https://api.example.com
|
||||
WEBPACK_MODE=test
|
||||
SECRET_KEY=should-not-be-exposed
|
||||
PRIVATE_VAR=also-hidden
|
||||
|
||||
# Expand test
|
||||
WEBPACK_BASE=example.com
|
||||
WEBPACK_FULL_URL=${WEBPACK_API_URL}/v1
|
||||
WEBPACK_PORT=${PORT:-3000}
|
||||
|
||||
# Mode-specific base value
|
||||
WEBPACK_ENV=development
|
|
@ -0,0 +1,3 @@
|
|||
# Production overrides
|
||||
WEBPACK_API_URL=https://prod-api.example.com
|
||||
WEBPACK_ENV=production
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
it("should expose only WEBPACK_ prefixed env vars", () => {
|
||||
expect(process.env.WEBPACK_API_URL).toBe("https://api.example.com");
|
||||
expect(process.env.WEBPACK_MODE).toBe("test");
|
||||
|
||||
// Non-prefixed vars should not be exposed
|
||||
expect(typeof process.env.SECRET_KEY).toBe("undefined");
|
||||
expect(typeof process.env.PRIVATE_VAR).toBe("undefined");
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
it("should load from custom envDir", () => {
|
||||
expect(process.env.WEBPACK_FROM_ENVS).toBe("loaded-from-envs-dir");
|
||||
expect(process.env.WEBPACK_API_URL).toBe("https://custom.example.com");
|
||||
});
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
"use strict";
|
||||
|
||||
it("should expose only APP_ and CONFIG_ prefixed vars", () => {
|
||||
expect(process.env.APP_NAME).toBe("MyApp");
|
||||
expect(process.env.CONFIG_TIMEOUT).toBe("5000");
|
||||
|
||||
// WEBPACK_ prefixed should not be exposed
|
||||
expect(typeof process.env.WEBPACK_API_URL).toBe("undefined");
|
||||
|
||||
// Non-prefixed should not be exposed
|
||||
expect(typeof process.env.SECRET_KEY).toBe("undefined");
|
||||
});
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
WEBPACK_FROM_ENVS=loaded-from-envs-dir
|
||||
WEBPACK_API_URL=https://custom.example.com
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
it("should expand variables by default", () => {
|
||||
expect(process.env.WEBPACK_BASE).toBe("example.com");
|
||||
expect(process.env.WEBPACK_API_URL).toBe("https://api.example.com");
|
||||
expect(process.env.WEBPACK_FULL_URL).toBe("https://api.example.com/v1");
|
||||
|
||||
// Test default value operator
|
||||
expect(process.env.WEBPACK_PORT).toBe("3000");
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
"use strict";
|
||||
|
||||
it("should load .env.production and override .env values", () => {
|
||||
// Value from .env.production should override .env
|
||||
expect(process.env.WEBPACK_API_URL).toBe("https://prod-api.example.com");
|
||||
expect(process.env.WEBPACK_ENV).toBe("production");
|
||||
|
||||
// Value only in .env
|
||||
expect(process.env.WEBPACK_MODE).toBe("test");
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
APP_NAME=MyApp
|
||||
CONFIG_TIMEOUT=5000
|
||||
WEBPACK_API_URL=should-not-be-exposed
|
||||
SECRET_KEY=also-hidden
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
|
||||
/** @type {import("../../../../").Configuration[]} */
|
||||
module.exports = [
|
||||
// Test 1: Basic - default behavior with WEBPACK_ prefix
|
||||
{
|
||||
name: "basic",
|
||||
mode: "development",
|
||||
entry: "./basic.js",
|
||||
dotenv: true
|
||||
},
|
||||
// Test 2: Expand - variables are always expanded
|
||||
{
|
||||
name: "expand",
|
||||
mode: "development",
|
||||
entry: "./expand.js",
|
||||
dotenv: true
|
||||
},
|
||||
// Test 3: Custom envDir - load from different directory
|
||||
{
|
||||
name: "custom-envdir",
|
||||
mode: "development",
|
||||
entry: "./custom-envdir.js",
|
||||
dotenv: {
|
||||
envDir: "./envs"
|
||||
}
|
||||
},
|
||||
// Test 4: Custom prefixes - multiple prefixes
|
||||
{
|
||||
name: "custom-prefixes",
|
||||
mode: "development",
|
||||
entry: "./custom-prefixes.js",
|
||||
dotenv: {
|
||||
envDir: "./prefixes-env",
|
||||
prefixes: ["APP_", "CONFIG_"]
|
||||
}
|
||||
},
|
||||
// Test 5: Mode-specific - .env.[mode] overrides
|
||||
{
|
||||
name: "mode-specific",
|
||||
mode: "production",
|
||||
entry: "./mode-specific.js",
|
||||
dotenv: true
|
||||
}
|
||||
];
|
|
@ -1,27 +1,39 @@
|
|||
it("should set fetchPriority", () => {
|
||||
import(/* webpackFetchPriority: "high" */ "./a");
|
||||
function abortable(fn) {
|
||||
return new Promise((resolve) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
fn = undefined;
|
||||
resolve('Promise resolved after delay');
|
||||
clearTimeout(timeoutId);
|
||||
}, 1000);
|
||||
|
||||
return fn();
|
||||
});
|
||||
}
|
||||
|
||||
it("should set fetchPriority", async () => {
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./a"));
|
||||
expect(document.head._children).toHaveLength(4);
|
||||
const script1 = document.head._children[2];
|
||||
expect(script1._attributes.fetchpriority).toBe("high");
|
||||
|
||||
import(/* webpackFetchPriority: "low" */ "./b");
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./b"));
|
||||
expect(document.head._children).toHaveLength(5);
|
||||
const script2 = document.head._children[4];
|
||||
expect(script2._attributes.fetchpriority).toBe("low");
|
||||
|
||||
import(/* webpackFetchPriority: "low" */ "./c");
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./c"));
|
||||
expect(document.head._children).toHaveLength(6);
|
||||
const script3 = document.head._children[5];
|
||||
expect(script3._attributes.fetchpriority).toBe("low");
|
||||
|
||||
import(/* webpackPrefetch: 20, webpackFetchPriority: "auto" */ "./c");
|
||||
abortable(() => import(/* webpackPrefetch: 20, webpackFetchPriority: "auto" */ "./c"));
|
||||
|
||||
import("./d")
|
||||
abortable(() => import("./d"))
|
||||
expect(document.head._children).toHaveLength(7);
|
||||
const script4 = document.head._children[6];
|
||||
expect(script4._attributes.fetchpriority).toBeUndefined();
|
||||
|
||||
import(/* webpackPrefetch: -20 */ "./d3");
|
||||
abortable(() => import(/* webpackPrefetch: -20 */ "./d3"));
|
||||
expect(document.head._children).toHaveLength(8);
|
||||
const script5 = document.head._children[7];
|
||||
expect(script5._attributes.fetchpriority).toBeUndefined();
|
||||
|
@ -29,12 +41,12 @@ it("should set fetchPriority", () => {
|
|||
const condition = true;
|
||||
|
||||
if (!condition) {
|
||||
import(/* webpackFetchPriority: "high", webpackChunkName: "one" */ "./e");
|
||||
abortable( () => import(/* webpackFetchPriority: "high", webpackChunkName: "one" */ "./e"));
|
||||
expect(document.head._children).toHaveLength(9);
|
||||
const script6 = document.head._children[8];
|
||||
expect(script6._attributes.fetchpriority).toBe("high");
|
||||
} else {
|
||||
import(/* webpackFetchPriority: "low", webpackChunkName: "two" */ "./e");
|
||||
abortable(() => import(/* webpackFetchPriority: "low", webpackChunkName: "two" */ "./e"));
|
||||
expect(document.head._children).toHaveLength(9);
|
||||
const script6 = document.head._children[8];
|
||||
expect(script6._attributes.fetchpriority).toBe("low");
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
function abortable(fn) {
|
||||
return new Promise((resolve) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
fn = undefined;
|
||||
resolve('Promise resolved after delay');
|
||||
clearTimeout(timeoutId);
|
||||
}, 1000);
|
||||
|
||||
return fn();
|
||||
});
|
||||
}
|
||||
|
||||
it("should set fetchPriority", () => {
|
||||
// Single Chunk
|
||||
import(/* webpackFetchPriority: "high" */ "./a");
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./a"));
|
||||
expect(document.head._children).toHaveLength(1);
|
||||
const script1 = document.head._children[0];
|
||||
expect(script1._attributes.fetchpriority).toBe("high");
|
||||
|
||||
// Multiple Chunks
|
||||
import(/* webpackFetchPriority: "high" */ "./b");
|
||||
import(/* webpackFetchPriority: "high" */ "./b2");
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./b"));
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./b2"));
|
||||
expect(document.head._children).toHaveLength(4);
|
||||
const script2 = document.head._children[1];
|
||||
const script3 = document.head._children[2];
|
||||
|
@ -17,19 +29,19 @@ it("should set fetchPriority", () => {
|
|||
expect(script4._attributes.fetchpriority).toBe("high");
|
||||
|
||||
// Single Chunk, low
|
||||
import(/* webpackFetchPriority: "low" */ "./c");
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./c"));
|
||||
expect(document.head._children).toHaveLength(5);
|
||||
const script5 = document.head._children[4];
|
||||
expect(script5._attributes.fetchpriority).toBe("low");
|
||||
|
||||
// Single Chunk, auto
|
||||
import(/* webpackFetchPriority: "auto" */ "./d");
|
||||
abortable(() => import(/* webpackFetchPriority: "auto" */ "./d"));
|
||||
expect(document.head._children).toHaveLength(6);
|
||||
const script6 = document.head._children[5];
|
||||
expect(script6._attributes.fetchpriority).toBe("auto");
|
||||
|
||||
// No fetch priority
|
||||
import("./e");
|
||||
abortable(() => import("./e"));
|
||||
expect(document.head._children).toHaveLength(7);
|
||||
const script7 = document.head._children[6];
|
||||
expect(script7._attributes.fetchpriority).toBeUndefined();
|
||||
|
@ -44,49 +56,49 @@ it("should set fetchPriority", () => {
|
|||
const script8 = document.head._children[7];
|
||||
expect(script8._attributes.fetchpriority).toBeUndefined();
|
||||
|
||||
import(/* webpackFetchPriority: "auto" */ "./g");
|
||||
abortable(() => import(/* webpackFetchPriority: "auto" */ "./g"));
|
||||
expect(document.head._children).toHaveLength(9);
|
||||
const script9 = document.head._children[8];
|
||||
expect(script9._attributes.fetchpriority).toBe("auto");
|
||||
|
||||
import(/* webpackFetchPriority: "unknown" */ "./h.js");
|
||||
abortable(() => import(/* webpackFetchPriority: "unknown" */ "./h.js"));
|
||||
expect(document.head._children).toHaveLength(10);
|
||||
const script10 = document.head._children[9];
|
||||
expect(script10._attributes.fetchpriority).toBeUndefined();
|
||||
|
||||
import(/* webpackFetchPriority: "high" */ "./i");
|
||||
import(/* webpackFetchPriority: "low" */ "./i");
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./i"));
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./i"));
|
||||
expect(document.head._children).toHaveLength(11);
|
||||
const script11 = document.head._children[10];
|
||||
expect(script11._attributes.fetchpriority).toBe("high");
|
||||
|
||||
import(/* webpackFetchPriority: "low" */ "./j");
|
||||
import(/* webpackFetchPriority: "high" */ "./j");
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./j"));
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./j"));
|
||||
expect(document.head._children).toHaveLength(12);
|
||||
const script12 = document.head._children[11];
|
||||
|
||||
expect(script12._attributes.fetchpriority).toBe("low");
|
||||
import(/* webpackFetchPriority: "low" */ "./k");
|
||||
import("./e");
|
||||
import(/* webpackFetchPriority: "high" */ "./k");
|
||||
expect(document.head._children).toHaveLength(13);
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./k"));
|
||||
abortable(() => import("./e"));
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./k"));
|
||||
abortable(() => expect(document.head._children).toHaveLength(13));
|
||||
const script13 = document.head._children[12];
|
||||
expect(script13._attributes.fetchpriority).toBe("low");
|
||||
|
||||
__non_webpack_require__("./125.js");
|
||||
import(/* webpackFetchPriority: "high" */ "./style.css");
|
||||
abortable(() => import(/* webpackFetchPriority: "high" */ "./style.css"));
|
||||
expect(document.head._children).toHaveLength(14);
|
||||
const link1 = document.head._children[13];
|
||||
expect(link1._attributes.fetchpriority).toBe("high");
|
||||
|
||||
__non_webpack_require__("./499.js");
|
||||
import("./style-1.css");
|
||||
abortable(() => import("./style-1.css"));
|
||||
expect(document.head._children).toHaveLength(15);
|
||||
const link2 = document.head._children[14];
|
||||
expect(link2._attributes.fetchpriority).toBeUndefined();
|
||||
|
||||
__non_webpack_require__("./616.js");
|
||||
import(/* webpackFetchPriority: "low" */ "./style-2.css");
|
||||
abortable(() => import(/* webpackFetchPriority: "low" */ "./style-2.css"));
|
||||
expect(document.head._children).toHaveLength(16);
|
||||
const link3 = document.head._children[15];
|
||||
expect(link3._attributes.fetchpriority).toBe("low");
|
||||
|
|
|
@ -57,9 +57,7 @@ describe("browserslist target", () => {
|
|||
["node 10.0.0"],
|
||||
["node 10.17.0"],
|
||||
["node 12.19.0"],
|
||||
|
||||
// UC browsers for Android
|
||||
["and_uc 12.12"],
|
||||
["node 13.12.0"],
|
||||
|
||||
// QQ browser
|
||||
["and_qq 10.4"],
|
||||
|
@ -73,6 +71,45 @@ describe("browserslist target", () => {
|
|||
// Multiple
|
||||
["firefox 80", "chrome 80"],
|
||||
["chrome 80", "node 12.19.0"],
|
||||
["chrome 80", "node 13.12.0"],
|
||||
|
||||
// defaults and fully supports es6-module
|
||||
// maintained node versions
|
||||
[
|
||||
"and_chr 140",
|
||||
"and_ff 142",
|
||||
"and_qq 14.9",
|
||||
"and_uc 15.5",
|
||||
"android 140",
|
||||
"chrome 140",
|
||||
"chrome 139",
|
||||
"chrome 138",
|
||||
"chrome 137",
|
||||
"chrome 112",
|
||||
"chrome 109",
|
||||
"chrome 105",
|
||||
"edge 140",
|
||||
"edge 139",
|
||||
"edge 138",
|
||||
"firefox 143",
|
||||
"firefox 142",
|
||||
"firefox 141",
|
||||
"firefox 140",
|
||||
"ios_saf 26.0",
|
||||
"ios_saf 18.5-18.6",
|
||||
"kaios 3.0-3.1",
|
||||
"node 24.8.0",
|
||||
"node 22.19.0",
|
||||
"node 20.19.0",
|
||||
"op_mob 80",
|
||||
"opera 122",
|
||||
"opera 121",
|
||||
"opera 120",
|
||||
"safari 26.0",
|
||||
"safari 18.5-18.6",
|
||||
"samsung 28",
|
||||
"samsung 27"
|
||||
],
|
||||
|
||||
// Unknown
|
||||
["unknown 50"]
|
||||
|
|
|
@ -17,7 +17,7 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProgressPlugin(),
|
||||
new webpack.ProgressPlugin(() => {}),
|
||||
{
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tapPromise("CacheTest", async () => {
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProgressPlugin(),
|
||||
new webpack.ProgressPlugin(() => {}),
|
||||
{
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tapPromise("CacheTest", async () => {
|
||||
|
|
|
@ -2947,6 +2947,22 @@ declare interface Configuration {
|
|||
*/
|
||||
devtool?: string | false;
|
||||
|
||||
/**
|
||||
* Enable and configure the Dotenv plugin to load environment variables from .env files.
|
||||
*/
|
||||
dotenv?:
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string | string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* The entry point(s) of the compilation.
|
||||
*/
|
||||
|
@ -4336,6 +4352,55 @@ declare interface DllReferencePluginOptionsManifest {
|
|||
| "jsonp"
|
||||
| "system";
|
||||
}
|
||||
declare class DotenvPlugin {
|
||||
constructor(options?: DotenvPluginOptions);
|
||||
config: {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir: string | boolean;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes: string | string[];
|
||||
};
|
||||
apply(compiler: Compiler): void;
|
||||
|
||||
/**
|
||||
* Load environment variables from .env files
|
||||
* Similar to Vite's loadEnv implementation
|
||||
*/
|
||||
loadEnv(
|
||||
fs: InputFileSystem,
|
||||
mode: undefined | string,
|
||||
context: string,
|
||||
callback: (
|
||||
err: null | Error,
|
||||
env?: Record<string, string>,
|
||||
fileDependencies?: string[]
|
||||
) => void
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Load a file with proper path resolution
|
||||
*/
|
||||
loadFile(fs: InputFileSystem, file: string): Promise<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for Dotenv plugin.
|
||||
*/
|
||||
declare interface DotenvPluginOptions {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string | string[];
|
||||
}
|
||||
declare class DynamicEntryPlugin {
|
||||
constructor(context: string, entry: () => Promise<EntryStaticNormalized>);
|
||||
context: string;
|
||||
|
@ -6380,35 +6445,6 @@ declare interface ImportDependencyMeta {
|
|||
externalType?: "import" | "module";
|
||||
}
|
||||
type ImportExpressionJavascriptParser = ImportExpressionImport & {
|
||||
options?:
|
||||
| null
|
||||
| ImportExpressionImport
|
||||
| UnaryExpression
|
||||
| ArrayExpression
|
||||
| ArrowFunctionExpression
|
||||
| AssignmentExpression
|
||||
| AwaitExpression
|
||||
| BinaryExpression
|
||||
| SimpleCallExpression
|
||||
| NewExpression
|
||||
| ChainExpression
|
||||
| ClassExpression
|
||||
| ConditionalExpression
|
||||
| FunctionExpression
|
||||
| Identifier
|
||||
| SimpleLiteral
|
||||
| RegExpLiteral
|
||||
| BigIntLiteral
|
||||
| LogicalExpression
|
||||
| MemberExpression
|
||||
| MetaProperty
|
||||
| ObjectExpression
|
||||
| SequenceExpression
|
||||
| TaggedTemplateExpression
|
||||
| TemplateLiteral
|
||||
| ThisExpression
|
||||
| UpdateExpression
|
||||
| YieldExpression;
|
||||
phase?: "defer";
|
||||
};
|
||||
declare interface ImportModuleOptions {
|
||||
|
@ -11288,12 +11324,6 @@ declare abstract class NormalModuleFactory extends ModuleFactory {
|
|||
],
|
||||
Module
|
||||
>;
|
||||
createParser: HookMap<SyncBailHook<[ParserOptions], void | ParserClass>>;
|
||||
parser: HookMap<SyncBailHook<[any, ParserOptions], void>>;
|
||||
createGenerator: HookMap<
|
||||
SyncBailHook<[GeneratorOptions], void | Generator>
|
||||
>;
|
||||
generator: HookMap<SyncBailHook<[any, GeneratorOptions], void>>;
|
||||
createModuleClass: HookMap<
|
||||
SyncBailHook<
|
||||
[
|
||||
|
@ -17992,6 +18022,22 @@ declare interface WebpackOptionsNormalized {
|
|||
*/
|
||||
devtool?: string | false;
|
||||
|
||||
/**
|
||||
* Enable and configure the Dotenv plugin to load environment variables from .env files.
|
||||
*/
|
||||
dotenv?:
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string | string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* The entry point(s) of the compilation.
|
||||
*/
|
||||
|
@ -18193,7 +18239,39 @@ type WebpackOptionsNormalizedWithDefaults = WebpackOptionsNormalized & {
|
|||
} & { watch: NonNullable<undefined | boolean> } & {
|
||||
performance: NonNullable<undefined | false | PerformanceOptions>;
|
||||
} & { recordsInputPath: NonNullable<undefined | string | false> } & {
|
||||
recordsOutputPath: NonNullable<undefined | string | false>;
|
||||
recordsOutputPath:
|
||||
| (string & {
|
||||
dotenv: NonNullable<
|
||||
| undefined
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string | string[];
|
||||
}
|
||||
>;
|
||||
})
|
||||
| (false & {
|
||||
dotenv: NonNullable<
|
||||
| undefined
|
||||
| boolean
|
||||
| {
|
||||
/**
|
||||
* The directory from which .env files are loaded. Defaults to the webpack context. Loads .env, .env.local, .env.[mode], .env.[mode].local in order.
|
||||
*/
|
||||
envDir?: string;
|
||||
/**
|
||||
* Only expose environment variables that start with these prefixes. Defaults to 'WEBPACK_'.
|
||||
*/
|
||||
prefixes?: string | string[];
|
||||
}
|
||||
>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -18916,6 +18994,7 @@ declare namespace exports {
|
|||
DllPlugin,
|
||||
DllReferencePlugin,
|
||||
DynamicEntryPlugin,
|
||||
DotenvPlugin,
|
||||
EntryOptionPlugin,
|
||||
EntryPlugin,
|
||||
EnvironmentPlugin,
|
||||
|
|
30
yarn.lock
30
yarn.lock
|
@ -2393,7 +2393,7 @@ camelcase@^6.3.0:
|
|||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||
|
||||
caniuse-lite@^1.0.30001737, caniuse-lite@^1.0.30001746:
|
||||
caniuse-lite@^1.0.30001746:
|
||||
version "1.0.30001746"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001746.tgz#199d20f04f5369825e00ff7067d45d5dfa03aee7"
|
||||
integrity sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==
|
||||
|
@ -3034,7 +3034,7 @@ eastasianwidth@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
electron-to-chromium@^1.5.211, electron-to-chromium@^1.5.227:
|
||||
electron-to-chromium@^1.5.227:
|
||||
version "1.5.228"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.228.tgz#38b849bc8714bd21fb64f5ad56bf8cfd8638e1e9"
|
||||
integrity sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==
|
||||
|
@ -6247,7 +6247,7 @@ node-preload@^0.2.1:
|
|||
dependencies:
|
||||
process-on-spawn "^1.0.0"
|
||||
|
||||
node-releases@^2.0.19, node-releases@^2.0.21:
|
||||
node-releases@^2.0.21:
|
||||
version "2.0.21"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.21.tgz#f59b018bc0048044be2d4c4c04e4c8b18160894c"
|
||||
integrity sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==
|
||||
|
@ -7179,10 +7179,10 @@ schema-utils@^3.0.0, schema-utils@^3.1.1:
|
|||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
schema-utils@^4.0.0, schema-utils@^4.3.0, schema-utils@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.2.tgz#0c10878bf4a73fd2b1dfd14b9462b26788c806ae"
|
||||
integrity sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==
|
||||
schema-utils@^4.0.0, schema-utils@^4.3.0, schema-utils@^4.3.3:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46"
|
||||
integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.9"
|
||||
ajv "^8.9.0"
|
||||
|
@ -7685,10 +7685,10 @@ synckit@^0.11.7, synckit@^0.11.8:
|
|||
dependencies:
|
||||
"@pkgr/core" "^0.2.4"
|
||||
|
||||
tapable@^2.2.0, tapable@^2.2.1, tapable@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.3.tgz#4b67b635b2d97578a06a2713d2f04800c237e99b"
|
||||
integrity sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==
|
||||
tapable@^2.2.0, tapable@^2.2.1, tapable@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6"
|
||||
integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==
|
||||
|
||||
tar@^7.4.3:
|
||||
version "7.4.3"
|
||||
|
@ -7973,10 +7973,10 @@ typedarray-to-buffer@^3.1.5:
|
|||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
typescript@^5.9.2:
|
||||
version "5.9.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6"
|
||||
integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==
|
||||
typescript@^5.9.3:
|
||||
version "5.9.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
|
||||
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.19.3"
|
||||
|
|
Loading…
Reference in New Issue