Передача зависимых от среды переменных в 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-файл для другой среды.
- использовать webpack.разработка.config для копирования
env.dev
to .env в корневую папку - использовать 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. Иногда простое жестко закодированное решение может работать для некоторых людей.