一、为什么?
现代全栈前端框架项目,安装一些常用的工具库之后,构建镜像轻轻松松大小超过 1G
。在生产环境运行并不需要开发环境的内容,优化开中各种问题,就成了开发者必须面对的一道题了,下面是我们对 Docker + Remix、Next 框架事件一些探索的总结。
二、linux 基础镜像层面
- 最小的 alpine 版本的 linux
- 时间问题(有服务,需要准确的时间)
三、Docker 层面
在 Node.js 项目中,使用辅助库很常见,明显这些库不会在生产环境中使用,例如如果我们使用了 test 库,在部署声到生产环境之前,移除这些不会在生产环境运行的库,减小 docker 构建的体积,也能加快构建速度。
3.1) docker 分阶段的用法
阶段构建中 Dockerfile 两个重要的关键之:
AS
指定名字--from=<name>
指定名字
以下是最为场景的 docker 分阶段示例:
dockerfile
FROM node:20.11.1-alpine3.19 AS builder
WORKDIR /app
COPY . .
RUN npm run build
# 第二阶段:运行阶段
FROM alpine:latest
WORKDIR /app
# 使用 builder 和 --from 访问第一个阶段的镜像
COPY --from=builder /app/myapp .
# 暴露端口
EXPOSE 8080
# 启动应用
CMD ["./myapp"]
从第一个阶段中复制数据到第二阶段减小包体积。
3.2) 一种常用分阶段策略
- 开发阶段 dev
- 构建阶段 build
- 运行阶段 run
dockerfile
FROM node:20.11.1-alpine3.19 AS dev
// do something in dev
FROM node:20.11.1-alpine3.19 AS build
// do something in build
FROM node:20.11.1-alpine3.19
// do run
CMD ["pnpm", "start"]
3.3)及时清理产生的不必要的缓存
通过包管理安装包,通常会产生大量的缓存文件,一定要在同一 RUN
指令的结尾处立刻清理。
四、内存分配
4.1) Node.js 内存分配
ts
NODE_OPTIONS=--max-old-space-size=4096 pnpm run build
处理 Node.js 内存 分配问题。
4.2)Docker 主机内存分配
如果你使用 Docker 桌面端, 可以通
- Settings
- Resources
- Resource Allocation
- Resources
根据自己机器情况分配:cpu 数量、交换内存、虚拟硬盘限制甚至可以改docker的镜像地址。
五、包管理工具 npm 和 pnpm
很多时候我们项目使用 pnpm 管理,没有使用 npm,然而 pnpm 的命令与 npm 的命令以及参数会有区别,下面我们给出几个常用:
5.1)只安装生产环境
这个两个是根据声环境进行的
sh
npm install --only=production
pnpm install --prod
5.2)--ignore-scripts
跳过与脚本运行(不执行任何 package.json 中定义的脚本)这在跳过开发阶段包安装,减小构建体积有很大的帮助
sh
npm install --ignore-scripts
pnpm install --ignore-scripts
5.3)跳过包
sh
npm install <package_name> --no-optional
pnpm install <package_name> --no-optional
5.4)使用 npm ci
ci 并不是 CICD 的 ci, npm 的 ci 也常用在 CI 中,ci 也是安装但是与 install 不同的是 ci 会自动的移除并缓存、效果比 install 好。
六、技术选型减少源头文件
项目不断地变化,技术选型是否符合需求。良好的技术选型从源头减少性能开销。
在开始项目之前,了解自己的设备性能,了解技术只要的性能是什么样的。例如:
在我们使用 Next.js/Remix 等项目的时候,选择 Antd 家族的 ProComponents 等系统合适吗?理论上是合适的。但是如果你现有的机器性能一般,这种技术选型,在随着项目增大的时候就需要注意了。以 Antd + Remix 为例,Remix 虽然可以最小化 hydrate 解决 Antd 样式闪动的问题,但是它的包大小也备受关注,antd 单独安装系列测试:
库名称 | 版本 | 单独安装(包含依赖) |
---|---|---|
antd | ^5.17.2 | 108M |
pro-components | ^2.7.1 | 126M |
antd mobile | ^5.36.0 | 48M |
pro-chat | ^1.13.7 | 216M |
icons | ^1.13.7 | 44M |
这五项加起来已经 500M+
了,如果你使用 nextjs 他的单独安装大概 310M+
(包含 eslint),如果你在加入一些开发时的辅助工具,轻轻松松就过了 1G
。项目在变化,包体积增加不可避免。做选型的时候做好各种方面测试,能有效的避免包体积一些问题。
其次如果使用 sqlite 等本地数据库, 可以考虑迁到别的在线数据库中。减少构建成本。
七、小结
现代前端框架能力越来越强,React 生态中 Next.js 和 Remix 都具备良好的操作后端的能力。如果项目做到了如使用到了 Docker,上服务器时候我们就需要考虑性能问题,当然最小的性能和可维护性之间平衡。当然你也可以选择云服务,当这不在 Docker 的讨论范围,本文适合在现代全栈meta框架探索和Docker优化小伙伴,希望能够帮助到读者。