From 0e98f24f5453a236f1ffcdd9b1c707f0fd4346db Mon Sep 17 00:00:00 2001 From: jackymao Date: Fri, 19 Jul 2024 18:59:11 +0800 Subject: [PATCH 1/2] update part3b.md to catch up with the latest en version --- src/content/0/zh/part0a.md | 2 +- src/content/3/zh/part3b.md | 166 ++++++++++++++++++------------------- 2 files changed, 83 insertions(+), 85 deletions(-) diff --git a/src/content/0/zh/part0a.md b/src/content/0/zh/part0a.md index e2c7ab07a38..a691b08d044 100644 --- a/src/content/0/zh/part0a.md +++ b/src/content/0/zh/part0a.md @@ -576,6 +576,6 @@ lang: zh 在教学内容的每一部分底部,都有一个链接 提出对材料的修改。您可以通过点击该链接编辑页面的源代码。 -也有很多扩展材料的链接。如果你发现链接已经失效(这种情况时长发生...),如果你找不到替换的链接,请提出修改或者在 Discord 上@我们。 +也有很多扩展材料的链接。如果你发现链接已经失效(这种情况时常发生...),如果你找不到替换的链接,请提出修改或者在 Discord 上@我们。 diff --git a/src/content/3/zh/part3b.md b/src/content/3/zh/part3b.md index dbddd4675de..5d952f819af 100644 --- a/src/content/3/zh/part3b.md +++ b/src/content/3/zh/part3b.md @@ -89,8 +89,11 @@ const cors = require('cors') app.use(cors()) ``` - - 前端就可以工作了!然而,改变笔记重要性的功能还没有在后端实现。 + +**注:** 启用 cors 时,应考虑如何配置。就我们的应用程序而言,由于后端在生产环境中不会对公众可见,因此只从特定来源(如前端)启用 cors 可能更有意义。 + + +现在,前端的大部分功能都能正常工作了!更改备注重要性的功能尚未在后台实现,因此自然也无法在前台使用。我们稍后会解决这个问题。 你可以在[Mozilla 的页面](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)上了解更多关于 CORS 的信息。 @@ -126,20 +129,15 @@ React应用现在在浏览器中运行,从运行在localhost:3001上的node/ex 也有一些其他免费的托管选项可以很好地用于本课程,至少除了第11部分(CI/CD)可能会有一个棘手的练习外,其他部分都可以。 - -to describe their experiences: - -一些课程参与者也用了下面的话来描述他们的经历: + +一些课程参与者还使用了以下服务: - -- [铁路](https://railway.app/) -# Cyclic -[循环](https://www.cyclic.sh/) +[Cyclic](https://www.cyclic.sh/) -- [Replit](https://replit.com):[Replit](https://replit.com) +- [Replit](https://replit.com) -- [CodeSandBox](https://codesandbox.io):代码沙箱 +- [CodeSandBox](https://codesandbox.io) 如果你知道其他一些好用且易于使用的NodeJS托管服务,请告诉我们! @@ -159,7 +157,8 @@ app.listen(PORT, () => { #### Fly.io -Note that you may need to give your credit card number to Fly.io even if you are using only the free tier! There has been actually conflicting reports about this, it is known for a fact that some of the students in this course are using Fly.io without entering the credit card info. At the moment [Render](https://render.com/) can be used without a credit card. + +请注意,即使您只使用免费层,您也可能需要向 Fly.io 提供您的信用卡号!关于这一点的报道实际上是相互矛盾的,本课程的一些学生在使用 Fly.io 时没有输入信用卡信息。目前,[render](https://render.com/) 无需信用卡即可使用。 默认情况下,每个人都可以免费获得两台虚拟机,可以同时运行两个应用程序。 @@ -175,12 +174,6 @@ app.listen(PORT, () => { ```bash fly auth login ``` - -在 https://devcenter.heroku.com/ ,创建Heroku账户 - - 使用命令安装Heroku包:npm install -g heroku - - 用命令heroku create创建一个Heroku应用,将你的代码提交到版本库,并用命令git push heroku main将其移到Heroku。 如果你的机器上的 _fly_ 命令不起作用,你可以尝试更长的版本 _flyctl_。例如,在MacOS上,两种形式的命令都能正常工作。 @@ -191,28 +184,27 @@ fly auth login 在应用程序的根目录中运行以下命令可以初始化应用程序: ```bash -fly launch +fly launch --no-deploy ``` 给应用程序取一个名字,或者让Fly.io自动生成一个。选择一个运行应用程序的区域。不要为应用程序创建Postgres数据库,也不要创建Upstash Redis数据库,因为这些都不需要。 - - 前端也可以和Heroku的后端一起工作。你可以通过把前端的后端地址改为Heroku中的后端地址,而不是http://localhost:3001来检查。 - -飞行。io 在您的应用程序的根目录中创建一个文件fly.toml,其中配置了应用程序。 为了让应用程序正常运行,我们可能需要在配置的[env]部分做一些小的添加: +Fly.io 在您的应用程序的根目录中创建一个文件fly.toml,其中配置了应用程序。 为了让应用程序正常运行,我们可能需要在配置的[env]部分做一些小的添加: ```bash -[env] - PORT = "8080" # add this - -[experimental] - auto_rollback = true +[build] -[[services]] - http_checks = [] - internal_port = 8080 +[env] + PORT = "3000" # add this + +[http_service] + internal_port = 3000 # ensure that this is same as PORT + force_https = true + auto_stop_machines = true + auto_start_machines = true + min_machines_running = 0 processes = ["app"] ``` @@ -232,18 +224,14 @@ fly deploy 如果一切顺利,应用程序现在应该已经启动并运行了。你可以用 `python app.py` 命令在浏览器中打开它。 ```bash -fly open -``` - - -在初始设置之后,当应用程序代码更新后,可以使用命令部署到生产环境 - -```bash -fly deploy +fly apps open ``` -_飞行日志_ 是一个特别重要的命令。这个命令可以用来查看服务器日志。最好总是保持日志可见! +_fly logs_ 是一个特别重要的命令。这个命令可以用来查看服务器日志。最好总是保持日志可见! + + +**注意:** Fly 可能会为您的应用程序创建 2 台机器,如果创建了 2 台机器,您应用程序中的数据状态在不同请求之间就会不一致,也就是说,您会有 2 台机器,每台机器都有自己的备注变量,您可以 POST 到一台机器,然后下一次 GET 可能会转到另一台机器。你可以使用“$ fly scale show ”命令来检查机器数量,如果 COUNT 大于 1,你可以使用“$ fly scale count 1 ”命令将其强制为 1。也可以在 dashboard 上检查机器数量。 and does not produce any output, please try running it again with `--no-progress` added. @@ -258,19 +246,7 @@ flyctl ping -o personal 如果你的电脑出现无法连接Fly.io的情况,[这里](https://github.com/fullstack-hy2020/misc/blob/master/fly_io_problem.md)描述了可以尝试的一种方法。 -`ls -l` - -total 8 -drwxr-xr-x 2 root root 4096 May 15 10:10 test - 如果以下命令的输出看起来像这样: -`ls -l` - -total 8 -drwxr-xr-x 2 root root 4096 May 15 10:10 test - -总共 8 -drwxr-xr-x 2 root root 4096 May 15 10:10 test ```bash $ flyctl ping -o personal @@ -283,6 +259,13 @@ $ flyctl ping -o personal 如果没有连接问题,那就太好了! + +每次对应用程序进行更改,都可以使用如下命令将新版本带入生产环境 + +```bash +fly deploy +``` + #### Render @@ -342,14 +325,14 @@ app.listen(PORT, () => { 当应用程序部署时,我们必须创建[生产构建](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build)或优化用于生产的应用程序的版本。 - -使用create-react-app创建的应用程序的生产构建可以使用命令[npm run build](https://github.com/facebookincubator/create-react-app#npm-run-build-or-yarn-build)创建。 + +使用create-react-app创建的应用程序的生产构建可以使用命令[npm run build](https://vitejs.dev/guide/build.html)创建。 - - **注意:**在撰写本文时(2022年1月20日)create-react-app有一个错误,导致以下错误 _TypeError: MiniCssExtractPlugin不是一个构造函数_ 。 + +让我们在 [第 2 章节](/en/part2) 中开发的笔记前端项目的根目录中运行这条命令。 - -这将创建一个叫做build的目录(其中包含我们应用程序的唯一的HTML文件index.html),其中包含目录static。我们应用程序的JavaScript代码的[最小化]()版本将被生成在static目录中。尽管应用程序代码分布在多个文件中,但所有的JavaScript代码都将被最小化到一个文件中。所有来自应用程序依赖的代码也将被最小化到这个单一文件中。 + +这将创建一个叫做dist的目录(其中包含我们应用程序的唯一的HTML文件index.html)和目录assets。我们应用程序的JavaScript代码的[最小化]()版本将被生成在dist目录中。尽管应用程序代码分布在多个文件中,但所有的JavaScript代码都将被最小化到一个文件中。所有来自应用程序依赖的代码也将被最小化到这个单一文件中。 最小化的代码不是很容易阅读。代码的开头看起来像这样: @@ -360,14 +343,14 @@ app.listen(PORT, () => { ### Serving static files from the backend - -一种部署前端的选项是将生产构建(构建目录)复制到后端仓库的根目录,并配置后端将前端的主页(文件build/index.html)显示为其主页。 + +一种部署前端的选项是将生产构建(dist目录)复制到后端仓库的根目录,并配置后端将前端的主页(文件build/index.html)显示为其主页。 我们首先把前端的生产构建复制到后端的根目录下。在Mac或Linux电脑上,复制可以在前端目录下用命令完成 ```bash -cp -r build ../backend +cp -r dist ../backend ``` @@ -382,12 +365,10 @@ cp -r build ../backend 要使express展示静态内容,页面index.html和它获取的JavaScript等,我们需要express内置的中间件[static](http://expressjs.com/en/starter/static-files.html)。 -, - 当我们在中间件声明中添加以下内容时, ```js -app.use(express.static('build')) +app.use(express.static('dist')) ``` @@ -442,8 +423,6 @@ const getAll = () => { 文件包含指令来获取一个定义应用程序样式的CSS样式表,以及两个脚本标记,指示浏览器获取应用程序的JavaScript代码 - 实际的React应用程序。 -文件包含指令来获取一个定义应用程序样式的CSS样式表,以及两个脚本标签,指示浏览器获取应用程序的JavaScript代码 - 实际的React应用程序。 - React 代码从服务器地址获取笔记,并将它们渲染到屏幕上。服务器和浏览器之间的通信可以在开发者控制台的网络标签中看到: @@ -462,6 +441,9 @@ React 代码从服务器地址获取笔记, 确保应用程序的生产版本在本地正常运行后,将前端的生产构建提交到后端存储库,并将代码再次推送到GitHub。 + +**注*** 如果使用 Render,请确保后端 git 不会忽略 dist 目录。 + 如果你正在使用Render,推送到GitHub可能就足够了。如果自动部署不起作用,从Render仪表板中选择“手动部署”。 @@ -477,9 +459,13 @@ fly deploy 应用程序运行得很完美,只是我们还没有在后端添加改变笔记重要性的功能。 + +注意:使用 Fly.io 时,请注意项目目录中的 _.dockerignore_ 文件会列出部署过程中不会上传的文件。默认情况下包括 dist 目录。要部署这个目录,请从 .dockerignore 文件中移除它的引用,以确保你的应用程序能正确部署。 + ![screenshot of notes application](../../images/3/30new.png) -**NOTE:** changing of the importance DOES NOT work yet since the backend has no implementation for it yet. + +***注:** 更改重要度目前还不起作用,因为后台还没有实现该功能。 我们的应用程序将笔记保存到一个变量中。如果应用程序崩溃或重新启动,所有的数据都会消失。 @@ -493,7 +479,7 @@ fly deploy ![diagram of react app on heroku with a database](../../images/3/102.png) -现在节点/ express-backend位于Fly.io/Render服务器中。当访问根地址时,浏览器加载并执行从Fly.io/Render服务器获取json数据的React应用程序。 +现在 node/express-backend 位于 Fly.io/Render 服务器中。当访问根地址时,浏览器加载并执行从 Fly.io/Render 服务器获取 json 数据的 React 应用程序。 ### Streamlining deploying of the frontend @@ -520,8 +506,8 @@ fly deploy ##### Note for Windows users follows: - 注意,`build:ui` 中的标准shell命令不能在Windows中本地工作。Windows中的PowerShell工作方式不同,在这种情况下,脚本可以按照以下方式编写: + ```json "build:ui": "@powershell Remove-Item -Recurse -Force build && cd ../frontend && npm run build && @powershell Copy-Item build -Recurse ../backend", ``` @@ -579,7 +565,7 @@ npm config set script-shell "C:\\Program Files\\git\\bin\\bash.exe" ### Proxy - 前端的变化导致它在开发模式下不再工作(当用_npm start_命令启动时),因为与后端的连接不起作用。 +前端的变化导致它在开发模式下不再工作(当用_npm start_命令启动时),因为与后端的连接不起作用。 ![Network dev tools showing a 404 on getting notes](../../images/3/32new.png) @@ -591,25 +577,37 @@ const baseUrl = '/api/notes' ``` - 因为在开发模式下,前端的地址是localhost:3000,对后端的请求会进入错误的地址localhost:3000/api/notes。后端是在localhost:3001。 +因为在开发模式下,前端的地址是localhost:3000,对后端的请求会进入错误的地址localhost:3000/api/notes。后端是在localhost:3001。 - -如果项目是使用create-react-app创建的,解决这个问题就很容易。只需在前端仓库的package.json文件中添加以下声明即可。 + +如果项目是使用 Vite 创建的,解决这个问题就很容易。只需在前端仓库的vite.config.js文件中添加以下声明即可。 ```bash -{ - "dependencies": { - // ... - }, - "scripts": { - // ... +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + // highlight-start + server: { + proxy: { + '/api': { + target: 'http://localhost:3001', + changeOrigin: true, + }, + } }, - "proxy": "http://localhost:3001" // highlight-line -} + // highlight-end +}) + ``` - -重新启动后,React开发环境将作为[代理](https://create-react-app.dev/docs/proxying-api-requests-in-development/)工作。如果React代码向未由React应用程序本身管理的 服务器地址发出HTTP请求(即当请求不是关于获取应用程序的CSS或JavaScript时),则该请求将重定向到 服务器。 + +重新启动后,React开发环境将作为[代理](https://vitejs.dev/config/server-options.html#server-proxy)工作。如果React代码向未由React应用程序本身管理的 服务器地址发出HTTP请求(即当请求不是关于获取应用程序的CSS或JavaScript时),则该请求将重定向到 服务器。 + + +请注意,在上述 vite 配置中,只有指向以 /api 开头的路径的请求才会重定向到服务器。 现在前端也很好,无论是在开发模式还是生产模式下都能与服务器正常工作。 From c46c3ccb83095bc7a60662ce05bbd9a1b8608c40 Mon Sep 17 00:00:00 2001 From: jackymao Date: Mon, 22 Jul 2024 11:57:56 +0800 Subject: [PATCH 2/2] update part7d.md and part11c.md to catch up with the latest en version --- src/content/11/zh/part11c.md | 676 ++++++++++++----------------------- src/content/7/zh/part7d.md | 75 ++-- 2 files changed, 260 insertions(+), 491 deletions(-) diff --git a/src/content/11/zh/part11c.md b/src/content/11/zh/part11c.md index 27dded66daa..f766e2e8246 100644 --- a/src/content/11/zh/part11c.md +++ b/src/content/11/zh/part11c.md @@ -60,31 +60,47 @@ Fly.io 和 Render 至少比起许多其他类型的托管设置来说,发布 定义一个部署系统的明确规则或要求是很困难的,但我们还是尝试一下: -我们的部署系统应该能够在部署的**任何**一步优雅地失败。 +- 我们的部署系统应该能够在部署的**任何**一步优雅地失败。 -我们的部署系统**永远不应**使我们的软件处于损坏状态。 +- 我们的部署系统**永远不应**使我们的软件处于损坏状态。 -我们的部署系统应该让我们知道失败发生时。通知失败比通知成功更重要。 +- 我们的部署系统应该让我们知道失败发生时。通知失败比通知成功更重要。 -我们的部署系统应该允许我们回滚到以前的部署。 +- 我们的部署系统应该允许我们回滚到以前的部署。 -最好这个回滚比完整部署更容易实现,也更不容易出错。 + - 最好这个回滚比完整部署更容易实现,也更不容易出错。 -- 当然,最好的选择是在部署失败时自动回滚。 + - 当然,最好的选择是在部署失败时自动回滚。 -我们的部署系统应该处理用户在部署前/期间发出HTTP请求的情况。 +- 我们的部署系统应该处理用户在部署前/期间发出HTTP请求的情况。 -我们的部署系统应该确保我们部署的软件符合我们为此设定的要求(例如,如果没有运行测试,则不要部署)。 +- 我们的部署系统应该确保我们部署的软件符合我们为此设定的要求(例如,如果没有运行测试,则不要部署)。 让我们定义一些我们**想要**在这个假设的部署系统中的东西: -我们希望它能快速完成。 +- 我们希望它能快速完成。 -我们希望在部署期间没有停机时间(这与我们在部署之前/期间处理用户请求的要求是不同的)。 +- 我们希望在部署期间没有停机时间(这与我们在部署之前/期间处理用户请求的要求是不同的)。 - -接下来我们将有三组用于用GitHub Actions自动部署的练习,一个是[Fly.io](https://fly.io/),另一个是[Render](https://render.com/),最后是老牌[Heroku](https://heroku.com/)。部署过程总是特定于特定的云提供商,因此您也可以完成两个练习集,以便查看这些服务在部署方面的差异。 + +接下来我们将有两组用于用GitHub Actions自动部署的练习,一个是[Fly.io](https://fly.io/),另一个是[Render](https://render.com/)。部署过程总是特定于特定的云提供商,因此您也可以完成两个练习集,以便查看这些服务在部署方面的差异。 + + + +### Has the app been deployed? + + +由于我们没有对应用程序进行任何真正的更改,因此可能很难确定应用程序部署是否真的有效。 + + +让我们在应用程序中创建一个虚拟端点,这样就可以进行一些代码更改,并确保部署的版本确实发生了变化: + +```js +app.get('/version', (req, res) => { + res.send('1') // change this string to ensure a new version deployed +}) +``` @@ -92,16 +108,21 @@ Fly.io 和 Render 至少比起许多其他类型的托管设置来说,发布 ### Exercises 11.10-11.12. (Fly.io) - -在开始下面的练习之前,您应该在[Fly.io](https://fly.io/)托管服务中像我们在[第3章节](/en/part3/deploying_app_to_internet#application-to-the-internet)中所做的那样设置您的应用程序。 + +如果您更喜欢使用其他托管选项,[Render](http://localhost:8000/en/part11/deployment#exercises-11-10-11-12-render)有一套替代练习。 - -如果您更喜欢使用其他托管选项,[Render](http://localhost:8000/en/part11/deployment#exercises-11-10-11-12-render) 和 [Heroku](/en/part11/deployment#exercises-11-10-11-12-heroku) 均有一套替代练习。 +#### 11.10 Deploying your application to Fly.io + + +在 [Fly.io](https://fly.io/) 托管服务中安装应用程序,就像我们在 [part 3](/en/part3/deploying_app_to_internet#application-to-the-internet 所做的那样。) 相比起第三章节,我们不再自己部署代码到Fly.io上(使用命令flyctl deploy),我们让GitHub Actions工作流来帮我们完成! - + +在进行自动部署之前,我们应确保应用程序可以手动部署。 + + line 在Fly.io上创建一个新的应用,然后使用命令行生成Fly.io API令牌。 @@ -113,328 +134,246 @@ flyctl auth token 你很快就需要令牌来部署工作流程了! - + 在设置部署管道之前,让我们确保使用命令flyctl deploy可以进行手动部署。 - -首先,在文件package.json中定义要使用的Node版本,以匹配您的机器使用的版本。对我来说是16.19.1: - -```json -{ - // highlight-start - "engines": { - "node": "16.19.1" - }, - // highlight-end - "name": "fullstackopen-cicd", - "version": "1.0.0", - "description": "Full Stack Open", - // ... -} -``` + +需要做一些改动。 - -fly.toml 配置文件也应该被修改以包括以下内容: + +应修改配置文件 fly.toml 以包含以下内容: ```yml -[deploy] - release_command = "npm run build" +[env] + PORT = "3000" # add this where PORT matches the internal_port below [processes] - app = "node app.js" + app = "node app.js" # add this -[build] - [build.args] - NODE_VERSION = "16.19.1" +[http_service] + internal_port = 3000 + force_https = true + auto_stop_machines = true + auto_start_machines = true + min_machines_running = 0 + processes = ["app"] ``` - -除此之外,我们还应该将_webpack_从_devDependencies_移动到_dependencies_,因为我们的构建步骤需要它被安装。 - -```json -{ - // ... - "dependencies": { - "webpack": "^4.43.0", - } -} -``` - -release\_command 根据[部署](https://fly.io/docs/reference/configuration/)现在确保在启动应用程序之前完成生产构建。在[过程](https://fly.io/docs/reference/configuration/#the-processes-section)中,我们定义启动应用程序的命令。没有这些更改,Fly.io只会启动React开发服务器,这会导致它关闭,因为应用程序本身没有启动。 +### Exercises 11.10-11.12. (Fly.io) - -这里的应用程序指的是在[服务](https://fly.io/docs/reference/configuration/#the-services-sections)部分启动的应用程序过程: + +如果你想使用其他托管选项,还有一套 [Render] 的替代练习(/en/part11/deployment#exercises-11-10-11-12-render)。 -```yml -[[services]] - http_checks = [] - internal_port = 8080 - processes = ["app"] # highlight-line -``` #### 11.10 Deploying your application to Fly.io - -在开始这个练习之前,请确保使用命令 flyctl deploy 手动部署可以正常工作! - - -扩展工作流,按照[这里](https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/)给出的建议,添加一个步骤将应用部署到Fly.io。 + +在 [Fly.io](https://fly.io/) 托管服务中安装应用程序,就像我们在 [part 3](/en/part3/deploying_app_to_internet#application-to-the-internet 所做的那样。) - -你需要刚刚创建的用于部署的授权令牌。向GitHub Actions传递它的值的正确方法是使用存储库秘密: + +与 part3 不同,在这个部分我们 并不直接将代码部署 到 Fly.io (使用命令 flyctl deploy), 我们使用 Github Actions 工作流来为我们做到. -![repo secret](../../images/11/10f.png) - - -现在工作流程可以按如下方式访问令牌值: - -``` -${{secrets.FLY_API_TOKEN}} -``` - - -如果一切顺利,您的工作流日志应该看起来有点像这样: - -![](../../images/11/11.png) - - -of this guide, we can find the solution. - -你可以用浏览器试用这个应用,但很可能会遇到问题。如果仔细阅读[本指南第三章节的「将应用部署到互联网」一节](/en/part3/deploying_app_to_internet#application-to-the-internet),我们就可以找到解决方案。 - - -**记住**,当玩转产品部署时,总是必须密切关注服务器日志上发生的事情,因此尽早使用flyctl logs,并经常使用它。不,一直使用它! + +在进行自动部署之前,我们应确保应用程序可以手动部署。 -#### 11.11 Health check and rollback - - -每次在Fly.io上的部署都会创建一个[发布](https://fly.io/docs/flyctl/releases/)。可以从命令行检查发布: + +因此,请在 Fly.io 中创建一个新应用程序。然后使用以下命令生成 Fly.io API 令牌 ```bash -$ flyctl releases -VERSION STABLE TYPE STATUS DESCRIPTION USER DATE -v13 true release succeeded Deploy image mluukkai@iki.fi 30m6s ago -v12 true release succeeded Deploy image mluukkai@iki.fi 51m30s ago -v11 true release succeeded Deploy image mluukkai@iki.fi 59m25s ago -v10 true release succeeded Deploy image mluukkai@iki.fi 1h6m ago +flyctl auth token ``` - -确保部署最终发布成功,应用处于健康的功能状态是至关重要的。幸运的是,Fly.io有几个配置选项可以处理应用程序健康检查。 - - -source] - -[源] 部分已经有默认的fly.toml - -## 服务.tcp_checks + +您很快就会在部署工作流程中用到该令牌,因此请将其保存在某个地方(但不要提交到 GitHub)! -tcp_checks 指令允许您指定一组 TCP 检查,以检查代理的后端服务是否可用。如果检查失败,则代理将拒绝流量,您可以配置可选的超时和重试次数。检查的结果将被缓存,并且当检查失败时,将自动重试检查。 + +如前所述,在下一个练习中设置部署管道之前,我们现在要确保使用 flyctl deploy 命令进行手动部署能够正常运行。 -**服务.tcp_checks** + +需要做一些更改。 -tcp_checks指令允许您指定一组TCP检查,以检查代理的后端服务是否可用。如果检查失败,则代理将拒绝流量,您可以配置可选的超时和重试次数。检查的结果将被缓存,并且当检查失败时,将自动重试检查。 + +应修改配置文件 fly.toml 以包含以下内容: ```yml - [[services.tcp_checks]] - grace_period = "1s" - interval = "15s" - restart_limit = 0 - timeout = "2s" -``` - - -这一节定义了部署的基本健康检查。TCP检查确保应用程序所在的虚拟机处于运行状态,并且可以从外部通过[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)连接到虚拟机。 +[env] + PORT = "3000" # add this where PORT matches the internal_port below - -这个检查通知如果配置中有什么基本上是破坏的。例如,在我的情况下,对于这部分的应用程序,直到我把应用程序起来运行,它花了几次试验: +[processes] + app = "node app.js" # add this -```bash -$ fly releases -VERSION STABLE TYPE STATUS DESCRIPTION USER DATE -v4 true release succeeded Deploy image mluukkai@iki.fi 5h39m ago -v3 false release failed Deploy image mluukkai@iki.fi 5h50m ago -v2 false release failed Deploy image mluukkai@iki.fi 5h57m ago -v1 false release failed Deploy image mluukkai@iki.fi 6h12m ago -v0 false release failed Deploy image mluukkai@iki.fi 6h19m ago +[http_service] + internal_port = 3000 + force_https = true + auto_stop_machines = true + auto_start_machines = true + min_machines_running = 0 + processes = ["app"] ``` - -最后在第5次部署(版本v4)中,我正确地配置了它,最终发布成功了。 - - -除了基本的TCP健康检查之外,进行一些“应用程序级别”的健康检查以确保应用程序真正处于功能状态是极其有益的。其中一种可能性是在[services.http_checks](https://fly.io/docs/reference/configuration/#services-tcp_checks)中定义的HTTP级别检查,可用于确保应用程序正在响应HTTP请求。 + +在 [processes](https://fly.io/docs/reference/configuration/#the-processes-section) 中,我们定义了启动应用程序的命令。如果不做这一更改,Fly.io 只会启动 React dev 服务器,这会导致服务器关闭,因为应用程序本身并没有启动。我们还将把传递给应用程序的端口设置为环境变量。 - -在后端添加一个简单的端点用于做应用程序健康检查。你可以比如复制以下代码: + +我们还需要修改一下文件 _.dockerignore_,删除下一行: -```js -app.get('/health', (req, res) => { - res.send('ok') -}) +``` +dist ``` - -配置一个[HTTP-check](https://fly.io/docs/reference/configuration/#services-http_checks),根据对定义的健康检查端点的HTTP请求,确保部署的健康状态。 + +如果不删除该行,前端的产品构建将无法下载到 Fly.io 服务器。 - -注意,默认的fly.toml中已经定义了http\_checks是一个空数组。当您添加一个手动定义的HTTP检查时,您需要删除此行: + +如果本地计算机中存在生产构建,即运行 _npm build_ 命令后,部署工作就会正常进行。 -```yml -[[services]] - http_checks = [] # highlight-line -``` - - -也许有一个虚拟端点在应用中也是一个好主意,这样可以做一些代码更改,并确保部署的版本确实发生了变化: + +在进入下一个练习之前,请确保使用 flyctl deploy 命令进行的手动部署正常运行! -```js -app.get('/version', (req, res) => { - res.send('1') // change this string to ensure a new version deployed -}) -``` +#### 11.11 Automatic deployments - -确保Actions能够注意到如果部署破坏了你的应用程序: + +按照 [此处](https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/)给出的建议,扩展工作流程,添加将应用程序部署到 Fly.io 的步骤。 -![](../../images/11/12f.png) + +请注意,GitHub 操作应在部署步骤之前创建生产构建(使用 _npm run build_)! - -你可以像下面这样模拟: + +部署时需要刚才创建的授权令牌。将其值传递给 GitHub 操作的正确方法是使用 _Repository secrets_: -```js -app.get('/health', (req, res) => { - throw 'error...' - // eslint-disable-next-line no-unreachable - res.send('ok') -}) -``` +![repo secret](../../images/11/10f.png) - -在命令行中可以看到,当部署失败时,Fly.io会回滚到之前的可用发布版本: +Now the workflow can access the token value as follows: +现在,工作流可以如下方式访问令牌值: -```bash -$ fly releases -VERSION STABLE TYPE STATUS DESCRIPTION USER DATE -v15 true rollback succeeded Reverting to version 13 16m48s ago -v14 false release failed Deploy image mluukkai@iki.fi 21m53s ago -v13 true release succeeded Deploy image mluukkai@iki.fi 30m6s ago -v12 true release succeeded Deploy image mluukkai@iki.fi 51m30s ago -v11 true release succeeded Deploy image mluukkai@iki.fi 59m25s ago -v10 true release succeeded Deploy image mluukkai@iki.fi 1h6m ago +``` +${{secrets.FLY_API_TOKEN}} ``` - -所以,尽管发布存在问题,但该应用仍然可以正常使用! +If all goes well, your workflow log should look a bit like this: +如果一切顺利,你的工作流程日志应该是这样的: - -在进入下一个练习之前,修复你的部署,确保应用程序再次按预期正常工作。 +![](../../images/11/fly-good.png) -#### 11.12. Custom health check + +**请记住***,在玩转产品部署时,始终关注服务器日志中发生的情况至关重要,因此请尽早并经常使用 flyctl logs。不,是一直使用! - -除了基于TCP和HTTP的健康检查,Fly.io还允许使用非常灵活的基于shell脚本的健康检查。 该功能仍未文档化,但例如[此](https://community.fly.io/t/verifying-services-script-checks-is-supported/1464)会向您展示如何使用它。 +#### 11.12 Health check - -创建一个文件 health\_check.sh,内容如下: + +Fly.io 中的每次部署都会创建一个 [release](https://fly.io/docs/flyctl/releases/)。可通过命令行检查发布情况: ```bash -#!/bin/bash - -echo "Hello from shell script" - -exit 1 # exit status 1 means that the script "fails" +$ flyctl releases +VERSION STATUS DESCRIPTION USER DATE +v18 complete Release mluukkai@iki.fi 16h56m ago +v17 complete Release mluukkai@iki.fi 17h3m ago +v16 complete Release mluukkai@iki.fi 21h22m ago +v15 complete Release mluukkai@iki.fi 21h25m ago +v14 complete Release mluukkai@iki.fi 21h34m ago ``` - -给它执行权限(可以搜索Google或参考[此处](https://www.guru99.com/file-permissions.html)了解如何操作),并确保可以从命令行运行它。 +It is essential to ensure that a deployment ends up in a succeeding release, where the app is in healthy functional state. Fortunately, Fly.io has several configuration options that take care of the application health check. +确保部署以成功的版本结束,应用程序处于健康的功能状态,这一点至关重要。幸运的是,Fly.io 提供了多个配置选项来进行应用程序健康检查。 -```bash -$ ./health_check.sh -Hello from shell script +If we change the app as follows, it fails to start: +如果我们对应用程序进行如下更改,它就无法启动: + +```js +app.listen(PORT, () => { + this_causes_error + // eslint-disable-next-line no-console + console.log(`server started on port ${PORT}`) +}) ``` - -定义一个对你的应用程序进行健康检查的脚本,该脚本位于文件health\_check.sh中。确保此健康检查和部署失败。然后,更改脚本如下: +In this case, the deployment fails: +在这种情况下,部署会失败: ```bash -#!/bin/bash - -echo "Hello from shell script" - -exit 0 # exit status 0 means that the script "succeeds" +$ flyctl releases +VERSION STATUS DESCRIPTION USER DATE +v19 failed Release mluukkai@iki.fi 3m52s ago +v18 complete Release mluukkai@iki.fi 16h56m ago +v17 complete Release mluukkai@iki.fi 17h3m ago +v16 complete Release mluukkai@iki.fi 21h22m ago +v15 complete Release mluukkai@iki.fi 21h25m ago +v14 complete Release mluukkai@iki.fi 21h34m ago ``` - -"ssh username@hostname". +The app however stays up and running, Fly.io does not replace the functioning version (v18) with the broken one (v19). +但是,应用程序仍在运行,Fly.io 不会用损坏的版本(v19)替换正常运行的版本(v18)。 -确保现在部署可以正常工作。注意,为了正确获取脚本文件的路径,可能有利于登录到虚拟机控制台来查看文件所在的位置。登录使用命令“ssh username@hostname”。 +Let us consider the following change +让我们考虑以下变化 -```bash -flyctl ssh console -t YOUR_AUTH_TOKEN +```js +// start app in a wrong port +app.listen(PORT + 1, () => { + // eslint-disable-next-line no-console + console.log(`server started on port ${PORT}`) +}) ``` - -现在当你知道基于脚本的健康检查工作时,是时候定义真正的健康检查了。 - -Write a script ensuring the health check endpoint (that is, the GET request to '/health') not only works, but also returns the correct string 'ok'. + +现在,应用程序启动了,但它连接到了错误的端口,因此服务将无法运行。Fly.io 认为这是一次成功的部署,因此会在中断状态下部署应用程序。 - -你可能应该在脚本中使用[curl](https://curl.se/)来执行HTTP请求。你最有可能需要谷歌如何获得返回的字符串并与预期值'ok'进行比较。 + +防止部署中断的一种方法是使用 [http\_service.http_checks](https://fly.io/docs/reference/configuration/#http_service-checks) 节中定义的 HTTP 级检查。这种类型的检查可用于确保应用程序处于正常运行状态。 - -默认情况下,_curl_ 不存在于Fly.io虚拟机中。您可以通过在Fly.io应用程序设置时在项目根目录中创建的_Dockerfile_文件中添加以下行来安装它: + +添加一个简单的端点,用于对后台应用程序进行健康检查。例如,您可以复制这段代码: -```bash -# ... +```js +app.get('/health', (req, res) => { + res.send('ok') +}) +``` -FROM debian:bullseye + +然后配置 [HTTP check](https://fly.io/docs/reference/configuration/#http_service-checks),根据向定义的健康检查端点发出的 HTTP 请求确保部署的健康状况。 -RUN apt-get update; apt install -y curl // highlight-line + +您还需要将应用程序的 [部署策略](https://fly.io/docs/reference/configuration/#picking-a-deployment-strategy)(在文件 _fly.toml_中)设置为canary。这些策略可确保只部署状态健康的应用程序。 -LABEL fly_launch_runtime="nodejs" + +确保 GitHub Actions 在部署破坏应用程序时发出通知: -COPY --from=builder /root/.volta /root/.volta -COPY --from=builder /app /app +![](../../images/11/fly-fail.png) -WORKDIR /app -ENV NODE_ENV production -ENV PATH /root/.volta/bin:$PATH +You may simulate this e.g. as follows: +例如,您可以按以下方式进行模拟: -CMD [ "npm", "run", "start" ] +```js +app.get('/health', (req, res) => { + // eslint-disable-next-line no-constant-condition + if (true) throw('error... ') + res.send('ok') +}) ``` - -强烈建议首先本地检查脚本是否有效,因为脚本中可能会出现许多问题,而在GitHub Action中运行时,您无法进行任何调试打印。如果()事情没有按预期运行,登录虚拟机(使用flyctl ssh console)并手动检查脚本是否有效也是一个非常好的主意。 - - -*注意*,为了在虚拟机中测试脚本,您应该在成功部署时将脚本放在本地目录中。因此,如果部署失败,脚本将不会上传到Fly.io服务器。因此,如果遇到问题,请注释fly.toml中的脚本健康检查,然后进行部署以将脚本传送到虚拟机。 - - -我们基于脚本的健康检查在实际生活中几乎没有意义,因为它基本上和简单的HTTP检查所能实现的是一样的。这里的例子只是为了显示这种机制的存在。与HTTP检查不同,使用脚本基础的健康检查,原则上可以根据需要为你的应用编写复杂的、多方面的健康检查。 -
### Exercises 11.10-11.12. (Render) - -如果你想使用其他的托管选项,有一套替代练习可供[Fly.io](/en/part11/deployment/#exercises-11-10-11-12-fly-io)和[Heroku](/en/part11/deployment#exercises-11-10-11-12-heroku)使用。 + +如果你想使用其他托管选项,还有一套适用于 [Fly.io] 的练习(/en/part11/deployment/#exercises-11-10-11-12-fly-io)。 #### 11.10 Deploying your application to Render - -在[Render](render.com)中设置你的应用程序。 现在设置不像[第3章节](/en/part3/deploying_app_to_internet#application-to-the-internet)那么直接。 你必须仔细思考这些设置应该放置什么: + +在 [Render](https://render.com/) 中设置应用程序。现在的设置不像 [part 3](/en/part3/deploying_app_to_internet#application-to-the-internet)那么简单。您必须仔细考虑这些设置中应包含哪些内容: ![](../../images/11/render1.png) - -如果你需要在构建或启动命令中运行几个命令,你可以使用一个简单的shell脚本来完成。 + +如果需要在构建或启动命令中运行多个命令,可以使用简单的 shell 脚本。 - -创建一个文件 build_step.sh,内容如下: + +例如,创建一个 build_step.sh 文件,内容如下: ```bash #!/bin/bash @@ -444,247 +383,96 @@ echo "Build script" # add the commands here ``` - -给它执行权限(可以使用谷歌或参考[此链接](https://www.guru99.com/file-permissions.html)来了解如何操作),并确保可以从命令行运行它。 + +赋予它执行权限(Google 或参阅 [this](https://www.guru99.com/file-permissions.html) 了解方法),并确保可以从命令行运行它: ```bash $ ./build_step.sh Build script ``` - -你还需要打开高级设置并关闭自动部署,因为我们想在GitHub Actions中控制部署。 + +另一种方法是使用 [预部署命令](https://docs.render.com/deploys#deploy-steps),这样就可以在部署开始前运行一个额外的命令。 + + +您还需要打开高级设置并关闭自动部署,因为我们希望在 GitHub 操作中控制部署: ![](../../images/11/render2.png) - -确保现在你可以让应用程序正常运行。使用手动部署。 + +确保现在应用程序正常运行.使用手工部署 - -大概事情一开始就会失败,所以记得一直保持日志开放。 + +很可能一开始就出现故障,因此请记住始终打开日志。 #### 11.11 Automatic deployments - -现在去GitHub Actions [市场](https://github.com/marketplace)搜索我们的用途的action。你可以用render deploy来搜索。有几个action可供选择。你可以选择任何一个。通常最好的选择是拥有最多星星的那个。同时也有必要看看action是否经常维护(最近一次发布的时间),是否有许多打开的问题或拉取请求。 - - -设置您的工作流程的动作,确保每个通过所有检查的提交都会导致新的部署。注意,您需要Render API密钥和应用服务ID才能进行部署。参见[这里](https://render.com/docs/api)了解如何生成API密钥。您可以从您应用程序的Render仪表板的URL中获取服务ID。URL的结尾(以_srv-_开头)就是ID: - -```bash -https://dashboard.render.com/web/srv-crandomcharachtershere -``` - -另外,您也可以使用[Render部署钩子](https://render.com/docs/deploy-hooks),这是一个私有URL来触发部署。您可以从应用设置中获取它! ![fsorender1](https://user-images.githubusercontent.com/47830671/230722899-1ebb414e-ae1e-4a5e-a7b8-f376c4f1ca4d.png)。 - -不要在你的管道中使用普通的url,而是为你的密钥和服务ID创建Github密钥:![fsorender2](https://user-images.githubusercontent.com/47830671/230723138-77d027be-3162-4697-987e-b654bc710187.png) - -然后你可以这样使用它们: -``` bash - main: - name: Deploy to Render - runs-on: ubuntu-latest - steps: - - name: Trigger deployment - run: curl https://api.render.com/deploy/srv-${{ secrets.RENDER_SERVICE_ID }}?key=${{ secrets.RENDER_API_KEY }} -``` + +下一步是自动部署。有两种选择,一种是现成的自定义操作,另一种是使用渲染部署钩子。 +Deployment with custom action - -部署需要一些时间。查看Render仪表板的事件选项卡,以查看新部署何时准备就绪: +Go to GitHub Actions [marketplace](https://github.com/marketplace) and search for action for our purposes. You might search with render deploy. There are several actions to choose from. You can pick any. Quite often the best choice is the one with the most stars. It is also a good idea to look if the action is actively maintained (time of the last release) and does it have many open issues or pull requests. -![](../../images/11/render3.png) +**Warning**: for some reason, the most starred option [render-action](https://github.com/Bounceapp/render-action) was very unreliable when the part was updated (16th Jan 2024), so better avoid that. If you end up with too much problems, the deploy hook might be a better option! - -可能有个好主意,在应用程序中添加一个虚拟端点,使得可以做一些代码更改,并确保已部署的版本确实发生了变化: +Set up the action to your workflow and ensure that every commit that passes all the checks results in a new deployment. Note that you need Render API key and the app service id for the deployment. See [here](https://render.com/docs/api) how the API key is generated. You can get the service id from the URL of the Render dashboard of your app. The end of the URL (starting with _srv-_) is the id: -```js -app.get('/version', (req, res) => { - res.send('1') // change this string to ensure a new version deployed -}) +```bash +https://dashboard.render.com/web/srv-randomcharachtershere ``` -#### 11.12 Health check +Deployment with deploy hook - -所有测试都通过,新版本的应用程序自动部署到Render,一切似乎都正常。但是应用程序真的有效吗?除了部署管道中所做的检查之外,还有一些“应用程序级别”的健康检查,可以确保应用程序真正处于功能状态,这是极其有益的。 +Alternative, and perhaps a more reliable option is to use [Render Deploy Hook](https://render.com/docs/deploy-hooks) which is a private URL to trigger the deployment. You can get it from your app settings: - -添加一个简单的端点用于应用程序健康检查后端。例如,你可以复制此代码: +![fsorender1](https://user-images.githubusercontent.com/47830671/230722899-1ebb414e-ae1e-4a5e-a7b8-f376c4f1ca4d.png) -```js -app.get('/health', (req, res) => { - res.send('ok') -}) +DON'T USE the plain URL in your pipeline. Instead create GitHub secrets for your key and service id: ![fsorender2](https://user-images.githubusercontent.com/47830671/230723138-77d027be-3162-4697-987e-b654bc710187.png) +Then you can use them like this: +``` bash +- name: Trigger deployment + run: curl https://api.render.com/deploy/srv-${{ secrets.RENDER_SERVICE_ID }}?key=${{ secrets.RENDER_API_KEY }} ``` - -提交代码并将其推送到GitHub。确保您可以访问应用程序的健康检查端点。 +The deployment takes some time. See the events tab of the Render dashboard to see when the new deployment is ready: - -配置现在一个健康检查路径到您的应用程序。配置在Render仪表板的设置选项卡中完成。 +![](../../images/11/render3.png) - -更改你的代码,将其推送到GitHub,并确保部署成功。 +#### 11.12 Health check - -点击事件标签中最近一次部署,您可以查看部署日志。 +All tests pass and the new version of the app gets automatically deployed to Render so everything seems to be in order. But does the app really work? Besides the checks done in the deployment pipeline, it is extremely beneficial to have also some "application level" health checks ensuring that the app for real is in a functional state. - -当你完成健康检查设置之后,通过以下方式改变代码来模拟一次损坏的部署: +The [zero downtime deploys](https://docs.render.com/deploys#zero-downtime-deploys) in Render should ensure that your app stays functional all the time! For some reason, this property did not always work as promised when this part was updated (16th Jan 2024). The reason might be the use of a free account. + +Add a simple endpoint for doing an application health check to the backend. You may e.g. copy this code: ```js app.get('/health', (req, res) => { - throw 'error...' - // eslint-disable-next-line no-unreachable res.send('ok') }) ``` - -推送代码到GitHub,确保不会部署坏版本,并且之前的应用程序保持运行。 - - -在继续前进之前,请修复你的部署并确保应用程序再次按预期工作。 - -
- -
- -### Exercises 11.10-11.12. (Heroku) - - -在做下面的练习之前,你应该像我们在[第三章节](/en/part3/deploying_app_to_internet#application-to-the-internet)中所做的那样,在[Heroku](heroku.com)托管服务上设置你的应用程序。 - - -如果您想使用其他主机选项,还有另一套针对[Fly.io](/en/part11/deployment/#exercises-11-10-11-12-fly-io)和[Render](/en/part11/deployment#exercises-11-10-11-12-render)的练习。 - - -在与第3章节形成对比的是,我们不再自己把代码推送到Heroku上,而是让Github Actions工作流来为我们完成这项任务! +Commit the code and push it to GitHub. Ensure that you can access the health check endpoint of your app. - -确保现在您已经安装[Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli#download-and-install),并使用CLI通过heroku login登录Heroku。 +Configure now a Health Check Path to your app. The configuration is done in the settings tab of the Render dashboard. - -使用CLI在Heroku上创建一个新应用:heroku create --region eu {your-app-name},选择一个[地区](https://devcenter.heroku.com/articles/regions)靠近你自己的位置!(你也可以留空应用,Heroku会为你创建一个应用名称。) +Make a change in your code, push it to GitHub, and ensure that the deployment succeeds. - -使用命令 heroku authorizations:create 为你的 Heroku 配置生成一个 API 令牌,并将凭据保存到本地文件中,但**不要推送到 GitHub 上**! +Note that you can see the log of deployment by clicking the most recent deployment in the events tab. - -你很快就需要一个令牌来完成部署工作流程。更多关于Heroku令牌的信息请参见[这里](https://devcenter.heroku.com/articles/platform-api-quickstart)。 - -#### 11.10 Deploying your application to Heroku - - -增加一个步骤,将你的应用程序部署到Heroku。 - - -以下假设您使用社区开发的准备好的Heroku部署操作[AkhileshNS/heroku-deploy](https://github.com/AkhileshNS/heroku-deploy)。 - - -你需要刚刚创建的授权令牌来部署。正确的传递它的值给GitHub Actions的方式是使用存储库秘密: - -![repo secret](../../images/11/10x.png) - - -现在工作流可以按照以下方式访问令牌值: - -``` -${{secrets.HEROKU_API_KEY}} -``` - - -如果一切顺利,你的工作流日志应该看起来有点像这样: - -![](../../images/11/11.png) - - -你可以用浏览器试用该应用,但很可能会遇到问题。如果我们仔细阅读[第3章节的“应用程序上网”一节](/en/part3/deploying_app_to_internet#application-to-the-internet),我们会注意到Heroku假定存储库中有一个叫做Procfile的文件,它告诉Heroku如何启动应用程序。 - - -所以,添加一个合适的`Procfile`,确保应用程序启动正常。 - - -**记住**,在玩弄产品部署时,总是必须密切留意伺服器日志中发生的事情,因此要早早使用heroku logs,而且要经常使用它。不,要一直使用它! - -#### 11.11 Health check - - -在继续前,让我们增加一个步骤来扩展工作流程,即进行一个检查,以确保部署后应用程序正常运行。 - - -is already part of the existing workflow - -实际上,不需要单独的工作流步骤,因为该操作已经是现有工作流的一部分。 - -# 部署到Heroku -[部署到Heroku](https://github.com/marketplace/actions/deploy-to-heroku) 包含一个选项可以处理它。 - - -添加一个简单的端点来检查应用程序的健康状况到后端。例如,可以复制这段代码: +When you are set up with the health check, simulate a broken deployment by changing the code as follows: ```js app.get('/health', (req, res) => { + // eslint-disable-next-line no-constant-condition + if (true) throw('error... ') res.send('ok') }) ``` - -也许在应用中添加一个虚拟端点是个好主意,这样可以做一些代码更改,并确保部署的版本确实发生了变化: +Push the code to GitHub and ensure that a broken version does not get deployed and the previous version of the app keeps running. -```js -app.get('/version', (req, res) => { - res.send('1') // change this string to ensure a new version deployed -}) -``` - - -现在从[文档](https://github.com/marketplace/actions/deploy-to-heroku)中查看如何在部署步骤中包含健康检查。使用创建的端点作为健康检查URL。您可能还需要checkstring选项才能使检查工作。 - - -确保Actions能够及时注意到部署破坏了你的应用程序。例如,你可以通过给Procfile写入错误的启动命令来模拟这种情况: - -![](../../images/11/12x.png) - - -在进入下一个练习之前,修复你的部署,确保应用程序再次按预期正常工作。 - -#### 11.12. Rollback - - -如果部署导致应用程序出现故障,最好的办法是回滚到以前的发布版本。幸运的是,Heroku使这一切变得相当容易。每次部署到Heroku都会产生一个[发布](https://blog.heroku.com/releases-and-rollbacks#releases)。您可以使用命令heroku releases查看应用程序的发布版本: - -```js -$ heroku releases -=== calm-wildwood-40210 Releases - Current: v8 -v8 Deploy de15fc2b mluukkai@iki.fi 2022/03/02 19:14:22 +0200 (~ 8m ago) -v7 Deploy 8748a04e mluukkai@iki.fi 2022/03/02 19:06:28 +0200 (~ 16m ago) -v6 Deploy a617a93d mluukkai@iki.fi 2022/03/02 19:00:02 +0200 (~ 23m ago) -v5 Deploy 70f9b219 mluukkai@iki.fi 2022/03/02 18:48:47 +0200 (~ 34m ago) -v4 Deploy 0b2db00d mluukkai@iki.fi 2022/03/02 17:53:24 +0200 (~ 1h ago) -v3 Deploy f1cd250b mluukkai@iki.fi 2022/03/02 17:44:32 +0200 (~ 1h ago) -v2 Enable Logplex mluukkai@iki.fi 2022/03/02 17:00:26 +0200 (~ 2h ago) -v1 Initial release mluukkai@iki.fi 2022/03/02 17:00:25 +0200 (~ 2h ago) -``` - - -一句命令就可以快速从命令行[回滚](https://blog.heroku.com/releases-and-rollbacks#rollbacks)到一个发布版本。 - - -更棒的是,[deploy-to-heroku](https://github.com/marketplace/actions/deploy-to-heroku) 这个动作可以为我们负责回滚! - - -那么再次阅读[文档](https://github.com/marketplace/actions/deploy-to-heroku),并修改工作流程以防止完全破坏部署。您可以再次通过破坏Procfile来模拟破坏部署: +Before moving on, fix your deployment and ensure that the application works again as intended. -![](../../images/11/13x.png) - - -确保应用程序在部署失败的情况下仍能继续运行。 - - -注意,尽管自动回滚操作已执行,但构建仍然失败,当这种情况发生在现实生活中时,至关重要的是要找出导致该问题的原因并迅速解决。 通常,找出问题原因的最佳起点是研究Heroku日志: - -![](../../images/11/14.png) - -
+ \ No newline at end of file diff --git a/src/content/7/zh/part7d.md b/src/content/7/zh/part7d.md index 13355f4e186..5f92bbd0875 100644 --- a/src/content/7/zh/part7d.md +++ b/src/content/7/zh/part7d.md @@ -6,61 +6,55 @@ lang: zh ---
- -开发React一直以来都以配置非常困难而臭名昭著。如今,由于[create-react-app](https://github.com/facebookincubator/create-react-app),开始React开发几乎可以说是无痛的。对于浏览器端JavaScript开发来说,可能从未有过更好的开发工作流程。 + +早期,React 因难以配置应用程序开发所需的工具而出名。为了简化这种情况,[Create React App](https://github.com/facebookincubator/create-react-app)应运而生,它消除了与配置相关的问题。本课程中也使用了 [Vite](https://vitejs.dev/),它最近在新的应用程序中取代了 Create React App。 - -我们不能永远依赖create-react-app的黑魔法,是时候让我们看看引擎盖下面的情况了。使React应用程序可以正常工作的关键工具之一是[webpack](https://webpack.js.org/)。 +Both Vite and Create React App use bundlers to do the actual work. We will now familiarize ourselves with the bundler called [Webpack](https://webpack.js.org/) used by Create React App. Webpack was by far the most popular bundler for years. Recently, however, there have been several new generation bundlers such as [esbuild](https://esbuild.github.io/) used by Vite, which are significantly faster and easier to use than Webpack. However, e.g. esbuild still lacks some useful features (such as hot reload of the code in the browser), so next we will get to know the old ruler of bundlers, Webpack. +Vite 和 Create React App 都使用bundlers(捆绑) 来完成实际工作。现在,我们将熟悉 Create React App 使用的名为 [Webpack](https://webpack.js.org/) 的捆绑程序。多年来,Webpack 一直是最流行的捆绑程序。不过,最近出现了几种新一代捆绑程序,如 Vite 使用的 [esbuild](https://esbuild.github.io/) ,它们比 Webpack 快得多,也更容易使用。不过,esbuild 等捆绑程序仍然缺乏一些有用的功能(如在浏览器中热重载代码),因此接下来我们将了解一下老牌捆绑程序统治者 Webpack。 ### Bundling 我们通过将代码分割成单独的模块来实现我们的应用程序,这些模块被导入到需要它们的地方。尽管ES6模块在ECMAScript标准中定义,但较旧的浏览器不知道如何处理被分割成模块的代码。 - -因此,必须为浏览器将分割成模块的代码打包,这意味着所有源代码文件都被转换成一个包含所有应用程序代码的单个文件。当我们在[第3章节](/en/part3/deploying_app_to_internet)将React前端部署到生产环境时,我们使用_npm run build_命令对应用程序进行了打包。在幕后,npm脚本使用webpack对源代码进行了打包,在build目录中生成了以下文件集: + +因此,必须为浏览器将分割成模块的代码打包,这意味着所有源代码文件都被转换成一个包含所有应用程序代码的单个文件。当我们在[第3章节](/en/part3/deploying_app_to_internet)将React前端部署到生产环境时,我们使用_npm run build_命令对应用程序进行了打包。在幕后,npm脚本对源代码进行了打包,在dist目录中生成了以下文件集:
-.
-├── asset-manifest.json
-├── favicon.ico
+├── assets
+│   ├── index-d526a0c5.css
+│   ├── index-e92ae01e.js
+│   └── react-35ef61ed.svg
 ├── index.html
-├── logo192.png
-├── logo512.png
-├── manifest.json
-├── robots.txt
-└── static
-    ├── css
-    │   ├── main.1becb9f2.css
-    │   └── main.1becb9f2.css.map
-    └── js
-        ├── main.88d3369d.js
-        ├── main.88d3369d.js.LICENSE.txt
-        └── main.88d3369d.js.map
+└── vite.svg
 
- -index.html 文件位于构建目录的根目录下,是应用程序的“主文件”,它使用script标签加载打包的JavaScript文件: + +index.html 文件位于dist目录的根目录下,是应用程序的“主文件”,它使用script标签加载打包的JavaScript文件: ```html - - React App - - + + + + Vite + React + + +
+ ``` - -正如我们从使用`create-react-app`创建的示例应用程序中所看到的,构建脚本还将应用程序的CSS文件打包到单个/static/css/main.1becb9f2.css文件中。 + +正如我们从使用`Vite`创建的示例应用程序中所看到的,构建脚本还将应用程序的CSS文件打包到单个/assets/index-d526a0c5.css文件中。 - -在实践中,将代码捆绑在一起的目的是为了定义应用程序的入口点,这通常是index.js文件。当webpack捆绑代码时,它将包括入口点所导入的所有代码,以及它导入的代码所导入的代码,依此类推。 + +在实践中,将代码捆绑在一起的目的是为了定义应用程序的入口点,这通常是index.js文件。webpack 在捆绑代码时,不仅包括入口点的代码,还包括入口点导入的代码,以及其导入语句导入的代码,等等。 由于部分导入的文件是诸如React、Redux和Axios等包,因此打包的JavaScript文件也将包含每个库的内容。 @@ -68,7 +62,7 @@ lang: zh > 老的分割应用程序代码到多个文件的方式是基于index.html文件通过使用脚本标签来加载应用程序的所有单独的JavaScript文件。由于每个单独文件的加载都会带来一定的开销,这导致性能下降。因此,如今的首选方法是将代码打包到一个单独的文件中。 - + 接下来,我们将从零开始手动为 React 应用程序创建一个合适的 webpack 配置。 @@ -807,8 +801,8 @@ function h(){if(!d){var e=u(p);d=!0;for(var t=c.length;t;){for(s=c,c=[];++f 我们的目标是使用webpack配置应用程序,使得本地使用时,应用程序使用端口3001上可用的json-server作为其后端。 - - 然后,捆绑的文件将被配置为使用网址上的后端。 + + 然后,捆绑的文件将被配置为使用网址上的后端。 我们将安装axios,启动 json-server,然后对应用程序进行必要的更改。为了改变情况,我们将使用我们的[自定义钩子](/en/part7/custom_hooks)称为_useNotes_从后端获取笔记: @@ -996,16 +990,3 @@ if (!window.Promise) { 可以通过访问[https://caniuse.com](https://caniuse.com) 或 [Mozilla的网站](https://developer.mozilla.org/en-US/) 来检查不同API的浏览器兼容性。 - -### Eject - - -create-react-app 工具在幕后使用 webpack。如果默认配置不够,可以[弹出](https://create-react-app.dev/docs/available-scripts/#npm-run-eject)项目,这将摆脱所有的黑魔法,默认配置文件将存储在config目录和修改后的package.json文件中。 - - -如果你退出一个使用`create-react-app`创建的应用程序,就没有回头路了,所有的配置都必须手动维护。默认配置并不简单,与其从`create-react-app`应用程序中退出,一个更好的选择可能是从一开始就编写自己的`webpack`配置。 - - -通过阅读已卸载应用程序的配置文件仍然是值得推荐的,并且非常有教育意义。 - -