mirror of https://github.com/webpack/webpack.git
Compare commits
4 Commits
08625a84d7
...
99738ed20a
Author | SHA1 | Date |
---|---|---|
|
99738ed20a | |
|
891e3a7204 | |
|
c81107ae59 | |
|
ada334b199 |
|
@ -6,7 +6,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const createSchemaValidation = require("./util/create-schema-validation");
|
const createSchemaValidation = require("./util/create-schema-validation");
|
||||||
const { join } = require("./util/fs");
|
const { isAbsolute, join } = require("./util/fs");
|
||||||
|
|
||||||
/** @typedef {import("../declarations/WebpackOptions").DotenvPluginOptions} DotenvPluginOptions */
|
/** @typedef {import("../declarations/WebpackOptions").DotenvPluginOptions} DotenvPluginOptions */
|
||||||
/** @typedef {import("./Compiler")} Compiler */
|
/** @typedef {import("./Compiler")} Compiler */
|
||||||
|
@ -260,6 +260,8 @@ class DotenvPlugin {
|
||||||
|
|
||||||
/** @type {string[] | undefined} */
|
/** @type {string[] | undefined} */
|
||||||
let fileDependenciesCache;
|
let fileDependenciesCache;
|
||||||
|
/** @type {string[] | undefined} */
|
||||||
|
let missingDependenciesCache;
|
||||||
|
|
||||||
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, (_params, callback) => {
|
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, (_params, callback) => {
|
||||||
const inputFileSystem = /** @type {InputFileSystem} */ (
|
const inputFileSystem = /** @type {InputFileSystem} */ (
|
||||||
|
@ -272,7 +274,7 @@ class DotenvPlugin {
|
||||||
inputFileSystem,
|
inputFileSystem,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
(err, env, fileDependencies) => {
|
(err, env, fileDependencies, missingDependencies) => {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
const definitions = envToDefinitions(env || {});
|
const definitions = envToDefinitions(env || {});
|
||||||
|
@ -281,6 +283,8 @@ class DotenvPlugin {
|
||||||
definePlugin.definitions = definitions;
|
definePlugin.definitions = definitions;
|
||||||
// update the file dependencies
|
// update the file dependencies
|
||||||
fileDependenciesCache = fileDependencies;
|
fileDependenciesCache = fileDependencies;
|
||||||
|
// update the missing dependencies
|
||||||
|
missingDependenciesCache = missingDependencies;
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -289,6 +293,7 @@ class DotenvPlugin {
|
||||||
|
|
||||||
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
||||||
compilation.fileDependencies.addAll(fileDependenciesCache || []);
|
compilation.fileDependencies.addAll(fileDependenciesCache || []);
|
||||||
|
compilation.missingDependencies.addAll(missingDependenciesCache || []);
|
||||||
});
|
});
|
||||||
|
|
||||||
definePlugin.apply(compiler);
|
definePlugin.apply(compiler);
|
||||||
|
@ -321,7 +326,7 @@ class DotenvPlugin {
|
||||||
* @param {InputFileSystem} fs the input file system
|
* @param {InputFileSystem} fs the input file system
|
||||||
* @param {string | undefined} mode the mode
|
* @param {string | undefined} mode the mode
|
||||||
* @param {string} context the compiler context
|
* @param {string} context the compiler context
|
||||||
* @param {(err: Error | null, env?: Record<string, string>, fileDependencies?: string[]) => void} callback callback function
|
* @param {(err: Error | null, env?: Record<string, string>, fileDependencies?: string[], missingDependencies?: string[]) => void} callback callback function
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
loadEnv(fs, mode, context, callback) {
|
loadEnv(fs, mode, context, callback) {
|
||||||
|
@ -336,6 +341,9 @@ class DotenvPlugin {
|
||||||
}
|
}
|
||||||
const getDir = () => {
|
const getDir = () => {
|
||||||
if (typeof rawDir === "string") {
|
if (typeof rawDir === "string") {
|
||||||
|
if (isAbsolute(rawDir)) {
|
||||||
|
return rawDir;
|
||||||
|
}
|
||||||
return join(fs, context, rawDir);
|
return join(fs, context, rawDir);
|
||||||
}
|
}
|
||||||
if (rawDir === true) {
|
if (rawDir === true) {
|
||||||
|
@ -350,26 +358,30 @@ class DotenvPlugin {
|
||||||
const envFiles = this.getEnvFilesForMode(fs, dir, mode);
|
const envFiles = this.getEnvFilesForMode(fs, dir, mode);
|
||||||
/** @type {string[]} */
|
/** @type {string[]} */
|
||||||
const fileDependencies = [];
|
const fileDependencies = [];
|
||||||
|
/** @type {string[]} */
|
||||||
|
const missingDependencies = [];
|
||||||
|
|
||||||
// Read all files
|
// Read all files
|
||||||
const readPromises = envFiles.map((filePath) =>
|
const readPromises = envFiles.map((filePath) =>
|
||||||
this.loadFile(fs, filePath).then(
|
this.loadFile(fs, filePath).then(
|
||||||
(content) => {
|
(content) => {
|
||||||
fileDependencies.push(filePath);
|
fileDependencies.push(filePath);
|
||||||
return { content, filePath };
|
return content;
|
||||||
},
|
},
|
||||||
() =>
|
() => {
|
||||||
// File doesn't exist, skip it (this is normal)
|
// File doesn't exist, add to missingDependencies (this is normal)
|
||||||
({ content: "", filePath })
|
missingDependencies.push(filePath);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
Promise.all(readPromises)
|
Promise.all(readPromises)
|
||||||
.then((results) => {
|
.then((contents) => {
|
||||||
// Parse all files and merge (later files override earlier ones)
|
// Parse all files and merge (later files override earlier ones)
|
||||||
// Similar to Vite's implementation
|
// Similar to Vite's implementation
|
||||||
const parsed = /** @type {Record<string, string>} */ ({});
|
const parsed = /** @type {Record<string, string>} */ ({});
|
||||||
for (const { content } of results) {
|
for (const content of contents) {
|
||||||
if (!content) continue;
|
if (!content) continue;
|
||||||
const entries = parse(content);
|
const entries = parse(content);
|
||||||
for (const key in entries) {
|
for (const key in entries) {
|
||||||
|
@ -400,7 +412,7 @@ class DotenvPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, env, fileDependencies);
|
callback(null, env, fileDependencies, missingDependencies);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
callback(err);
|
callback(err);
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
WEBPACK_API_URL=https://api0.example.com
|
||||||
|
WEBPACK_FEATURE_FLAG=false
|
|
@ -0,0 +1,5 @@
|
||||||
|
it("should load env variables from .env file in step 0", function () {
|
||||||
|
expect(process.env.WEBPACK_API_URL).toBe("https://api0.example.com");
|
||||||
|
expect(process.env.WEBPACK_FEATURE_FLAG).toBe("false");
|
||||||
|
expect(process.env.WEBPACK_NEW_VAR).toBeUndefined();
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
WEBPACK_API_URL=https://api1.example.com
|
||||||
|
WEBPACK_FEATURE_FLAG=false
|
||||||
|
WEBPACK_NEW_VAR=added-in-step-1
|
|
@ -0,0 +1,5 @@
|
||||||
|
it("should load new variable added to .env file in step 1", function () {
|
||||||
|
expect(process.env.WEBPACK_API_URL).toBe("https://api1.example.com");
|
||||||
|
expect(process.env.WEBPACK_FEATURE_FLAG).toBe("false");
|
||||||
|
expect(process.env.WEBPACK_NEW_VAR).toBe("added-in-step-1");
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
WEBPACK_API_URL=https://api2.example.com
|
||||||
|
WEBPACK_FEATURE_FLAG=false
|
||||||
|
WEBPACK_NEW_VAR=added-in-step-1
|
|
@ -0,0 +1,2 @@
|
||||||
|
WEBPACK_FEATURE_FLAG=true
|
||||||
|
WEBPACK_DEV_ONLY=development-value
|
|
@ -0,0 +1,8 @@
|
||||||
|
it("should override .env values with .env.development in step 2", function () {
|
||||||
|
expect(process.env.WEBPACK_API_URL).toBe("https://api2.example.com");
|
||||||
|
// WEBPACK_FEATURE_FLAG should be overridden by .env.development
|
||||||
|
expect(process.env.WEBPACK_FEATURE_FLAG).toBe("true");
|
||||||
|
expect(process.env.WEBPACK_NEW_VAR).toBe("added-in-step-1");
|
||||||
|
// New variable from .env.development
|
||||||
|
expect(process.env.WEBPACK_DEV_ONLY).toBe("development-value");
|
||||||
|
});
|
|
@ -0,0 +1,35 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const DotenvPlugin = require("../../../../").DotenvPlugin;
|
||||||
|
|
||||||
|
/** @type {(env: Env, options: TestOptions) => import("../../../../").Configuration} */
|
||||||
|
|
||||||
|
module.exports = (env, { srcPath, testPath }) => {
|
||||||
|
const dotenvPlugin = new DotenvPlugin({
|
||||||
|
prefix: "WEBPACK_",
|
||||||
|
dir: ""
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
mode: "development",
|
||||||
|
dotenv: false,
|
||||||
|
plugins: [
|
||||||
|
(compiler) => {
|
||||||
|
let i = 0;
|
||||||
|
// Update dotenvPlugin.config.dir before each compile
|
||||||
|
// Use beforeCompile with stage -1 to run before DotenvPlugin
|
||||||
|
compiler.hooks.beforeCompile.tap(
|
||||||
|
{
|
||||||
|
name: "UpdateDotenvDir",
|
||||||
|
stage: -1
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
dotenvPlugin.config.dir = path.join(__dirname, String(i));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
dotenvPlugin
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
|
@ -4463,7 +4463,8 @@ declare class DotenvPlugin {
|
||||||
callback: (
|
callback: (
|
||||||
err: null | Error,
|
err: null | Error,
|
||||||
env?: Record<string, string>,
|
env?: Record<string, string>,
|
||||||
fileDependencies?: string[]
|
fileDependencies?: string[],
|
||||||
|
missingDependencies?: string[]
|
||||||
) => void
|
) => void
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue