Передача зависимых от среды переменных в 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иdevelopment. Это будет карта в./config/development.jsзатем. Модуль, который он отображает, может экспортировать конфигурацию следующим образом:module.exports = { testing: 'something', ... };
просто еще один вариант, если вы хотите использовать только интерфейс cli, просто используйте
defineопция webpack. Я добавляю следующий скрипт в мой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 docs имеет пример: 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.вы просто должны объявить плагин в свой
webpack.config.jsfile: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.конфигурации, доступ к атрибуту, используя импортируйте переменную, затем используйте атрибут в DefinePlugin.
const PACKAGE = require('../package.json'); const _version = PACKAGE.version;//Picks the version number from package.jsonнапример определенная конфигурация на webpack.конфигурации использует метаданные для 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 позволяет создавать глобальные константы, которые могут быть настроены во время компиляции. Это может быть полезно для разрешения различного поведения между сборками разработки и сборками выпуска. Например, можно использовать глобальную константу, чтобы определить, выполняется ли ведение журнала; возможно, вы выполняете ведение журнала в сборке разработки, но не в сборке выпуска. Это своего рода сценарий, который облегчает DefinePlugin.
что это так, вы можете проверить, если вы типа
webpack --helpConfig 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# директива #define 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.разработка.конфигурация для копирования
env.devдля .env в корневую папку- использовать webpack.подгонять.конфигурация для копирования
env.prodto .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. Иногда простое жестко закодированное решение может работать для некоторых людей.
Comments