如何为生产准备 nodejs?

Posted

技术标签:

【中文标题】如何为生产准备 nodejs?【英文标题】:How to prepare nodejs for production? 【发布时间】:2019-06-07 17:37:57 【问题描述】:

我有一个 MEAN Stack 应用程序需要托管在 CPanel 上,但我之前从未部署过应用程序。通过使用以下命令在 dist 文件夹中创建一个包,可以很容易地部署应用程序的 Angular 部分:

ng build --prod

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

我也想知道我是否需要安装一些 npm 包以确保我的应用程序在服务器上顺利运行?就像我在谷歌上搜索部署 nodejs 时一直在阅读有关 PM2 和 nginx 的信息。那么它们有什么好处呢?

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

Angular 版本 7

节点版本 8.11.3

Ubuntu 16.04

【问题讨论】:

这个问题太宽泛了,不适合SO。 Angular 是一个框架并且是客户端,您将橘子与苹果进行比较。 Node 不需要这些。只需上传您的项目(node_modules 除外)并在服务器上运行npm i就像我在谷歌上搜索部署 nodejs 时一直在阅读有关 PM2 和 Nginx 的信息。那么它们有什么好处呢? - 您可能会在生产中需要它们。我建议继续阅读,这不是可以简单解释的东西。了解它们真正用途的一个好方法是尝试在没有它们的情况下设置 Web 服务器。 @estus 节点项目的大小呢?有什么方法可以缩小它,或者我必须按原样发布完整的项目(节点模块除外)? PM2 用于在服务器上运行您的应用程序,而无需您每次都手动启动/杀死它们,Nginx 用于提供静态文件并将 localhost:3000 网络服务器绑定到 yourdomain.com:80。关于大小,如果你真的不受磁盘空间的限制,你可以照原样复制,否则你可以尝试剥离一些生产中不需要的东西。 @estus 所以 PM2 类似于永远? 是的。它更先进。 【参考方案1】:

您可以按原样部署代码,它会工作!

您不需要缩小代码。 VM 足够快以运行它。缩小通常是为了在将文件从服务器发送到客户端时减小文件的大小,并且由于您不发送任何文件,因此您不必担心。

我推荐PM2 在您达到生产状态后管理节点进程。它包括日志、自动重启和许多很酷的功能,可以帮助您。

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

如果您关注The Twelve Factors,那么还要为生产专用凭据创建一个环境文件。

为了完整起见,如果您使用 Babel/Typescript 或任何其他类似的工具,那么您确实需要将项目转换为 Node 可以理解的 javascript 代码。运行相应的命令以生成生产版本。

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

【讨论】:

您能否推荐一些可能有用的 Nginx 文章或视频教程?【参考方案2】:

安装 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

nodejs 包包含 nodejs 二进制文件以及 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 应用程序,它只向任何 HTTP 请求返回“Hello World”。这是一个示例应用程序,可帮助您设置 Node.js,您可以将其替换为您自己的应用程序 - 只需确保修改您的应用程序以侦听适当的 IP 地址和端口。

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

$ cd ~
$ nano hello.js

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

你好.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,一个用于安装 Node.js 的 Node 模块的包管理器,在我们的服务器上安装 PM2。使用此命令安装 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 │ 0       │ 0s     │ 21.566 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app

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

如果应用程序崩溃或被杀死,在 PM2 下运行的应用程序将自动重新启动,但需要采取额外的步骤以使应用程序在系统启动(启动或重新启动)时启动。幸运的是,PM2 提供了一种简单的方法来执行此操作,即启动子命令。

startup 子命令生成并配置启动脚本以在服务器启动时启动 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:使用服务、单元和日志。

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

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

$ pm2 stop app_name_or_id

使用此命令重新启动应用程序(指定 PM2 应用程序名称或 id):

$ pm2 restart app_name_or_id

PM2当前管理的应用列表也可以通过list子命令查询:

$ pm2 list

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

$ pm2 info example

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

$ pm2 monit

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

将 Nginx 设置为反向代理服务器 现在您的应用程序正在运行,并在 localhost 上进行侦听,您需要为您的用户设置一种访问它的方式。为此,我们将设置 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/ 会将请求发送到 hello.js,监听 localhost 的 8080 端口。

您可以向同一服务器块添加其他位置块,以提供对同一服务器上其他应用程序的访问。例如,如果您还在端口 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 地址或域名)来尝试一下。

结论 恭喜!现在,您的 Node.js 应用程序在 Ubuntu 16.04 服务器上的 Nginx 反向代理后面运行。这种反向代理设置足够灵活,可以让您的用户访问您想要共享的其他应用程序或静态 Web 内容。祝您的 Node.js 开发顺利!

我还找到了这个帮助视频:https://www.youtube.com/watch?v=Jsmeh7q9Qv4

【讨论】:

以上是关于如何为生产准备 nodejs?的主要内容,如果未能解决你的问题,请参考以下文章

如何为生产者设置路由键

如何为 AWS Glue 生产 Python 脚本?

NextJS:如何为生产构建添加屏幕加载?

如何为生产和开发环境 iOS 设置不同的证书和配置文件?

如何为 Kafka 生产者配置日志记录?

如何为生产模式c# wpf创建连接字符串[重复]