Express 教程第 7 部分:部署到生产环境

现在您已经创建(并测试)了一个很棒的 LocalLibrary 网站,您将希望将其安装到公共 Web 服务器上,以便图书馆工作人员和成员可以通过互联网访问。本文概述了如何找到主机来部署您的网站,以及为了使您的网站准备好投入生产,您需要做些什么。

先决条件 完成所有之前的教程主题,包括 Express 教程第 6 部分:使用表单.
目标 了解在哪里以及如何将 Express 应用程序部署到生产环境。

概述

网站完成后(或完成“足够”以开始公开测试),您需要将其托管在比您的个人开发计算机更公开、更易于访问的地方。

到目前为止,您一直在 开发环境 中工作,使用 Express/Node 作为 Web 服务器将您的网站共享到本地浏览器/网络,并使用(不安全)开发设置运行您的网站,这些设置会暴露调试和其他私有信息。在您可以在外部托管网站之前,您首先需要

  • 选择一个环境来托管 Express 应用程序。
  • 对您的项目设置进行一些更改。
  • 为您的网站设置生产级基础设施。

本教程提供了有关选择托管网站的选项的一些指导,简要概述了为使您的 Express 应用程序准备好投入生产而需要做的事情,以及将 LocalLibrary 网站安装到 Railway 云托管服务的示例。

什么是生产环境?

生产环境是由您将在其中运行您的网站以供外部使用​​的服务器计算机提供的环境。该环境包括

  • 运行网站的计算机硬件。
  • 操作系统(例如 Linux 或 Windows)。
  • 在您的网站编写之上的编程语言运行时和框架库。
  • Web 服务器基础设施,可能包括 Web 服务器、反向代理、负载均衡器等。
  • 您的网站依赖的数据库。

服务器计算机可以位于您的场所,并通过快速链接连接到互联网,但更常见的是使用托管在“云”中的计算机。这实际上意味着您的代码在托管公司数据中心中的一些远程计算机(或可能是“虚拟”计算机)上运行。远程服务器通常会以一定的价格提供一些保证的计算资源级别(例如 CPU、RAM、存储内存等)和互联网连接。

这种远程可访问的计算/网络硬件被称为基础设施即服务 (IaaS)。许多 IaaS 供应商提供在您必须安装生产环境其他组件的选项,以预安装特定操作系统。其他供应商允许您选择功能更全面的环境,可能包括完整的 Node 设置。

注意: 预构建的环境可以使您的网站设置变得非常容易,因为它们减少了配置,但可用的选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的 OS。通常,最好自己安装组件,以便您获得所需的组件,以及当您需要升级系统的一部分时,您会知道从哪里开始!

其他托管提供商支持 Express 作为平台即服务 (PaaS) 产品的一部分。使用这种类型的托管时,您无需担心大多数生产环境(服务器、负载均衡器等),因为主机平台会为您处理这些问题。这使得部署非常容易,因为您只需要专注于您的 Web 应用程序,而无需任何其他服务器基础设施。

一些开发人员会选择 IaaS 提供的更高灵活性而不是 PaaS,而另一些开发人员会欣赏 PaaS 降低的维护开销和更轻松的扩展。在您入门时,在 PaaS 系统上设置您的网站要容易得多,所以这就是我们将在本教程中所做的。

注意: 如果您选择一个 Node/Express 友好的托管提供商,他们应该提供有关如何使用不同配置的 Web 服务器、应用程序服务器、反向代理等来设置 Express 网站的说明。例如,在 Digital Ocean Node 社区文档 中有许多针对各种配置的分步指南。

选择托管提供商

有许多托管提供商被认为是积极支持或与Node(和Express)配合得很好。这些供应商提供不同类型的环境(IaaS、PaaS)以及不同价格的不同级别计算和网络资源。

注意: 托管解决方案很多,它们的服务和定价会随着时间的推移而变化。虽然我们在下面介绍了一些选项,但值得在选择托管提供商之前查看这些选项和其他选项。

选择主机时需要考虑的一些事项

  • 您的网站可能有多忙以及满足该需求所需的​​数据和计算资源的成本。
  • 水平扩展(添加更多机器)和垂直扩展(升级到更强大的机器)的支持级别以及这样做的成本。
  • 供应商拥有数据中心的位置,以及访问速度最快的位置。
  • 主机历史上的正常运行时间和停机时间表现。
  • 用于管理网站的工具——它们是否易于使用以及它们是否安全(例如 SFTP 与 FTP)。
  • 用于监控您的服务器的内置框架。
  • 已知限制。一些主机会故意阻止某些服务(例如电子邮件)。其他主机只在某些价格等级中提供一定数量的“实时”时间,或者只提供少量存储空间。
  • 其他好处。一些提供商将提供免费的域名和对 TLS 证书的支持,否则您需要付费才能获得这些证书。
  • 您所依赖的“免费”等级是否会随着时间的推移而过期,以及迁移到更昂贵等级的成本是否意味着您一开始就应该使用其他服务!

好消息是,当您入门时,有相当多的网站提供旨在用于评估和测试的“免费”计算环境。这些通常是资源相当有限的/有限的环境,您需要意识到它们可能会在某些介绍期后过期或具有其他限制。然而,它们非常适合在托管环境中测试低流量网站,并且可以在您的网站变得更繁忙时提供轻松的迁移到付费更多资源。

大多数提供商还提供一个“基本”或“爱好”等级,旨在用于小型生产网站,并提供更有用的计算能力级别和更少的限制。RailwayHerokuDigital OceanPython Anywhere 是拥有相对便宜的基本计算等级(在每月 5 美元到 10 美元之间)的流行托管提供商的示例。

注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,您可能会发现可扩展性是最重要的考虑因素。

准备好您的网站以发布

在发布网站时要考虑的主要事项是 Web 安全性和性能。至少,您将希望修改数据库配置,以便您可以使用不同的数据库进行生产并保护其凭据,删除在开发期间错误页面上包含的堆栈跟踪,整理您的日志,并设置适当的标头以避免许多常见的安全威胁。

在以下小节中,我们概述了您应该对您的应用程序进行的最重要的更改。

注意: Express 文档中还有其他有用的提示——请参阅 生产最佳实践:性能和可靠性生产最佳实践:安全.

数据库配置

到目前为止,在本教程中,我们已经使用了一个开发数据库,其地址和凭据硬编码到 app.js 中。由于开发数据库不包含我们不介意被公开或损坏的任何信息,因此泄露这些详细信息没有特别风险。但是,如果您使用的是真实数据,尤其是个人用户的信息,那么保护您的数据库凭据非常重要。

因此,我们希望为生产使用与开发中不同的数据库,并将生产数据库凭据与源代码分开,以便可以妥善保护它们。

如果您的托管提供商支持通过 Web 界面设置环境变量(就像许多提供商一样),那么一种方法是让服务器从环境变量中获取数据库 URL。下面,我们修改 LocalLibrary 网站以从名为 MONGODB_URI 的环境变量中获取数据库 URI(如果已设置,请使用您自己的数据库 URL 而不是下面的占位符)。

打开 app.js 并找到设置 MongoDB 连接变量的行。它看起来像这样

js
const mongoDB =
  "mongodb+srv://your_user_name:[email protected]/local_library?retryWrites=true&w=majority";

用以下代码替换该行,该代码使用 process.env.MONGODB_URI 从名为 MONGODB_URI 的环境变量中获取连接字符串(如果已设置,请使用您自己的数据库 URL 而不是下面的占位符)。

js
// Set up mongoose connection
const mongoose = require("mongoose");
mongoose.set("strictQuery", false);

const dev_db_url =
  "mongodb+srv://your_user_name:[email protected]/local_library?retryWrites=true&w=majority";
const mongoDB = process.env.MONGODB_URI || dev_db_url;

main().catch((err) => console.log(err));
async function main() {
  await mongoose.connect(mongoDB);
}

注意: 另一种常见的将生产数据库凭据与源代码分开的方法是从一个单独部署到文件系统中的 .env 文件中读取它们(例如,它们可能使用 npm dotenv 模块读取)。

将 NODE_ENV 设置为“production”

我们可以通过将 NODE_ENV 环境变量设置为 production 来删除错误页面中的堆栈跟踪(默认情况下它设置为“development”)。除了生成不太详细的错误消息外,将变量设置为 production 还会缓存从 CSS 扩展生成的视图模板和 CSS 文件。测试表明,将 NODE_ENV 设置为 production 可以将应用程序性能提高三倍!

此更改可以通过使用 export、环境文件或 OS 初始化系统来完成。

注意: 这实际上是您在环境设置而不是您的应用程序中进行的更改,但在这里值得注意!我们将在下面展示如何在我们的托管示例中设置它。

适当地记录

日志记录调用会对高流量网站产生影响。在生产环境中,您可能需要记录网站活动(例如跟踪流量或记录 API 调用),但您应该尝试将为调试目的添加的日志记录量降至最低。

在生产中减少“调试”日志记录的一种方法是使用类似 debug 的模块,该模块允许您通过设置环境变量来控制执行哪些日志记录。例如,下面的代码片段展示了如何设置“author”日志记录。调试变量以“author”命名,并且对于来自此对象的 所有日志,将自动显示前缀“author”。

js
const debug = require("debug")("author");

// Display Author update form on GET.
exports.author_update_get = asyncHandler(async (req, res, next) => {
  const author = await Author.findById(req.params.id).exec();
  if (author === null) {
    // No results.
    debug(`id not found on update: ${req.params.id}`);
    const err = new Error("Author not found");
    err.status = 404;
    return next(err);
  }

  res.render("author_form", { title: "Update Author", author: author });
});

然后,您可以通过在 DEBUG 环境变量中指定它们作为逗号分隔列表来启用特定的一组日志。您可以按照所示设置显示作者和图书日志的变量(也支持通配符)。

bash
#Windows
set DEBUG=author,book

#Linux
export DEBUG="author,book"

注意:debug 的调用可以替换以前使用 console.log()console.error() 进行的日志记录。将代码中的任何 console.log() 调用替换为通过 debug 模块进行日志记录。通过设置 DEBUG 变量来打开和关闭开发环境中的日志记录,并观察这对日志记录的影响。

如果需要记录网站活动,可以使用 WinstonBunyan 等日志记录库。有关此主题的更多信息,请参见:生产最佳实践:性能和可靠性

对响应使用 gzip/deflate 压缩

Web 服务器通常可以压缩发送回客户端的 HTTP 响应,从而显着减少客户端获取和加载页面所需的时间。使用的压缩方法将取决于客户端在请求中声明支持的解压缩方法(如果客户端不支持任何压缩方法,则响应将以未压缩形式发送)。

使用 compression 中间件将此添加到您的网站。通过运行以下命令在项目的根目录下安装它。

bash
npm install compression

打开 ./app.js 并按所示要求压缩库。使用 use() 方法将压缩库添加到中间件链(这应该出现在您希望压缩的任何路由之前——在本例中,是所有路由!)。

js
const catalogRouter = require("./routes/catalog"); // Import routes for "catalog" area of site
const compression = require("compression");

// Create the Express application object
const app = express();

// …

app.use(compression()); // Compress all routes

app.use(express.static(path.join(__dirname, "public")));

app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/catalog", catalogRouter); // Add catalog routes to middleware chain.

// …

注意: 对于生产环境中的高流量网站,您不会使用此中间件。相反,您应该使用 Nginx 等反向代理。

使用 Helmet 防御已知漏洞

Helmet 是一个中间件包。它可以设置适当的 HTTP 头,帮助保护您的应用程序免受众所周知的 Web 漏洞(有关它设置的标头和它防御的漏洞的更多信息,请参见 文档)。

通过运行以下命令在项目的根目录下安装它。

bash
npm install helmet

打开 ./app.js 并按所示要求 helmet 库。然后使用 use() 方法将模块添加到中间件链。

js
const compression = require("compression");
const helmet = require("helmet");

// Create the Express application object
const app = express();

// Add helmet to the middleware chain.
// Set CSP headers to allow our Bootstrap and Jquery to be served
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      "script-src": ["'self'", "code.jquery.com", "cdn.jsdelivr.net"],
    },
  }),
);

// …

我们通常可能只插入 app.use(helmet()); 来添加对大多数网站有意义的安全相关标头的 子集。但是,在 LocalLibrary 基础模板 中,我们包含了一些 Bootstrap 和 jQuery 脚本。这些脚本违反了 helmet 的 默认 内容安全策略 (CSP),该策略不允许加载跨站点脚本。为了允许加载这些脚本,我们修改了 helmet 配置,以便它设置 CSP 指令以允许从指示的域加载脚本。对于您自己的服务器,您可以通过遵循 此处使用 helmet 的说明,根据需要添加/禁用特定标头。

向 API 路由添加速率限制

Express-rate-limit 是一个中间件包,可用于限制对 API 和端点的重复请求。造成对您的网站进行过多请求的原因有很多,例如拒绝服务攻击、暴力破解攻击,甚至仅仅是行为异常的客户端或脚本。除了由于过多请求导致服务器速度变慢而可能出现的性能问题外,您还可能因额外流量而被收费。此包可用于限制可以对特定路由或一组路由发出的请求数量。

通过运行以下命令在项目的根目录下安装它。

bash
npm install express-rate-limit

打开 ./app.js 并按所示要求 express-rate-limit 库。然后使用 use() 方法将模块添加到中间件链。

js
const compression = require("compression");
const helmet = require("helmet");

const app = express();

// Set up rate limiter: maximum of twenty requests per minute
const RateLimit = require("express-rate-limit");
const limiter = RateLimit({
  windowMs: 1 * 60 * 1000, // 1 minute
  max: 20,
});
// Apply rate limiter to all requests
app.use(limiter);

// …

上面的命令将所有请求限制为每分钟 20 次(您可以根据需要更改此值)。

注意: 如果您需要更高级的保护措施以防御拒绝服务或其他类型的攻击,也可以使用 Cloudflare 等第三方服务。

设置节点版本

对于包括 Express 在内的节点应用程序,package.json 文件包含托管提供商确定应用程序依赖项和入口点文件所需的一切。

我们当前 package.json 中唯一缺少的重要信息是库所需的节点版本。您可以通过输入以下命令找到用于开发的节点版本。

bash
>node --version
v16.17.1

打开 package.json,并按所示添加此信息作为 engines > node(使用系统上的版本号)。

json
  "engines": {
    "node": ">=16.17.1"
  },

托管服务可能不支持指定的特定节点版本,但此更改应确保它尝试使用具有相同主要版本号的版本,或更新的版本。

请注意,可能还有其他方法在不同的托管服务上指定节点版本,但 package.json 方法得到广泛支持。

获取依赖项并重新测试

在我们继续之前,让我们再次测试网站,并确保它没有受到我们所做的任何更改的影响。

首先,我们需要获取我们的依赖项。您可以在项目的根目录下在终端中运行以下命令来执行此操作。

bash
npm install

现在运行网站(有关相关命令,请参见 测试路由),并检查网站是否按预期运行。

在 GitHub 中创建应用程序存储库

许多托管服务允许您从本地存储库或从基于云的源版本控制平台导入和/或同步项目。这可以使部署和迭代开发变得更加容易。

在本教程中,我们将为库设置一个 GitHub 帐户和存储库,并使用 git 工具上传源代码。

注意: 如果您已经使用 GitHub 管理源代码,则可以跳过此步骤!

请注意,使用源代码管理工具是一种良好的软件开发实践,因为它允许您试用更改,并在需要时在实验和“已知良好代码”之间切换!

步骤如下

  1. 访问 https://github.com/ 并创建一个帐户。
  2. 登录后,单击顶层工具栏中的 + 链接,然后选择 新建存储库
  3. 填写此表单中的所有字段。虽然这些字段不是强制性的,但强烈建议填写。
    • 输入一个新的存储库名称(例如 express-locallibrary-tutorial)和描述(例如“使用 Express(Node)编写的 Local Library 网站”)。
    • 添加 .gitignore 选择列表中选择 Node
    • 添加许可证 选择列表中选择您喜欢的许可证。
    • 选中 使用 README 初始化此存储库

    警告: 默认的“公开”访问权限将使 所有 源代码(包括您的数据库用户名和密码)对互联网上的任何人可见!确保源代码 从环境变量中读取凭据,并且没有任何硬编码的凭据。

    否则,选择“私有”选项,仅允许选定的人员查看源代码。

  4. 创建存储库
  5. 单击新存储库页面上的绿色 克隆或下载 按钮。
  6. 从出现在对话框中的文本字段中复制 URL 值。如果您使用了存储库名称“express-locallibrary-tutorial”,则 URL 应类似于:https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git

现在存储库 (“repo”) 已在 GitHub 上创建,我们要将其克隆(复制)到我们的本地计算机。

  1. 为您的本地计算机安装 git(您可以在 此处 找到不同平台的版本)。
  2. 打开命令提示符/终端,并使用上面复制的 URL 克隆您的存储库。
    bash
    git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git
    
    这将在当前目录中创建存储库。
  3. 导航到存储库文件夹。
    bash
    cd express-locallibrary-tutorial
    

然后将您的应用程序源文件复制到存储库文件夹中,使用 git 将它们作为存储库的一部分,并将它们上传到 GitHub。

  1. 将您的 Express 应用程序复制到此文件夹(不包括 /node_modules,它包含您需要从 npm 获取的依赖项文件)。
  2. 打开命令提示符/终端,并使用 add 命令将所有文件添加到 git。
    bash
    git add -A
    
  3. 使用 status 命令检查您即将 commit 的所有文件是否正确(您要包含源文件,而不是二进制文件、临时文件等)。它应该看起来有点像下面的列表。
    bash
    git status
    
    On branch main
    Your branch is up-to-date with 'origin/main'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            new file:   ...
    
  4. 满意后,将文件 commit 到您的本地存储库。这相当于在更改上签字,并将它们作为本地存储库的正式组成部分。
    bash
    git commit -m "First version of application moved into GitHub"
    
  5. 此时,远程存储库尚未更改。最后一步是使用以下命令将您的本地存储库同步(push)到远程 GitHub 存储库。
    bash
    git push origin main
    

此操作完成后,您应该能够返回到您在 GitHub 上创建存储库的页面,刷新页面,并看到您的整个应用程序现在已上传。您可以使用此添加/提交/推送循环来继续更新存储库,因为文件会发生变化。

这是一个备份您的“普通”项目的最佳时机——虽然我们在以下部分中将要进行的一些更改可能对任何托管服务(或开发)上的部署有用,但其他更改可能没有用。您可以使用命令行上的 git 执行此操作。

bash
# Create branch vanilla_deployment from the current branch (main)
git checkout -b vanilla_deployment

# Push the new branch to GitHub
git push origin vanilla_deployment

# Switch back to main
git checkout main

# Make any further changes in a new branch
git pull upstream main # Merge the latest changes from GitHub
git checkout -b my_changes # Create a new branch

注意: Git 功能强大无比!要了解更多信息,请参见 学习 Git

示例:在 Glitch 上托管

本节提供了一个关于如何在 Glitch 上托管 LocalLibrary 的实用演示。

为什么要选择 Glitch?

我们选择使用 Glitch 的原因有很多。

  • Glitch 提供 免费入门计划,该计划是 真正 免费的,尽管有一些限制。它对所有开发人员来说都负担得起,这一点对于 MDN 来说非常重要!
  • Glitch 会处理基础设施,因此您无需操心。不必担心服务器、负载均衡器、反向代理等等,这使得入门变得容易得多。
  • 您在使用 Glitch 时将学习的技能和概念是可迁移的。
  • 服务和计划限制对我们使用 Glitch 进行教程没有太大影响。例如
    • 入门计划每月仅提供 1000 个“项目小时”,该时间每月重置。当您正在积极编辑网站或有人访问网站时,就会使用它。如果没有人访问或编辑网站,它将进入睡眠状态。
    • 入门计划环境的容器 RAM 和存储空间有限。对于本教程来说已经足够了,特别是考虑到我们的数据库托管在其他地方。
    • 自定义域不受良好支持(截至撰写本文时)。
    • 您可以在 Glitch 技术限制页面 中找到其他限制。

虽然 Glitch 适用于托管此演示,但您应该花时间确定它是否适合您自己的网站

Glitch 如何工作?

Glitch 提供了一个基于 Web 的界面,您可以在其中从入门模板创建项目,或从 GitHub 导入项目,然后添加和编辑项目文件。当您进行更改时,项目将在其自己的隔离且独立的虚拟化容器中构建和运行。

所有这些是如何“在幕后”工作的,这是一个谜——Glitch 没有说明。很明显,只要您创建一个相当标准的 nodejs web 应用程序(例如,使用package.json 来管理依赖项),并且不会消耗超过技术限制中列出的资源,您的应用程序应该“正常工作”。

应用程序运行后,可以使用私有数据(在.env 文件中提供)进行生产配置。秘密数据中的值由应用程序以环境变量的形式读取,正如您在上一节中所了解的那样,这就是我们配置应用程序以获取数据库 URL 的方式。请注意,这些变量是秘密的.env 不应包含在您的 GitHub 存储库中。

Glitch 编辑视图还提供对 Web 应用程序环境的终端访问,您可以使用它来处理 Web 应用程序,就好像它在您的本地机器上运行一样。

这只是您入门所需的所有概述。接下来,我们将设置一个 Glitch 帐户,从 GitHub 上传 Library 项目,并将其连接到数据库。

获取 Glitch 帐户

要开始使用 Glitch,您首先需要创建一个帐户

  • 访问glitch.com,并点击顶部的工具栏中的注册按钮。
  • 在弹出窗口中选择 GitHub,使用您的 GitHub 凭据注册。
  • 然后您将登录到 Glitch 仪表盘:https://glitch.com/dashboard

Node.js 版本故障排除

托管提供商通常支持某些最近发布的 Node.js 版本的主要版本。如果您的package.json 文件中指定的精确“次要”版本不受支持,它们通常会回退到它们支持的最近版本(而且通常这会正常工作)。

不幸的是,在撰写本文时,Glitch 上支持的最高版本是 Node.js 16。如果您一直使用 Node.js 17 或更高版本进行开发,则应降低package.json 文件中使用的版本,如所示。您还需要重新测试

json
  "engines": {
    "node": ">=v16"
  },

Glitch计划在未来更新 node 并使其保持更好的更新状态——当您阅读本文时,版本限制可能已经不存在。您可以上传您的项目以查看它是否可以构建,而不是降级node 版本。如果出现错误并且您的应用程序未加载,则应尝试在 Glitch 编辑器中将package.json 中的node 版本设置为>=v16

注意:您还可以通过在任何 Glitch 项目的终端中输入以下命令来检查支持的版本

shell
ls -l /opt/nvm/versions/node | grep '^d' | awk '{ print $9 }'

从 GitHub 部署到 Glitch

接下来,我们将从 GitHub 导入 Library 项目。首先从网站顶部菜单中选择仪表盘选项,然后选择新建项目按钮。Glitch 将显示新项目的选项列表;选择从 GitHub 导入

Glitch website dashboard showing a new project button and a popup menu with "Import from GitHub" option

将出现一个弹出窗口。在弹出窗口中输入您的 GitHub 库存储库的 URL,然后按确定。下面,我们输入了已完成项目的存储库。

Glitch popup for entering URL of GitHub repo to import

然后,Glitch 将导入项目,并显示进度通知。完成后,它将显示新项目的编辑视图,如下所示。

Glitch editor view for imported project

您可以通过选择分享按钮来获取实时站点 URL。

Glitch editor view for imported project

打开一个新的浏览器选项卡,并将实时站点的链接复制到地址栏中。本地图书馆网站应打开并显示来自开发数据库的数据。

注意:此过程是从 GitHub 进行的一次性导入。您还可以使用 GitHub 操作(例如glitch-project-sync)来保持 Glitch 和您的项目同步。

使用生产 MongoDB 数据库

您应该为生产设置一个与开发不同的数据库。虽然 Glitch 仅托管 SQLite 数据库(并且我们已设置为使用 MongoDB),但许多其他站点提供 MongoDB 数据库即服务。

一种选择是按照教程前面部分中的设置 MongoDB 数据库说明来设置一个新的生产数据库。

要使生产数据库可供库应用程序访问,请在项目的编辑视图中打开.env 文件。输入数据库 URL 变量MONGODB_URI 和生产数据库的 URL。当您在编辑器中输入值时,网站会更新。

Glitch .env file editor for private data with production variables

注意:我们没有创建此文件。它用于私有数据,并且在导入到 Glitch 时自动创建。它永远不会被导出或复制。

其他配置变量

您会记得,在上一节中,我们需要将 NODE_ENV 设置为“production”才能提高性能并生成更少的详细错误消息。我们在设置MONGODB_URI 变量的同一文件中执行此操作。

打开.env 并添加一个值为productionNODE_ENV 变量(请参阅上一节中的屏幕截图)。

本地库应用程序现在已设置并配置为生产使用。您可以通过网站界面添加数据,它应该像开发期间那样工作(尽管对于无效页面,公开的调试信息更少)。

注意:如果您只想添加一些测试数据,可以使用populatedb 脚本(使用您的 MongoDB 生产数据库 URL),如Express 教程第 3 部分:使用数据库(使用 Mongoose)测试——创建一些项目部分所述。

在 Glitch 上调试 Express 应用程序

Glitch 允许有效地进行调试。您可以做的一些事情包括

  • 选择编辑视图底部的日志按钮以查看来自服务器的日志信息,例如控制台日志输出。
  • 选择编辑视图底部的终端按钮以在托管环境中打开终端。您可以使用它在环境中运行命令和工具。例如,您可能使用node -v 来检查 node 版本。
  • 使用GLITCH 扩展 for VSCode 在 VSCode 中进行交互式调试。

示例:在 Railway 上托管

本节提供了在Railway 上安装LocalLibrary 的实用演示。

为什么选择 Railway?

警告:Railway 不再拥有完全免费的入门层。我们保留了这些说明,因为 Railway 有一些很棒的功能,对于某些用户来说将是一个更好的选择。

Railway 由于几个原因而成为一个有吸引力的托管选项

  • Railway 处理了大多数基础设施,因此您无需这样做。不必担心服务器、负载均衡器、反向代理等,可以更轻松地入门。
  • Railway专注于开发和部署的开发人员体验,这使得学习曲线比许多其他替代方案更快、更平滑。
  • 使用 Railway 时将学习的技能和概念是可以转化的。虽然 Railway 有一些出色的新功能,但其他流行的托管服务使用了许多相同的想法和方法。
  • Railway 文档清晰完整。
  • 该服务似乎非常可靠,如果您最终喜欢它,定价是可以预测的,并且扩展您的应用程序非常容易。

您应该花时间确定 Railway 是否适合您自己的网站

Railway 如何工作?

每个 Web 应用程序都在其自己的隔离且独立的虚拟化容器中运行。要执行您的应用程序,Railway 需要能够设置适当的环境和依赖项,并了解如何启动它。

Railway 使此操作变得容易,因为它可以根据“通用约定”的使用情况自动识别和安装许多不同的 Web 应用程序框架和环境。例如,Railway 识别 node 应用程序,因为它们具有package.json 文件,并且可以根据“锁定”文件确定用于构建的包管理器。例如,如果应用程序包含package-lock.json 文件,Railway 知道使用npm 来安装包,而如果它找到yarn.lock,它知道使用yarn。安装完所有依赖项后,Railway 将在包文件中查找名为“build”和“start”的脚本,并使用它们来构建和运行代码。

注意:Railway 使用Nixpacks 来识别用不同编程语言编写的各种 Web 应用程序框架。您不需要了解有关本教程的更多信息,但您可以在Nixpacks Node 中找到有关部署 node 应用程序的更多选项。

应用程序运行后,它可以使用环境变量中提供的信息进行配置。例如,使用数据库的应用程序必须使用变量获取地址。数据库服务本身可能由 Railway 或其他提供商托管。

开发人员通过 Railway 网站和使用特殊的命令行界面 (CLI) 工具与 Railway 交互。CLI 允许您将本地 GitHub 存储库与 railway 项目关联,将存储库从本地分支上传到实时站点,检查正在运行的进程的日志,设置和获取配置变量等等。其中一个最实用的功能是,您可以使用 CLI 在与实时项目相同的环境变量下运行本地项目。

这只是您将应用程序部署到 Railway 所需的所有概述。接下来,我们将设置一个 Railway 帐户,安装我们的网站和数据库,并试用 Railway 客户端。

获取 Railway 帐户

要开始使用 Railway,您首先需要创建一个帐户

  • 访问railway.app,并点击顶部的工具栏中的登录链接。
  • 在弹出窗口中选择 GitHub,使用您的 GitHub 凭据登录
  • 然后您可能需要访问您的电子邮件并验证您的帐户。
  • 然后您将登录到 Railway.app 仪表盘:https://railway.app/dashboard

从 GitHub 部署到 Railway

接下来,我们将设置 Railway 以从 GitHub 部署我们的库。首先从网站顶部菜单中选择仪表盘选项,然后选择新建项目按钮

Railway website dashboard showing new project button

Railway 将显示新项目的选项列表,包括从首先在您的 GitHub 帐户中创建的模板部署项目的选项,以及许多数据库。选择从 GitHub 存储库部署

Railway popup showing deployment options with Deploy from GitHub repo option highlighted

在设置过程中与 Railway 共享的 GitHub 仓库中的所有项目都将显示。选择你的 GitHub 仓库作为本地库:<user-name>/express-locallibrary-tutorial

Railway popup showing GitHub repos that can be deployed

选择**立即部署**确认你的部署。

Confirmation screen when you can select deployment of project

Railway 随后将加载并部署你的项目,在部署选项卡上显示进度。部署成功完成后,你将看到如下所示的屏幕。

Railway dashboard showing Deployments tab for the deployed project

现在选择*设置*选项卡,然后向下滚动到域名部分,并按下**生成域名**按钮。

Railway project settings tab showing button to generate a domain

这将发布网站并将域名替换按钮,如下所示。

Railway project settings tab showing a link to the local library site

选择域名 URL 打开你的库应用程序。注意,由于我们尚未指定生产数据库,本地库将使用你的开发数据打开。

配置并连接 MongoDB 数据库

接下来,让我们创建一个生产 MongoDB 数据库来替代使用我们的开发数据。我们将作为 Railway 应用程序项目的一部分创建数据库,尽管你可以在单独的项目中创建数据库,或者使用MongoDB Atlas数据库作为生产数据,就像你对开发数据库所做的那样。

在 Railway 上,从网站顶部的菜单中选择**仪表板**选项,然后选择你的应用程序项目。在此阶段,它仅包含一个用于应用程序的服务(可以选择此服务来设置变量和服务的其他详细信息)。选择**新建**按钮,用于将服务添加到当前项目。

Railway project with new service button highlighted

当提示添加服务的类型时,选择**数据库**。

Railway popup showing options for a new service, such as database, GitHub repo, empty service etc

然后选择**添加 MongoDB**开始添加数据库。

Railway popup showing different databases that can be selected: Postgres, MySQL, MongoDB and so on

Railway 随后将在同一项目中配置一个包含空数据库的服务。完成后,你将看到项目视图中的应用程序和数据库服务。

Railway project with application and database services

选择 MongoDB 服务以显示有关数据库的信息。打开*变量*选项卡并复制"Mongo_URL"(这是数据库的地址)。

Railway database settings screen showing the URL needed to connect to the database

为了使库应用程序能够访问此地址,我们需要使用环境变量将其添加到应用程序进程中。首先打开应用程序服务。然后选择*变量*选项卡并按下**新建变量**按钮。

输入变量名称MONGODB_URI和复制的数据库连接 URL(MONGODB_URI是环境变量的名称,我们已使用它配置应用程序以读取数据库地址)。这将类似于下面显示的屏幕。

Railway website variables screen while adding the MONGODB_URI variable and address

选择**添加**添加变量。

Railway 在更新变量时会重启你的应用程序。如果你现在检查主页,应该会看到对象计数为零,因为上面的更改意味着我们现在使用的是一个新的(空的)数据库。

其他配置变量

你将回忆起在前面部分中,我们需要将 NODE_ENV 设置为'production'以提高性能并生成更少的详细错误消息。我们可以在设置MONGODB_URI变量的同一屏幕中执行此操作。

打开应用程序服务。然后选择*变量*选项卡,你将看到MONGODB_URI已定义,并按下**新建变量**按钮。

Railway variables tab with the New Variable button highlighted

输入NODE_ENV作为新变量的名称,输入production作为环境的名称。然后按下**添加**按钮。

Railway variables tab with new NODE_ENV variable being set to 'production'

本地库应用程序现已设置并配置为生产使用。你可以通过网站界面添加数据,它应该像开发期间一样工作(尽管对于无效页面显示的调试信息更少)。

**注意:**如果你只想添加一些数据进行测试,你可以使用populatedb脚本(使用你的 MongoDB 生产数据库 URL),如部分Express 教程第 3 部分:使用数据库(使用 Mongoose)测试 - 创建一些项目中所述。

安装客户端

按照此处说明下载并安装适用于本地操作系统的 Railway 客户端。

客户端安装完成后,你将能够运行命令。一些更重要的操作包括将计算机的当前目录部署到关联的 Railway 项目(无需上传到 GitHub),以及在生产服务器上使用相同设置在本地运行项目。

你可以在终端中输入以下内容以获取所有可能命令的列表。

bash
railway help

调试

Railway 客户端提供 logs 命令以显示日志尾部(每个项目的网站上提供了更完整的日志)

bash
railway logs

总结

这是关于在生产环境中设置 Express 应用程序以及使用 Express 的一系列教程的结束。我们希望你发现它们有用。你可以在此处在 GitHub 上查看源代码的完整实现版本

另请参阅