前言

过来 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面撑持业务团队开发各类业务零碎,另一方面在本人的技术团队做根底技术建设。期间借着 Node.js 的矛头做了不少 Web 零碎,有的至今生气蓬勃、有的早已夭折淡出。在实践中,蚂蚁的 Chair 与淘系的 Midway 给了我不少启发,也借鉴了不少 bad case。思考过身边团队、本人团队、国外团队的各种案例之后发现,搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个要害事项

在接下来的一段时间里,我会以如何 “从零搭建 Node.js 企业级 Web 服务器” 为主题,将本人的所见所闻、所思所想详尽地记录下来,每个章节最初会附上实现本章内容的源码,心愿能够帮忙正在学习和理解 Node.js 的敌人对 Web 服务器畛域取得更清晰的了解和洞见。

浏览提醒:

  • 本文着重表述 Web 后端技术相干内容,Web 前端内容采纳 JavaScript Modules 进行演示。
  • 本文须要读者具备根底的编程能力以及对计算机网络的根本理解,一些罕用术语限于篇幅不再开展。

筹备环境

装置 Node.js

Node.js 公布版本分为 Current 和 LTS 两类,前者每 6 个月迭代一个大版本,疾速提供新增性能和问题修复,后者以 30 个月为一个大周期,为生产环境提供稳固依赖。以后 Node.js 最新 LTS 版本为 12.18.2,本文以此版本作为运行环境,能够在官网下载并装置。

装置实现后,在命令行输出 node --version 查看输入是否为 v12.8.2,如果统一,那么装置胜利。

另外,有趣味的读者能够尝试通过 nvm / nvm-windows 治理多个 Node.js 版本,此处不是本文重点不再开展。

装置 Yarn

Node.js 提供了本人的包管理器 npm,npm 默认从海内官网的 registry 拉取包信息速度比较慢,须要执行以下命令设置应用国内镜像地址:

$ npm config set registry http://r.cnpmjs.org/

通过 npm 能够全局或本地装置依赖包,当本地装置时 npm 会依据 package.json 装置最新的依赖包,同时主动生成并更新 package-lock.json 文件,这就引发了一个问题:如果一个依赖包在 package.json 标记版本范畴内公布了有问题的新版本,那么咱们本人的我的项目也会跟着出问题。

为了解决这个问题,就引入了第三方包管理器 yarn,通过以下命令装置:

$ npm i -g yarn

相比 npm,yarn 会严格依照主动生成的 yarn.lock 本地装置依赖包,只有增删依赖或者 package.json 标记版本产生不可兼容的变动时才会更新 yarn.lock,这就彻底杜绝了上述 npm 的问题。思考到企业级 Web 服务器对稳定性的要求,yarn 是必要的。

装置 Docker

一般来讲,做一个 Web 服务器会有两种部署抉择,要么是传统的包部署,要么是容器镜像部署,后者较前者在编排上更不便,联合 Kubernetes 能够做到很好的伸缩,是以后倒退的趋势。Docker 作为支流容器技术必须熟练掌握,能够在官网下载并装置。

写一个动态资源服务器

初始化工程

筹备好了环境就能够开始编码了,先新建工程根目录,而后进入并初始化 package.json 与目录构造:

$ mkdir 00-static   # 新建工程根目录$ cd 00-static      # 进入工程根目录$ yarn init -y      # 初始化 package.jsonyarn init v1.22.4success Saved package.json$ mkdir src         # 新建 src 目录寄存外围逻辑$ mkdir public      # 新建 public 目录寄存动态资源$ tree -L 1         # 展现当前目录内容构造.├── package.json├── public└── src

Express 还是 Koa?

Express 与 Koa 均是 Node.js 服务端根底框架。Express 公布于 2010 年,凭借杰出的中间件机制在开源社区积攒了大量的成熟模块,当初是 OpenJS 基金会 At-Large 级别我的项目。Koa 公布于 2013 年,相比 Express 具备了更加欠缺的中间件机制以及编程体验,但在开源社区模块积攒的质与量上还有肯定差距。在此比拟几个罕用模块:

模块名称性能简介Express / KoaStarContributersUsed by最近提交工夫
passport认证登录Express17.7k33385k2020-06-10
koa-passport认证登录Koa737214.7k2019-07-13
connect-redis会话存储Express2.3k5126.3k2020-07-10
koa-redis会话存储Koa310132.7k2020-01-16
helmet网络安全Express7.2k25136.4k2020-07-11
koa-helmet网络安全Koa546244.1k2020-06-03

上表整顿自 Github 截止 2020 年 7 月 20 日的数据。

相比 Koa 模块,Express 模块广泛在星数(Star)、贡献者数(Contributers)、应用数(Used by)上高出一个档次,同时 Express 模块的贡献者更热心于保护与更新,Koa 只管在国内受到过一些追捧,但在更全面的考量下 Express 才是更持重的抉择。在工程根目录执行以下命令装置:

$ yarn add express  # 本地装置 Express# ...info Direct dependencies└─ express@4.17.1# ...$ tree -L 1         # 展现当前目录内容构造.├── node_modules├── package.json├── public├── src└── yarn.lock

动态服务

当初能够开始写应用逻辑了,本章先做一个动态资源服务器,以 public 目录为动态资源目录:

// src/server.jsconst express = require('express');const { resolve } = require('path');const { promisify } = require('util');const server = express();const port = parseInt(process.env.PORT || '9000');const publicDir = resolve('public');async function bootstrap() {  server.use(express.static(publicDir));  await promisify(server.listen.bind(server, port))();  console.log(`> Started on port ${port}`);}bootstrap();
<!-- public/index.html --><html>  <head>    <meta charset="utf-8" />  </head>  <body>    <h1>It works!</h1>  </body></html>
$ tree -L 2 -I node_modules   # 展现除了 node_modules 之外的目录内容构造.├── package.json├── public│   └── index.html├── src│   └── server.js└── yarn.lock

逻辑写好之后在 package.json 中设置启动脚本:

{  "name": "00-static",  "version": "1.0.0",-  "main": "index.js",+  "scripts": {+    "start": "node src/server.js"+  },  "license": "MIT",  "dependencies": {    "express": "^4.17.1"  }}

而后就能够启动利用了:

$ yarn start> Started on port 9000

拜访 http://localhost:9000/ 即可看到 index.html 内容:

应用容器

接下来通过 Docker 对做好的动态资源服务器进行容器化,新建以下配置文件:

# DockerfileFROM node:12.18.2-slimWORKDIR /usr/app/00-staticCOPY . .RUN yarnEXPOSE 9000CMD yarn start
# .dockerignorenode_modules
$ tree -L 1 -a  # 展现包含 . 结尾的全副目录内容构造.├── .dockerignore├── Dockerfile├── node_modules├── package.json├── public├── src└── yarn.lock

而后构建镜像并启动容器:

$ docker build -t 00-static:1.0.0 . # 构建容器镜像,命名为 00-static,标签为 1.0.0# ...Successfully tagged 00-static:1.0.0$ docker run -p 9090:9000 -d --name 00-static 00-static:1.0.0 # 以镜像 00-static:1.0.0 运行容器,命名为 00-static$ docker logs 00-static   # 查看 00-static 容器的日志> Started on port 9000$ docker stats 00-static  # 查看 00-static 容器的状态CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS43c451232fa5        00-static           0.03%               37.41MiB / 1.945GiB   1.88%               8.52kB / 3.35kB     0B / 0B             24

拜访 http://localhost:9090/ 即可与之前一样看到 index.html 内容:

本章源码

host1-tech/nodejs-server-examples - 00-static

更多浏览

从零搭建 Node.js 企业级 Web 服务器(零):动态服务
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
从零搭建 Node.js 企业级 Web 服务器(二):校验