Ich versuche, eine angular App von gulp nach webpack zu konvertieren. In gulp benutze ich gulp-preprocess, um einige Variablen in der HTML-Seite (z. B. den Datenbanknamen) in Abhängigkeit von NODE_ENV zu ersetzen. Was ist der beste Weg, um mit dem Webpack ein ähnliches Ergebnis zu erzielen?
Es gibt zwei grundlegende Möglichkeiten, um dies zu erreichen.
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
Beachten Sie, dass dies nur die Übereinstimmungen "wie sie sind" ersetzt. Deshalb hat die Zeichenfolge das Format, in dem sie vorliegt. Sie könnten eine komplexere Struktur haben, z. B. ein Objekt, aber Sie haben die Idee.
new webpack.EnvironmentPlugin(['NODE_ENV'])
EnvironmentPlugin
verwendet DefinePlugin
intern und ordnet die Umgebungswerte zu, um sie zu codieren. Terser-Syntax.
Alternativ können Sie die Konfiguration über ein Alias-Modul konsumieren. Konsumentenseitig würde es so aussehen:
var config = require('config');
Die Konfiguration selbst könnte folgendermaßen aussehen:
resolve: {
alias: {
config: path.join(__dirname, 'config', process.env.NODE_ENV)
}
}
Angenommen, process.env.NODE_ENV
ist development
. Es würde dann in ./config/development.js
abbilden. Das Modul, dem es zugeordnet ist, kann die Konfiguration folgendermaßen exportieren:
module.exports = {
testing: 'something',
...
};
Nur eine weitere Option, wenn Sie nur eine CLI-Schnittstelle verwenden möchten, verwenden Sie einfach die Option define
des Webpacks. Ich füge das folgende Skript in mein package.json
ein:
"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"
Also muss ich nur npm run build-production
ausführen.
Ich habe einige Optionen zum Festlegen umgebungsspezifischer Variablen untersucht und dabei Folgendes festgestellt:
Ich habe derzeit 2 Webpack-Konfigurationen:
webpack.production.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('production'),
'API_URL': JSON.stringify('http://localhost:8080/bands')
}
}),
webpack.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('development'),
'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
}
}),
In meinem Code erhalte ich den Wert von API_URL auf folgende (kurze) Weise:
const apiUrl = process.env.API_URL;
3. November 2016 BEARBEITEN
Webpack-Dokumente haben ein Beispiel: https://webpack.js.org/plugins/define-plugin/#usage
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object")
})
Mit ESLint müssen Sie undefinierte Variablen im Code zulassen, wenn Sie die no-undef
-Regel aktiviert haben. http://eslint.org/docs/rules/no-undef wie folgt:
/*global TWO*/
console.log('Running App version ' + TWO);
BEARBEITEN 7. September 2017 (Create-React-App specific)
Wenn Sie nicht zu viel konfigurieren möchten, lesen Sie Create-React-App: Create-React-App - Hinzufügen benutzerdefinierter Umgebungsvariablen . Unter der Haube nutzt CRA sowieso Webpack.
Sie können any Befehlszeilenargument ohne zusätzliche Plugins mit --env
seit Webpack 2 übergeben:
webpack --config webpack.config.js --env.foo=bar
Verwenden der Variablen in webpack.config.js:
module.exports = function(env) {
if (env.foo === 'bar') {
// do something
}
}
Sie können direkt EnvironmentPlugin
in webpack
verwenden, um während der Transpilation auf eine beliebige Umgebungsvariable zuzugreifen.
Sie müssen nur das Plugin in Ihrer webpack.config.js
-Datei deklarieren:
var webpack = require('webpack');
module.exports = {
/* ... */
plugins = [
new webpack.EnvironmentPlugin(['NODE_ENV'])
]
};
Beachten Sie, dass Sie den Namen der Umgebungsvariablen, die Sie verwenden möchten, explizit deklarieren müssen.
Da meine Bearbeitung am über dem Beitrag von thevangelist nicht genehmigt wurde, Veröffentlichung zusätzlicher Informationen.
Wenn Sie einen Wert aus package.json wie eine definierte Versionsnummer auswählen und über DefinePlugin] darauf zugreifen möchten in Javascript.
{"version": "0.0.1"}
Importieren Sie dann package.json innerhalb des jeweiligen webpack.config, greifen Sie mit der Importvariablen auf das Attribut zu, und verwenden Sie dann das Attribut in DefinePlugin.
const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json
Beispielsweise verwendet eine bestimmte Konfiguration unter webpack.config METADATA for DefinePlugin:
const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
Host: Host,
port: PORT,
ENV: ENV,
HMR: HMR,
RELEASE_VERSION:_version//Version attribute retrieved from package.json
});
new DefinePlugin({
'ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'process.env': {
'ENV': JSON.stringify(METADATA.ENV),
'NODE_ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'VERSION': JSON.stringify(METADATA.RELEASE_VERSION)//Setting it for the Scripts usage.
}
}),
Greifen Sie in einer beliebigen TypeScript-Datei darauf zu:
this.versionNumber = process.env.VERSION;
Der klügste Weg wäre:
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require("./package.json").version)
})
]
Um die Antworten persönlich zu ergänzen, bevorzuge ich Folgendes:
const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;
module.exports = {
...
plugins: [
new webpack.DefinePlugin({
process: {
env: {
NODE_ENV: prod? `"production"`: '"development"'
}
}
}),
...
]
};
Auf diese Weise gibt es keine Probleme mit funky env-Variablen oder plattformübergreifenden Problemen (mit env-vars). Alles, was Sie tun, ist, den normalen webpack
oder webpack -p
für die Entwicklung bzw. Produktion auszuführen.
Hinweis: Github Ausgabe
Nur eine andere Antwort, die der Antwort von @ zer0chain ähnelt. Mit einem Unterschied.
webpack -p
ist ausreichend.Es ist dasselbe wie:
--define process.env.NODE_ENV="production"
Und das ist das gleiche wie
// webpack.config.js
const webpack = require('webpack');
module.exports = {
//...
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
};
So etwas brauchen Sie möglicherweise nur in der package.json
Node -Datei:
{
"name": "projectname",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"debug": "webpack -d",
"production": "webpack -p"
},
"author": "prosti",
"license": "ISC",
"dependencies": {
"webpack": "^2.2.1",
...
}
}
Nur ein paar Tipps aus dem DefinePlugin :
Mit dem DefinePlugin können Sie globale Konstanten erstellen, die beim Kompilieren konfiguriert werden können. Dies kann nützlich sein, um ein unterschiedliches Verhalten zwischen Entwicklungs- und Release-Builds zuzulassen. Sie können beispielsweise eine globale Konstante verwenden, um zu bestimmen, ob die Protokollierung stattfindet. Vielleicht führen Sie die Protokollierung in Ihrem Entwicklungs-Build durch, aber nicht im Release-Build. Dies ist das Szenario, das das DefinePlugin ermöglicht.
Hiermit können Sie überprüfen, ob Sie webpack --help
eingeben.
Config options:
--config Path to the config file
[string] [default: webpack.config.js or webpackfile.js]
--env Enviroment passed to the config, when it is a function
Basic options:
--context The root directory for resolving entry point and stats
[string] [default: The current directory]
--entry The entry point [string]
--watch, -w Watch the filesystem for changes [boolean]
--debug Switch loaders to debug mode [boolean]
--devtool Enable devtool for better debugging experience (Example:
--devtool eval-cheap-module-source-map) [string]
-d shortcut for --debug --devtool eval-cheap-module-source-map
--output-pathinfo [boolean]
-p shortcut for --optimize-minimize --define
process.env.NODE_ENV="production"
[boolean]
--progress Print compilation progress in percentage [boolean]
So ergänzen Sie die Antworten:
Verwenden Sie ExtendedDefinePlugin anstelle von DefinePlugin
npm install extended-define-webpack-plugin --save-dev.
ExtendedDefinePlugin ist viel einfacher zu bedienen und dokumentiert :-) link
Da es DefinePlugin an guter Dokumentation mangelt, möchte ich helfen, indem ich sage, dass es tatsächlich funktioniert wie # DEFINE in c # .
#if (DEBUG)
Console.WriteLine("Debugging is enabled.");
#endif
Wenn Sie also verstehen möchten, wie DefinePlugin funktioniert, lesen Sie die c # #define -Doppelung. Link
Ich fand die folgende Lösung am einfachsten, um Umgebungsvariablen für Webpack 2 einzurichten:
Zum Beispiel haben wir ein Webpack-Einstellungen:
var webpack = require('webpack')
let webpackConfig = (env) => { // Passing envirmonment through
// function is important here
return {
entry: {
// entries
},
output: {
// outputs
},
plugins: [
// plugins
],
module: {
// modules
},
resolve: {
// resolves
}
}
};
module.exports = webpackConfig;
Umgebungsvariable in Webpack hinzufügen:
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
]
Plugin Variable definieren und zu plugins
hinzufügen:
new webpack.DefinePlugin({
'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
}),
Wenn Sie nun den Befehl webpack ausführen, übergeben Sie env.NODE_ENV
als Argument:
webpack --env.NODE_ENV=development
// OR
webpack --env.NODE_ENV development
Jetzt können Sie überall in Ihrem Code auf die Variable NODE_ENV
zugreifen.
Seit Webpack v4 wird durch einfaches Einstellen von mode
in Ihrer Webpack-Konfiguration der NODE_ENV
für Sie festgelegt (über DefinePlugin
). Dokumente hier.
Ich bevorzuge die Verwendung von .env-Dateien für andere Umgebungen.
env.dev
nach .env in den Stammordner zu kopierenenv.prod
nach .env zu kopierenund im Code
verwenden
require('dotenv').config(); const API = process.env.API ## which will store the value from .env file
Hier ist ein Weg, der für mich funktioniert und es mir ermöglicht hat, meine Umgebungsvariablen DRY durch Wiederverwendung einer JSON-Datei beizubehalten.
let config = require('./settings.json');
if (__PROD__) {
config = require('./settings-prod.json');
}
const envVars = {};
Object.keys(config).forEach((key) => {
envVars[key] = JSON.stringify(config[key]);
});
new webpack.DefinePlugin({
'process.env': envVars
}),
Ich bin kein großer Fan von ...
new webpack.DefinePlugin({
'process.env': envVars
}),
... da es keinerlei Sicherheit bietet. Stattdessen steigern Sie am Ende Ihre Geheimnisse, es sei denn, Sie fügen gitignore ein Webpack hinzu. ♀️ Es gibt eine bessere Lösung.
Grundsätzlich gilt, dass mit dieser Konfiguration, sobald Sie Ihren Code kompiliert haben, alle Prozess-Umgebungsvariablen aus dem gesamten Code entfernt werden, dank des Babel-Plugins transform-inline-environment-variables
PS kein einziger process.env.VAR mehr vorhanden ist, wenn Sie dies tun Sie müssen die Datei env.js aufrufen, bevor das Webpack den Befehl babel-loader aufruft. Deshalb ist dies das erste, was das Webpack aufruft. Das Array der Variablen in der Datei babel.config.js muss mit dem Objekt in env.js übereinstimmen. Jetzt gibt es nur noch eins zu tun. Fügen Sie eine .env
-Datei hinzu. Fügen Sie dort alle Ihre env-Variablen ein. Die Datei muss sich im Stammverzeichnis des Projekts befinden. Sie können sie aber auch beliebig hinzufügen. Stellen Sie lediglich sicher, dass Sie denselben Speicherort in der Datei env.js angeben und füge es auch gitignore hinzu
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
Wenn du das ganze babel + webpack + ts sehen willst, hol es dir von heaw https://github.com/EnetoJara/Node-TypeScript-babel-webpack.git
und die gleiche Logik gilt für reagieren und alle anderen ????
config
---webpack.js
---env.js
src
---source code world
.env
bunch of dotFiles
env.js
"use strict";
/***
I took the main idea from CRA, but mine is more cooler xD
*/
const {realpathSync, existsSync} = require('fs');
const {resolve, isAbsolute, delimiter} = require('path');
const NODE_ENV = process.env.NODE_ENV || "development";
const appDirectory = realpathSync(process.cwd());
if (typeof NODE_ENV !== "string") {
throw new Error("falle and stuff");
}
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
process.env.NODE_PATH = (process.env.NODE_PATH || "")
.split(delimiter)
.filter(folder => folder && isAbsolute(folder))
.map(folder => resolve(appDirectory, folder))
.join(delimiter);
const ENETO_APP = /^ENETO_APP_/i;
module.exports = (function () {
const raw = Object.keys ( process.env )
.filter ( key => ENETO_APP.test ( key ) )
.reduce ( ( env, key ) => {
env[ key ] = process.env[ key ];
return env;
},
{
BABEL_ENV: process.env.ENETO_APP_BABEL_ENV,
ENETO_APP_DB_NAME: process.env.ENETO_APP_DB_NAME,
ENETO_APP_DB_PASSWORD: process.env.ENETO_APP_DB_PASSWORD,
ENETO_APP_DB_USER: process.env.ENETO_APP_DB_USER,
GENERATE_SOURCEMAP: process.env.ENETO_APP_GENERATE_SOURCEMAP,
NODE_ENV: process.env.ENETO_APP_NODE_ENV,
PORT: process.env.ENETO_APP_PORT,
PUBLIC_URL: "/"
} );
const stringyField = {
"process.env": Object.keys(raw).reduce((env, key)=> {
env[key]=JSON.stringify(raw[key]);
return env;
},{}),
};
return {
raw, stringyField
}
})();
webpack-Datei ohne Plugins Troll
"use strict";
require("core-js");
require("./env.js");
const path = require("path");
const nodeExternals = require("webpack-node-externals");
module.exports = env => {
return {
devtool: "source-map",
entry: path.join(__dirname, '../src/dev.ts'),
externals: [nodeExternals()],
module: {
rules: [
{
exclude: /node_modules/,
test: /\.ts$/,
use: [
{
loader: "babel-loader",
},
{
loader: "ts-loader"
}
],
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: "file-loader",
},
],
},
],
},
node: {
__dirname: false,
__filename: false,
},
optimization: {
splitChunks: {
automaticNameDelimiter: "_",
cacheGroups: {
vendor: {
chunks: "initial",
minChunks: 2,
name: "vendor",
test: /[\\/]node_modules[\\/]/,
},
},
},
},
output: {
chunkFilename: "main.chunk.js",
filename: "name-bundle.js",
libraryTarget: "commonjs2",
},
plugins: [],
resolve: {
extensions: ['.ts', '.js']
} ,
target: "node"
};
};
babel.config.js
module.exports = api => {
api.cache(() => process.env.NODE_ENV);
return {
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-transform-classes", {loose: true}],
["@babel/plugin-external-helpers"],
["@babel/plugin-transform-runtime"],
["@babel/plugin-transform-modules-commonjs"],
["transform-member-expression-literals"],
["transform-property-literals"],
["@babel/plugin-transform-reserved-words"],
["@babel/plugin-transform-property-mutators"],
["@babel/plugin-transform-arrow-functions"],
["@babel/plugin-transform-block-scoped-functions"],
[
"@babel/plugin-transform-async-to-generator",
{
method: "coroutine",
module: "bluebird",
},
],
["@babel/plugin-proposal-async-generator-functions"],
["@babel/plugin-transform-block-scoping"],
["@babel/plugin-transform-computed-properties"],
["@babel/plugin-transform-destructuring"],
["@babel/plugin-transform-duplicate-keys"],
["@babel/plugin-transform-for-of"],
["@babel/plugin-transform-function-name"],
["@babel/plugin-transform-literals"],
["@babel/plugin-transform-object-super"],
["@babel/plugin-transform-shorthand-properties"],
["@babel/plugin-transform-spread"],
["@babel/plugin-transform-template-literals"],
["@babel/plugin-transform-exponentiation-operator"],
["@babel/plugin-proposal-object-rest-spread"],
["@babel/plugin-proposal-do-expressions"],
["@babel/plugin-proposal-export-default-from"],
["@babel/plugin-proposal-export-namespace-from"],
["@babel/plugin-proposal-logical-assignment-operators"],
["@babel/plugin-proposal-throw-expressions"],
[
"transform-inline-environment-variables",
{
include: [
"ENETO_APP_PORT",
"ENETO_APP_NODE_ENV",
"ENETO_APP_BABEL_ENV",
"ENETO_APP_DB_NAME",
"ENETO_APP_DB_USER",
"ENETO_APP_DB_PASSWORD",
],
},
],
],
presets: [["@babel/preset-env",{
targets: {
node: "current",
esmodules: true
},
useBuiltIns: 'entry',
corejs: 2,
modules: "cjs"
}],"@babel/preset-TypeScript"],
};
};