如何在运行浏览器化脚本之前设置process.env?

时间:2014-10-24 02:35:33

标签: node.js browserify

最初的html来自后端。服务器具有已定义的process.env.NODE_ENV(以及其他环境变量)。浏览器化代码构建一次并且在多个环境中运行stagingproduction等),因此不可能将环境变量内联到浏览器化的脚本中(例如,通过envify)。我希望能够在渲染的html中编写环境变量,并使用浏览器化的代码来使用这些变量。这可能吗?

以下是我想象的事情:

<html>
  <head>
    <script>window.process = {env: {NODE_ENV: 'production'}};</script>
    <script src="/build/browserified_app.js"></script>
  </head>
</html>

5 个答案:

答案 0 :(得分:9)

不要在环境中对环境变量进行硬编码,而是使用envify插件。

npm install envify 

此插件会自动修改process.env.VARIABLE_HERE,并将您作为参数传递给envify。

例如:

browserify index.js -t [ envify --DEBUG app:* --NODE_ENV production --FOO bar ] > bundle.js

在您的申请中,process.env.DEBUG将替换为app:*process.env.NODE_ENV将替换为production,依此类推。这是一个干净的&amp;&amp;在我看来,优雅的方式来处理这个问题。

答案 1 :(得分:2)

您可以更改入口点文件,基本上可以进行此类设置,然后需要原始主文件。

process.env.NODE_ENV = 'production';
require('app.js');

其他方式(非常清晰)是使用envify之类的转换,它会直接用字符串值替换代码中的NODE_ENV。

选项1

我认为你的方法通常应该有效,但是我不会直接写到process.env,因为我非常确定它会在包中被覆盖。相反,您可以创建像__env这样的全局变量,然后在实际的捆绑代码中将其设置为条目文件中的process.env。这是未经测试的解决方案,但我相信它应该可行。

选项2

使用localStorage并让主脚本在初始化时从那里读取变量。您可以手动将变量设置为localStorage,或者如果您有变量,您甚至可以让服务器提供它们。开发人员只需打开控制台并键入类似loadEnv('production')的内容,它就会执行XHR并将结果存储在localStorage中。即使使用手动方法,仍然有一个优点,即这些不需要在html中进行硬编码。

如果手动听起来不够好并且服务器也是死路一条,你可以在捆绑包中包含所有环境中的所有变量(如果你有它们),然后使用switch语句来选择正确的基于某些条件的(例如localhost,生产主机)。


考虑到这一点,根据您的需求,您绝对不在Browserify的范围之内。它可以为您制作捆绑包,但如果您不想在捆绑包中使用这些信息,那么您就是自己的。

答案 2 :(得分:1)

所以我决定插入环境变量是Web服务器的工作。我的场景需要每个环境使用不同的记录器(例如'local','test','prod')。

代码:

var express = require('express')
  , replace = require('replace');

...

var app = express();
var fileToReplace = <your browserified js here>;
replace({
  regex: 'ENV_ENVIRONMENT'
  , replacement: process.env.ENVIRONMENT
  , paths: [fileToReplace]
});

...

app.listen(process.env.PORT);

我硬编码'ENV_ENVIRONMENT',但您可以在package.json中创建一个对象并使其可配置。

这当然有效,因为它可能是您拥有的唯一服务器入口点。

答案 3 :(得分:1)

我首先成功写入json文件,然后将该json文件导入需要读取环境的任何地方。

所以在我的gulp文件中:

import settings from './settings';
import fs from 'fs';
...
fs.writeFileSync('./settings.json', JSON.stringify(settings));

在settings.js文件中:

if(process.env.NODE_ENV) {
    console.log('Starting ' + process.env.NODE_ENV + ' environment...');
} else {
    console.log('No environment variable set.');
    process.exit();
}

export default (() => {
    let settings;

    switch(process.env.NODE_ENV) {
        case 'development':
            settings = {
                baseUrl: '...'
            };
            break;
        case 'production':
            settings = {
                baseUrl: 'some other url...'
            };
            break;
    }

    return settings;
})();

然后你可以在任何其他文件中导入settings.json文件,它将是静态的,但包含你当前的环境:

import settings from './settings.json';
...
console.log(settings.baseUrl);

我来这里寻找更清洁的解决方案......祝你好运!

答案 4 :(得分:1)

我遇到了这个问题构建同构反应应用程序。我使用以下(好吧,它有点hacky)解决方案:

我将env分配给window对象,当然我没有公开所有env个变种,只有那些可能是公开的变量(没有密码的秘密密钥和这样)。

// code...
const expose = ["ROOT_PATH", "ENDPOINT"];
const exposeEnv = expose.reduce(
    (exposeEnv, key) => Object.assign(exposeEnv, { [key]: env[key] }), {}
);
// code...
res.send(`<DOCTYPE html>
// html...
<script>window.env = ${JSON.stringify(exposeEnv)}</script>
// html...
`);
// code...

然后,在我的应用程序客户端入口点(哦,是的,你必须有一个入口点)我这样做:

process.env = window.env;

YMMV AKA WFM!