2015-02-25 2 views
13

Я использую webpack для объединения изоморфного приложения JS (based on this example), чтобы браузер выполнял тот же код, что и сервер. Все идет гладко, за исключением того, у меня есть config.js с некоторыми параметрами, которые тянули в из переменных окружения на сервере:Переменные окружения в изоморфном приложении JS: найти и заменить Webpack?

module.exports = { 
    servers: 
    auth: process.env.AUTH_SERVER_URL, 
    content: process.env.CONTENT_SERVER_URL 
    } 
} 

На сервере это большое, но когда WebPack делает это для клиента process пуст, и это не работает.

Я надеюсь, что есть что-то вроде «найти и заменить» плагин webpack, который заменит их своим содержимым только в этом файле?

"…config.js content…".replace(/process\.env\.([a-z0-9_]+)/, function(match, varName) { 
    return process.env[varName]; 
}) 
+0

Я нашел [envify] (https://www.npmjs.com/package/envify-loader), но мне сложно его настроить. –

+1

Существует плагин, который позволяет настраивать среду whitelist var, которая должна быть встроена: 'new webpack.EnvironmentPlugin ([" AUTH_SERVER_URL "," CONTENT_SERVER_URL "])' –

+0

Проблема в том, что машина, которая создает среду, не всегда одна тот, который запускает код (это верно в нашем случае). Один из способов - поместить их в «global» и «window» в HTML, но это не мое любимое решение. –

ответ

11

В вашем webpack.config.js, использовать следующие preLoaders (или postLoaders),

module: { 
    preLoaders: [ 
     { test: /\.js$/, loader: "transform?envify" }, 
    ] 
    } 

Другой способ использования в webpack.DefinePlugin:

plugins: [ 
    new DefinePlugin({ 
     'process.env': Object.keys(process.env).reduce(function(o, k) { 
     o[k] = JSON.stringify(process.env[k]); 
     return o; 
     }, {}) 
    }) 
] 

ПРИМЕЧАНИЕ: старый метод, использующий envify-loader осуждался:

DEPRECATED: используйте transform-loader + envify вместо этого.

+0

Из интереса, на каком основании другой метод устарел? –

+2

Все, что делалось в 'envify-loader', было всего лишь оберткой. Обсуждение [здесь] (https://github.com/mjohnston/envify-loader/issues/1). – activatedgeek

3

Да; выглядит как envify-loader было простым решением.

Я просто добавил следующее моих WebPack погрузчиков:

{ 
    test: /config\.js$/, loader: "envify-loader" 
} 

И config.js (и только этот файл) модифицируется, чтобы включить любые ссылочные переменные окружения статически :)

+7

Этот метод устарел! – activatedgeek

15

Обратите внимание, что использование DefinePlugin, как предложено в принятом ответе, потенциально опасно, поскольку оно полностью предоставляет process.env. Как уже отмечал Тобиас, на самом деле есть плагин EnvironmentPlugin, который делает именно это с добавленной способностью «белый список», используя внутреннюю область DefinePlugin.

В вашем webpack.config.js:

{ 
    plugins: [ 
    new webpack.EnvironmentPlugin([ 
     'NODE_ENV', 
     'WHITELISTED_ENVIRONMENT_VARIABLE' 
    ]) 
    ] 
} 
+0

Я не понимаю, как webpack знает, например, замену 'NODE_ENV'' 'production ''. С envify вам нужно сказать, что заменить «NODE_ENV» - как это работает? –

+1

Webpack на самом деле не заменяет никаких значений здесь, он будет вводить все, что вы делаете из списка process.env в свой код, с любыми уже установленными значениями. Перед началом компиляции вам необходимо установить переменные среды. Из командной строки 'NODE_ENV = production webpack' или, может быть, в вашем конфигурационном файле Webpack' process.env.NODE_ENV = 'production''. – owerme

+0

А это имеет смысл, спасибо! –

1

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

Я пока не вижу решения. Это то, что я сделал.

В publicEnv.js:

// List of the env variables you want to use on the client. Careful on what you put here! 
const publicEnv = [ 
    'API_URL', 
    'FACEBOOK_APP_ID', 
    'GA_ID' 
]; 

const isBrowser = typeof window !== 'undefined'; 
const base = (isBrowser ? window.__ENV__ : process.env) || {}; 

const env = {}; 
for (const v of publicEnv) { 
    env[v] = base[v]; 
} 
export default env; 

В шаблоне HTML файл страницы у меня есть:

import publicEnv from 'publicEnv.js'; 

... 

<script> 
    window.__ENV__ = ${stringify(publicEnv)}; 

    // Other things you need here... 
    window.__INITIAL_STATE__ = ${stringify(initialState)}; 
</script> 

Так что теперь я могу получить значение переменного окр на оба фронтэнде и бэкэнде с:

import publicEnv from 'publicEnv.js'; 

... 

console.log("Google Analytic code is", publicEnv.GA_ID); 

Надеюсь, это поможет.

Смежные вопросы