wake-up-neo.com

Umgebungsabhängige Variablen im Webpack übergeben

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?

279
kpg

Es gibt zwei grundlegende Möglichkeiten, um dies zu erreichen.

Plugin definieren

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.

EnvironmentPlugin

new webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPlugin verwendet DefinePlugin intern und ordnet die Umgebungswerte zu, um sie zu codieren. Terser-Syntax.

Alias

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',
    ...
};
402

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.

106
zer0chain

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.

67
thevangelist

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
    }
}

Quelle

22
andruso

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.

22
Kuhess

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)
    })
  ]

Danke an Ross Allen

13
Abhijeet

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

13
Goblinlord

Nur eine andere Antwort, die der Antwort von @ zer0chain ähnelt. Mit einem Unterschied.

Die Einstellung von 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]
11
prosti

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

3

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.

2
ruddra

Seit Webpack v4 wird durch einfaches Einstellen von mode in Ihrer Webpack-Konfiguration der NODE_ENV für Sie festgelegt (über DefinePlugin). Dokumente hier.

1
ericsoco

Ich bevorzuge die Verwendung von .env-Dateien für andere Umgebungen.

  1. Verwenden Sie webpack.dev.config, um env.dev nach .env in den Stammordner zu kopieren
  2. Verwenden Sie webpack.prod.config, um env.prod nach .env zu kopieren

und im Code

verwenden

require('dotenv').config(); const API = process.env.API ## which will store the value from .env file

1
Siva Kandaraj

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
}),
0
cbaigorri

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"],
    };
};
0
Ernesto