2016-01-13 37 views
3

我想根据环境以两种不同的方式启动应用程序。从简单脚本启动主节点应用程序的最佳方式

在的package.json:

"scripts": { 
    "start": "node start.js" 
} 

然后在脚本检查环境变量并执行正确的命令:

// start.js 
var env = process.env.NODE_ENV; 

if (env === 'development') { 
    //run './node_modules/.bin/nodemon main.js' 
} 

if (env === 'production') { 
    //run 'node main.js' 
} 

//do I need to exit? 
process.exit(1); 

execforkspawn理想在这里?我不需要在start.js和main.js之间进行通信,我想要的开销最小。我希望它能够直接运行特定于环境的命令。我的倾向是fork,因为它会开始一个新的过程,父母将终止。

UPDATE:我对使用多个npm命令的替代解决方案不感兴趣。我特别想了解使用各种方法从另一个节点脚本启动一个节点脚本的优点/缺点/资源使用/性能影响,这些方法使用各种各样的child_process方法。

+0

给出了一个答案,请让我知道如果有什么事情你都弄不清 - 很高兴,如果需要扩大。 – arcseldon

+0

嗨,请你可以查看我的答案,并让我知道你是否觉得有帮助(upvote/mark as answer)。如果您需要更多信息,请告诉我 - 欢迎提供进一步支持。 – arcseldon

回答

0

我认为这种方法不适合。

中的package.json

{ 
    ... 
    "scripts": { 
    "start": "NODE_ENV=production node ./app" 
    } 
    ... 
} 

的那么

npm start

更新1

如果你在Windows机器只使用这样的

set NODE_ENV=development&& nodemon server.js 

如果你的机器是不是Windows机器,使用此

{ 
... 
"scripts": { 
"start": "NODE_ENV=development nodemon ./src/server/app.js" 
} 
... 
} 
+1

这对于生产来说很好,但它无法在开发中使用nodemon启动应用程序。 – emkman

2

我倾向于做这样的事情:

var env = process.env.NODE_ENV || 'development'; 

就在主引导程序文件(app.js,main.js ,start.js或任何你命名的),因为我通常的用例是本地开发工作。所以如果没有设置,它使用开发,如果我已经明确地设置了一个环境变量,它会使用它(通常只为生产设置,但可以是任何东西,包括测试等)。

然后,对于生产环境,您只需设置NODE_ENV环境变量(在部署到实时环境时,可以非常简单地设置Heroku等云服务)。

你有时会看到另一种模式是:

var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development'; 

这实际上也更新process.env.NODE_ENV分配的值,这意味着如果你有其他地方也检查proces.env.NODE_ENV的价值那么你不必继续使用“||'开发'”检查。这不是我倾向于使用的模式,但你会在野外看到它。

您的npm脚本条目看起来不错,但没有什么能阻止您定义其他脚本,调用shell脚本,设置env变量等。 如果你想有一个生产,我建议你做的是明确的:

eg.In的package.json:

"scripts": { 
    "start": "npm run dev" 
    "dev": "nodemon start.js", 
    "prd": "NODE_ENV=production node start.js" 
} 

这样一来,没有混乱,你必须要么运行:

npm run dev 
// same as npm start 

npm run prd 

以上,我们的开发环境是EXEC根据要求与nodemon以及我们的生产环境节点

更新基于OP反馈

这child_process方法是最好的,从开始你的主节点的应用程序。这是我的问题的重点

你所问的是非典型的 - 但是,当然有选择:

如果你想背景节点实例,则容易从命令控制这个(&)等

但是,如果你真的想这样做,那么在过去我选择使用NPM模块 - cluster

npm install cluster 

这样就可以产卵从主进程的子实例 - 在你的情况下,只需设置子实例数为1

var cluster = require('cluster') 
    , app = require('./main'); 

cluster(app) 
    .set('workers', 1) 
    // other configuration here 

最后,如果你不希望使用集群,真正的问题是多线沿线的“如何启动内部节点的另一Node.js应用程式,然后:

使用child_process.fork()它类似于spawn(),而是用来创造全新的章安。 V8的nces。因此它专门用于运行Node的新实例。

var fork = require('child_process').fork; 
var child = fork('./main'); 

还有更多选项,详情请参阅documentation

+0

是的,这是一个不错的选择。我也可以在使用ENV或其他变量的'start'中使用bash stye if语句,但这仍然不能回答我最好从哪个** child_process **方法启动主节点应用程序的问题。这是我的问题的主要观点。 – emkman

+0

根据OP的反馈意见更新答案。 – arcseldon

1

如下

require('child_process').spawn()开始尽快在流发送回从子进程的数据作为子进程开始执行之间spawn()exec()child_processfork()的差异。当你运行这个命令时,它发送一个系统命令,它将在它自己的进程上运行,而不是在你的节点进程中执行代码。在此,不会创建新的V8实例,并且处理器上只有一个节点模块副本处于活动状态。当您希望子进程向节点返回大量数据时使用它。

require('child_process').fork()是spawn的一个特殊实例,它运行V8引擎的新实例。这实际上意味着您正在创建多个工作在相同节点代码库上的不同任务。

require('child_process').exec()从子进程返回缓冲区。默认缓冲区大小为200k。它是异步的,但它会等待子进程结束并尝试一次返回所有缓冲的数据。如果您的子进程的返回数据大于200k,那么您将超出maxBuffer。

PM2

var exec = require('child_process').exec; 

child_process.exec的源代码是用来启动的node.js应用程序。 PM2也有cluster模式,这里使用culster.for()。在child_process.fork之上实现了cluster.fork

if (cluster.isMaster) { 
    // Master: 
    // Let's fork as many workers as you have CPU cores 

    for (var i = 0; i < numCPUs; ++i) { 
    cluster.fork(); 
    } 
} else { 
    // Worker: 
    // Let's spawn a HTTP server 
    // (Workers can share any TCP connection. 
    // In this case its a HTTP server 
    ... 
} 

IMO,PM2是启动node.js应用程序的一个很好的选择。它也可以使用PM2-devdevelopment模式启动node.js。更多细节可以在here找到。

来源:

http://www.codingdefined.com/2014/08/difference-between-fork-spawn-and-exec.html https://nodejs.org/api/cluster.html#cluster_cluster_fork_env

+0

我已阅读您引用的文档和文章,但希望更深入地了解每个选项的含义。例如,自发布这个问题以来,我开始在512MB服务器实例上使用execFile启动一个应用程序,并且它似乎在泄漏内存。也许是因为它将缓冲流传回给父节点?此外,你推荐exec,因为PM2使用它,但@arcseldon在他的回答中推荐fork。我试图在没有几天的实验的情况下找到共识。 – emkman

相关问题