关于部署的总结
静态资源组织部分
- 为了最大程度利用缓存,将页面(HTML)设置为协商缓存,将 JavaScript、CSS 等设置为永久强缓存。
- 为了解决强缓存更新问题,将文件摘要(hash)作为资源路径(URL)构成的一部分。
- 为了解决覆盖式发布引发的问题,采用 name-hash 而非 query-hash 的组织方式,具体需要配置 webpack 的 output.filename 为 contenthash 方式。
- 为了解决 Nginx 目录存储过大 + 结合 CDN 提升访问速度,采用了 Nginx 反向代理+ 将静态资源上传到 CDN。
- 为了上传 CDN,我们需要按环境动态构造 publicPath + 按环境构造 CDN 上传目录并上传。
- 为了动态构造 publicPath 并且随构建过程插入到 HTML 中,采用 Webpack-HTML-Plugin 等插件,将编译好的带 hash + publicPath 的静态资源插入到 HTML 中。
- 为了保证上传 CDN 的安全,我们需要一种机制管控上传 CDN 秘钥,而非简单的将秘钥写到代码 / Dockerfile 等明文文件中。
自动化部署部分
为了提升部署效率,100% 避免因部署出错,需要设计 & 搭建自动化部署平台,以 Docker 等保证环境的一致性,以 Jenkins 等保证构建流程的串联。使用es-build等提升构建效率。
前端部署 & 静态资源加工
关于前端部署,能总结出下面几个原则/要求:
- 构建发布后,不应该被覆盖。
- 构建发布后,静态资源应当永久保存在服务器/CDN 上,即只可读。
- 静态资源组织上,每个版本应该按文件夹存储,做到资源收敛。这样假如真要删除时,可按版本删除。(如某个版本代码泄密)
1 | // webpack.config.js |
故 publicPath 应增加 version 字段
- 发布过程应该自动化,开发人员不应该直接接触服务器。
- 版本切换时,也应当不接触服务器。
- 版本切换能秒级生效。(如 v0.2 切换 v0.3,立即生效)。
- 线上需要能同时生效多个版本,满足 AB 测试、灰度、PRE 环境等小流量需求。
上述需求都相对复杂多变,为了应对复杂的线上需求,可以对静态资源做深度加工,如通过服务端直出 HTML、通过配置中心实现按用户 PRE 等等。
前端发布服务
面对复杂的商业化需求,方便多前端业务实现版本管理、灰度、PRE、AB 测试等小流量功能,我们设计了一个中间服务 PageConfig Web & PageServer,与 Nginx 和各种后端相结合,达到配置即时生效的能力。
灵魂拷问的部分答案
Q: 前端代码从 tsx/jsx 到部署上线被用户访问,中间大致会经历哪些过程?
A: 经历本地开发、远程构建打包部署、安全检查、上传CDN、Nginx做流量转发、对静态资源做若干加工处理等过程。
Q:可能大部分同学都知道强缓存/协商缓存,那前端各种产物(HTML、JS、CSS、IMAGES 等)应该用什么缓存策略?以及为什么?
– 若使用协商缓存,但静态资源却不频繁更新,如何避免协商过程的请求浪费?
– 若使用强缓存,那静态资源如何更新?
A:HTML使用协商缓存,静态资源使用强缓存,使用name-hash(非覆盖式发布)解决静态资源更新问题。
Q:配套的,前端静态资源应该如何组织?
A:搭配 Webpack 的Webpack_HTML-Plugin & 配置 output publicPath等。
Q:配套的,自动化构建 & 部署过程如何与 CDN 结合?
A:自动化构建打包后,将产物传输到对应环境 URL 的CDN上。
Q:如何避免前端上线,影响未刷新页面的用户?
A:使用name-hash方式组织静态资源,先上线静态资源,再上线HTML。
Q:刚上线的版本发现有阻塞性 bug,如何做到秒级回滚,而非再次部署等 20 分钟甚至更久?
A:HTML文件使用非覆盖方式存储在CDN上,搭建前端发布服务,对 HTML 按版本等做缓存加工处理。当需要回滚时,更改发布服务HTMl指向即可。
Q: CDN 域名突然挂了,如何实现秒级 CDN 降级修补而非再次全部业务重新部署一次?
A1: 将静态资源传输到多个 CDN 上,并开发一个加载Script的SDK集成到HTML中。当发现CDN资源加载失败时,逐步降级CDN域名。
A2:在前端发布服务中,增加HTML文本处理环节,如增加CDN域名替换,发生异常时,在发布服务中一键设置即可。
Q:如何实现一个预发环境,除了前端资源外都是线上环境,将变量控制前端环境内?
A:对静态资源做加工,对HTML入口做小流量。
Q:部署环节如何方便配套做 AB 测试等?
A:参见前端发布服务
Q:如何实现一套前端代码,发布成多套环境产物?
A:使用环境变量,将当前环境、CDN、CDN_HOST、Version等注入环境变量中,构建时消费 & 将产物上传不同的CDN即可。
其他
如果想深入学习前端部署,下面是一些学习建议。
- 学习负载均衡(要求:了解)。
学习和了解负载均衡的原理、都有哪些配置玩法。如参考大型网站架构系列:负载均衡详解 - 深入学习 HTTP(要求:熟练掌握)
如掌握常见的状态码、常见的 Header 及其深度应用、强缓存/协商缓存、HTTP2 的新增功能等等。尤其HTTP 1.1 和 HTTP 2.0。
推荐书籍:
图解HTTP
HTTP 权威指南 - 深入学习前端工程化 (要求:精通)
– 了解前端工程化可以做什么,如 前端工程化:体系设计与实践
– 掌握前端工程师的常见实践原理 & 实操
– 深度学习 Webpack Webpack 官方文档 - 学习各种对前端静态资源加工的各种方案(要求:掌握)
- 深度学习浏览器原理 (要求:精通)
一些资料:从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理