如何为生产环境准备Node.js?

10

我有一个MEAN Stack应用程序,需要在CPanel上进行托管,但我以前从未部署过应用程序。通过使用以下命令在dist文件夹中创建捆绑包,轻松部署应用程序的Angular部分:

ng build --prod

但是我想知道如何在服务器上发布我的后端代码。是否有任何命令可以像Angular中的一样创建一个缩小的捆绑包?

我还想知道是否需要安装一些npm包来确保我的应用程序在服务器上运行顺畅?当我搜索有关部署nodejs的信息时,经常看到PM2和Nginx。那么它们的好处是什么?

请提供可能有用的任何文章或视频。

Angular版本7

Node版本8.11.3

Ubuntu 16.04


1
问题太宽泛了,不适合在SO上讨论。Angular是一个框架,是客户端的,你正在比较橙子和苹果。Node不需要这些。只需上传项目(除了node_modules)并在服务器上运行“npm i”。就像我在谷歌搜索有关部署nodejs的信息时一直看到PM2和Nginx一样。那么它们的好处是什么?- 在生产中,您可能需要它们。我建议继续阅读,这不是可以简单解释的东西。了解它们真正用途的好方法是尝试在没有它们的情况下设置Web服务器。 - Estus Flask
@estus,那Node项目的大小怎么办?有没有什么方法可以将其压缩,或者我必须将完整项目(除了节点模块)发布出去? - harshit raghav
PM2旨在让您的应用程序在服务器上运行,而无需每次手动启动/关闭它们。Nginx用于提供静态文件并将localhost:3000 web服务器绑定到yourdomain.com:80。关于大小,如果您没有受到磁盘空间的限制,可以按原样复制它,否则可以尝试剥离一些在生产中不需要的内容。 - Estus Flask
@estus,所以PM2和forever类似吗? - harshit raghav
是的,它更加先进。 - Estus Flask
2个回答

29

代码可以按照现有的形式部署,它会正常工作!

您不需要缩小代码。虚拟机足够快以运行它。通常在从服务器发送文件到客户端时,会对文件进行缩小处理,以减小文件的大小,但由于您没有发送任何文件,所以无需担心。

我建议在达到生产状态后使用PM2管理Node进程。它包括日志、自动重启和许多实用功能,将帮助您解决问题。

如果您担心node_modules目录的大小,也许您可以确定哪些包仅在开发期间使用(例如测试工具如Jest和Mocha、转换器如Babel、Typescript等)。将这些包放置在"devDependency"键中您的package.json文件中。然后,在生产环境中,运行npm install --production,并且它不会安装您列出的devDependency内容。这应该会生成较小的node_modules

如果您正在遵循十二要素的原则,则还应为仅限生产的凭据创建一个环境文件。

为了完整性,如果你正在使用Babel / TypeScript或任何其他类似的工具,则需要将项目转译为Node可以理解的Javascript代码。运行相应的命令以生成生产构建。

关于Nginx,有些人喜欢将Nginx作为反向代理来服务静态资产,而对于API请求则将其转发到Node API。这是“最佳实践”,因为Nginx可以轻松地调整以更快地提供静态资产,并包括多个缓存、安全保护等选项。


你能推荐一些有用的 Nginx 文章或视频教程吗? - harshit raghav
clovis1122,谢谢你的回复。很长时间以来,我一直在关注PM2,但从未尝试过。我有1个CPU和1GB的虚拟机,运行PM2会有什么好处呢?是否有一些额外的功能?因为我只有1个CPU和1GB的配置。 - undefined
@ValentinPetkov 是的,有的!你可以查看文档以获取功能列表。点击这里查看文档。 - undefined

3

安装Node.js 我们将使用NodeSource包存档安装最新的LTS版本的Node.js。

首先,您需要安装NodeSource PPA以便获取其内容。确保您在主目录中,并使用curl检索Node.js 6.x存档的安装脚本:

$ cd ~
$curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh

你可以使用nano(或你喜欢的文本编辑器)来检查这个脚本的内容。
$ nano nodesource_setup.sh

并在sudo下运行脚本:

$ sudo bash nodesource_setup.sh

PPA 将被添加到您的配置文件中,并且本地软件包缓存将自动更新。在从 nodesource 运行设置脚本后,您可以以与上述相同的方式安装 Node.js 软件包:

$ sudo apt-get install nodejs

Node.js 包含了 Node.js 二进制文件以及 npm,因此您不需要单独安装 npm。但是,为了使一些 npm 包正常工作(例如那些需要从源代码编译的包),您需要安装 build-essential 包:

$ sudo apt-get install build-essential

Node.js 运行时已经安装并准备好运行应用程序!让我们来编写一个 Node.js 应用程序。

注意:当从 NodeSource PPA 安装时,Node.js 可执行文件名为 nodejs,而不是 node。

创建 Node.js 应用程序 我们将编写一个 Hello World 应用程序,仅返回 "Hello World" 到任何 HTTP 请求。这是一个示例应用程序,可帮助您设置 Node.js,并且您可以用自己的应用程序替换它 - 请确保修改应用程序以侦听适当的 IP 地址和端口。

Hello World 代码 首先,创建并打开您的 Node.js 应用程序进行编辑。本教程将使用 nano 编辑称为 hello.js 的示例应用程序:

$ cd ~
$ nano hello.js

将以下代码插入文件中。如果您愿意,您可以替换两个位置中的突出端口8080(确保使用非管理员端口,即1024或更高):

hello.js

#!/usr/bin/env nodejs
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080/');

现在保存并退出。

此Node.js应用程序仅简单地侦听指定的地址(localhost)和端口(8080),并使用200 HTTP成功代码返回“Hello World”。由于我们正在侦听localhost,远程客户端将无法连接到我们的应用程序。

测试应用程序 为了测试您的应用程序,请标记hello.js可执行:

$chmod +x ./hello.js

然后像这样运行:

$./hello.js

输出结果 服务器正在http://localhost:8080/上运行。 注意:以这种方式运行Node.js应用程序会阻止其他命令,直到通过按Ctrl-C 来终止该应用程序。

为了测试该应用程序,请在您的服务器上打开另一个终端会话,并使用curl连接到localhost:

$curl http://localhost:8080

如果您看到以下输出,则应用程序正常工作并侦听正确的地址和端口:
Output
Hello World

如果您没有看到正确的输出,请确保您的Node.js应用程序正在运行,并配置为侦听正确的地址和端口。

一旦确定它正常工作,请通过按Ctrl + C来停止应用程序(如果您还没有停止)。

安装PM2 现在,我们将安装PM2,它是一个用于Node.js应用程序的进程管理器。 PM2提供了一种简单的方式来管理和守护应用程序(将它们作为服务后台运行)。

我们将使用npm来安装PM2,它是一个随着Node.js一起安装的Node模块的软件包管理器,使用以下命令安装PM2:

$sudo npm install -g pm2

-g选项告诉npm将模块全局安装,以便在整个系统中都可以使用。

使用PM2管理应用程序 PM2简单易用。我们将介绍PM2的一些基本用法。

启动应用程序 您首先要做的是使用pm2 start命令在后台运行您的应用程序hello.js:

$ pm2 start hello.js

这还将您的应用程序添加到PM2的进程列表中,每次启动应用程序时都会输出:

Output
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Starting hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ hello    │ 0  │ fork │ 3524 │ online │ 00s     │ 21.566 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app

正如您所见,PM2会自动分配一个应用程序名称(基于文件名,不包括.js扩展名)和一个PM2 ID。 PM2还维护其他信息,例如进程的PID,其当前状态和内存使用情况。

在PM2下运行的应用程序将在应用程序崩溃或被杀死时自动重新启动,但需要采取额外步骤才能使应用程序在系统启动(引导或重新启动)时启动。幸运的是,PM2提供了一种简单的方法来实现这一点,即启动子命令。

启动子命令生成并配置启动脚本以在服务器引导时启动PM2及其管理的进程:

$ pm2 startup systemd

生成的输出的最后一行将包括一个必须使用超级用户权限运行的命令:

Output
[PM2] Init System found: systemd
[PM2] You have to run this command as root. Execute the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

运行生成的命令(类似于上面突出显示的输出,但是使用您自己的用户名而不是sammy),以设置PM2在启动时启动(使用您自己输出中的命令):

$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

这将创建一个systemd单元,该单元将在启动时为您的用户运行pm2。 这个pm2实例又运行hello.js。 您可以使用systemctl检查systemd单元的状态:
$ systemctl status pm2-sammy

有关systemd的详细概述,请参阅Systemd Essentials: Working with Services, Units, and the Journal。

其他PM2用法(可选) PM2提供许多子命令,允许您管理或查找有关应用程序的信息。请注意,运行没有任何参数的pm2将显示一个帮助页面,包括示例用法,涵盖比本教程的本节更详细的PM2用法。

使用此命令停止应用程序(指定PM2应用程序名称或ID):

$ pm2 stop app_name_or_id

使用以下命令重新启动应用程序(指定PM2应用程序名称或ID):
$ pm2 restart app_name_or_id

可以使用列表子命令查找当前由PM2管理的应用程序列表:

$ pm2 list

可以使用info子命令(指定PM2应用程序名称或ID)查找有关特定应用程序的更多信息:

$ pm2 info example

使用monit子命令可以打开PM2进程监视器。这将显示应用程序的状态、CPU和内存使用情况:

$ pm2 monit

现在你的Node.js应用程序正在运行,并由PM2管理,让我们设置反向代理。

设置Nginx作为反向代理服务器 现在你的应用程序正在运行,并且监听本地主机,你需要设置一种方式让用户访问它。我们将设置Nginx Web服务器作为反向代理来实现这个目的。

在先决条件教程中,我们在/etc/nginx/sites-available/default文件中设置了我们的Nginx配置。打开该文件进行编辑:

$ sudo nano /etc/nginx/sites-available/default

在服务器块中,您应该有一个现有的位置/块。请使用以下配置替换该块的内容。如果您的应用程序设置为侦听不同的端口,请将突出显示部分更新为正确的端口号。
/etc/nginx/sites-available/default
. . .
  location / {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

这将配置服务器以响应其根目录的请求。假设我们的服务器可通过 example.com 访问,通过 Web 浏览器访问 https://example.com/ 将发送请求到监听本地主机端口 8080 的 hello.js。

您可以向同一服务器块添加其他位置块,以提供对同一服务器上其他应用程序的访问。例如,如果您还在端口 8081 上运行另一个 Node.js 应用程序,则可以添加此位置块以允许通过 http://example.com/app2 访问它:

/etc/nginx/sites-available/default — Optional
   location /app2 {
     proxy_pass http://localhost:8081;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection 'upgrade';
     proxy_set_header Host $host;
     proxy_cache_bypass $http_upgrade;
 }

一旦您完成为应用程序添加位置块,请保存并退出。

请确保您没有通过输入引入任何语法错误:

$ sudo nginx -t

接下来,重新启动Nginx:

$ sudo systemctl restart nginx

假设你的Node.js应用程序正在运行,并且你的应用程序和Nginx配置是正确的,现在你应该能够通过Nginx反向代理访问你的应用程序。尝试通过访问服务器的URL(公共IP地址或域名)来验证。
结论 恭喜!你现在已经在Ubuntu 16.04服务器上使用Nginx反向代理运行了你的Node.js应用程序。这个反向代理设置足够灵活,可以让你的用户访问其他应用程序或静态网页内容。祝你在Node.js开发中好运!
我还找到了这个帮助视频:https://www.youtube.com/watch?v=Jsmeh7q9Qv4

1
请引用您复制粘贴的内容的来源。这不是您的努力。 https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-debian-10 - mohkamfer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接