Передача зависимых от среды переменных в webpack

Я пытаюсь преобразовать угловое приложение из gulp в webpack. в gulp я использую gulp-preprocess для замены некоторых переменных на html-странице (например, имя базы данных) в зависимости от NODE_ENV. Каков наилучший способ достижения аналогичного результата с помощью webpack?

13 ответов


есть два основных способа добиться этого.

DefinePlugin

new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),

обратите внимание, что это просто заменит матчи "как есть". Вот почему строка имеет такой формат. У вас может быть более сложная структура, такая как объект, но вы получаете идею.

EnvironmentPlugin

new webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPlugin использует DefinePlugin внутренне и отображает значения среды для кода через него. Пократче синтаксис.

псевдоним

в качестве альтернативы вы можете использовать конфигурацию через модуль с псевдонимами. Со стороны потребителя это выглядело бы так:

var config = require('config');
конфигурация может выглядеть так:
resolve: {
    alias: {
        config: path.join(__dirname, 'config', process.env.NODE_ENV)
    }
}

скажем process.env.NODE_ENV is development. Это будет карта в ./config/development.js затем. Модуля карты можно экспортировать настройки вроде этого:

module.exports = {
    testing: 'something',
    ...
};

просто еще один вариант, если вы хотите использовать только интерфейс cli, просто используйте define опция webpack. Я добавляю следующий скрипт в my package.json :

"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"

так что мне просто нужно бежать npm run build-production.


Я исследовал несколько вариантов того, как установить переменные, зависящие от среды, и в итоге получил следующее:

в настоящее время у меня есть 2 конфигурации webpack:

webpack.производство.конфиг.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('production'),
    'API_URL': JSON.stringify('http://localhost:8080/bands')
  }
}),

webpack.конфиг.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('development'),
    'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
  }
}),

в моем коде я получаю значение API_URL таким (кратким) способом:

const apiUrl = process.env.API_URL;

редактировать 3 ноября 2016

документы Webpack имеют пример: 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")
})

С ESLint нужно разрешить неопределенные переменные в коде, если у вас есть no-undef правило. http://eslint.org/docs/rules/no-undef вот так:

/*global TWO*/
console.log('Running App version ' + TWO);

редактировать 7 сентября 2017 года (Create-React-App specific)

если вы не в настройке слишком много, проверьте Create-React-App: Create-React-App-Добавление Пользовательских Переменных Среды. Под капотом CRA все равно использует Webpack.


вы можете напрямую использовать EnvironmentPlugin в наличии webpack иметь доступ к любой переменной среды во время transpilation.

вам просто нужно объявить плагин в своем :

var webpack = require('webpack');

module.exports = {
    /* ... */
    plugins = [
        new webpack.EnvironmentPlugin(['NODE_ENV'])
    ]
};

обратите внимание, что необходимо явно объявить имя переменных среды, которые вы хотите использовать.


вы можете пройти любой аргумент командной строки без дополнительных плагинов используя --env С webpack 2:

webpack --config webpack.config.js --env.foo=bar

использование переменной в webpack.конфиг.js:

module.exports = function(env) {
    if (env.foo === 'bar') {
        // do something
    }
}

источник


чтобы добавить к куче ответов лично я предпочитаю следующее:

const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;

module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin({
      process: {
        env: {
          NODE_ENV: prod? `"production"`: '"development"'
        }
      }
    }),
    ...
  ]
};

используя это, нет фанковых переменных env или кросс-платформенных проблем (с env vars). Все, что вы делаете, это запустить нормальный webpack или webpack -p для dev или продукции соответственно.

ссылки: выпуск Github


С момента моего редактирования на выше пост thevangelist не был утвержден, размещения дополнительной информации.

если вы хотите выбрать значение из пакета.в JSON как определено номер версии и получить доступ к нему через DefinePlugin внутри Javascript.

{"version": "0.0.1"}

Затем Импорт пакета.в JSON внутри соответствующих webpack.config, доступ к атрибуту, используя импортируйте переменную, затем используйте атрибут в DefinePlugin.

const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json

например, определенная конфигурация на webpack.config использует метаданные для 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.
        }
      }),

доступ к этому внутри любого файла typescript:

this.versionNumber = process.env.VERSION;

самый умный способ был бы таков:

// webpack.config.js
plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require("./package.json").version)
    })
  ]

спасибо Россу Аллену


просто еще один ответ, похожий на ответ @zer0chain. Однако с одним отличием.

задание webpack -p вполне достаточно.

это то же, что:

--define process.env.NODE_ENV="production"

и это то же самое, что

// webpack.config.js
const webpack = require('webpack');

module.exports = {
  //...

  plugins:[
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
};

таким образом, вам может понадобиться только что-то подобное в package.json узел файл:

{
  "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",
    ...
  }
}

всего несколько советов от DefinePlugin:

DefinePlugin позволяет создавать глобальные константы, которые можно настроить во время компиляции. Это может быть полезно для разрешения различного поведения между сборками разработки и сборками выпуска. Например, можно использовать глобальную константу, чтобы определить, происходит ли ведение журнала; возможно, вы выполняете ведение журнала в сборке разработки, но не в сборке выпуска. Это тот сценарий, который облегчает Дефинеплюгин.


что это так, что вы можете проверить, если вы вводите webpack --help

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]

чтобы добавить в кучу ответов:

использовать ExtendedDefinePlugin вместо DefinePlugin

npm install extended-define-webpack-plugin --save-dev.

ExtendedDefinePlugin намного проще в использовании и документируется :-) ссылке

Потому Что DefinePlugin не хватает хорошая документация, я хочу помочь, сказав, что это на самом деле работает как #определить в C#.

#if (DEBUG)
        Console.WriteLine("Debugging is enabled.");
#endif

таким образом, если вы хотите понять, как DefinePlugin работает, прочитайте c# #определяет doucmentation. ссылке


Я нашел следующее решение, которое проще всего настроить переменную среды для Webpack 2:

например, у нас есть настройки webpack:

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;

добавить переменную среды в Webpack:

plugins: [
    new webpack.EnvironmentPlugin({
       NODE_ENV: 'development',
       }),
]

определите переменную плагина и добавьте ее в plugins:

    new webpack.DefinePlugin({
        'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
    }),

теперь при выполнении команды webpack, pass env.NODE_ENV в качестве аргумента:

webpack --env.NODE_ENV=development

// OR

webpack --env.NODE_ENV development

теперь вы можете получить доступ к NODE_ENV переменная в любом месте вашего кода.


Я предпочитаю использовать .env-файл для другой среды.

  1. использовать webpack.разработка.config для копирования env.dev to .env в корневую папку
  2. использовать webpack.подгонять.config для копирования env.prod to .env

и в коде

использовать

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


вот способ, который работал для меня и позволил мне сохранить переменные среды сухими, повторно используя файл json.

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

Я не знаю, почему, но никто не упоминает самое простое решение. Это работает для меня для nodejs и grunt. Как для многих людей webpack может быть запутанным, вы можете просто использовать следующую строку:

process.env.NODE_ENV = 'production';

с вышеуказанным решением вам действительно не нужно использовать envify или webpack. Иногда простое жестко закодированное решение может работать для некоторых людей.