大公司里怎样开发和部署前端代码?
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的
offer。 已帮助数百位同学拿到了中大厂offer。欢迎来撩~~~~~~~~
Hello,大家好,我是 Sunday。
昨天的时候有同学问到前端部署相关的内容,正好在知乎中看到了张云龙大佬的前端部署回答
回答地址:https://www.zhihu.com/question/20790576
这个回答非常有价值,应该可以帮助到很多对部署不是很了解的同学,因此整理
问题
首先把问题给大家贴出来,如果大家也有类似的困惑,那么本文章肯定会给你带来一定的收获
大公司里怎样开发和部署前端代码?
主要有以下问题:
- 开发时的和部署时类库的引用和存放是一致还是不同?
- 模块放在项目中还是放在 CDN 之类服务器?
- 渲染网页用 Nginx 还是其他动态语言的 Web 服务器?
- 制作网页的流程,是先有设计师的稿,还是先看模块?
- 会选择用自己写的模块还是从社区寻找模块?
其他的思考
你平时在公司中是怎么部署项目的呢?
- 直接执行
npm run build打包项目 - 得到
dist文件夹,放到服务器对应位置 - 重新执行
nginx -s reload完成部署
这样应该没有什么问题了。撑死再去解决下跨域的问题,一般的中小公司部署就算是完成了。
但是 部署真的有那么简单吗?那些大厂的部署也是通过以上方式完成的吗?
让我们一起来看看吧~~
正文
基础部署逻辑

当我们回归到最基本的前端开发时,就像看到了这个"可爱"的index.html页面和它的样式文件a.css,简单地用文本编辑器书写代码,不需进行编译,只要本地预览确认无误,然后将其放到服务器上等待用户访问。
前端开发就是"如此简单",很轻松嘛!门槛也是相当低嘛!轻轻松松掌握有木有!!

然后我们访问页面,看到效果,再查看一下网络请求,200!不错,太™完美了!那么,研发完成。。。。了么?
等等,这还没完呢!对于大公司来说,那些变态的访问量和性能指标,将会让前端一点也不“好玩”。
看看那个a.css的请求吧,如果每次用户访问页面都要加载,是不是很影响性能,很浪费带宽啊,我们希望最好这样:

利用304,让浏览器使用本地缓存。
但,这样也就够了吗?不成!
304叫协商缓存,这玩意还是要和服务器通信一次,我们的优化级别是变态级,所以必须彻底灭掉这个请求,变成这样:

强制浏览器使用本地缓存(cache-control/expires),不要和服务器通信。好了,请求方面的优化已经达到变态级别,那问题来了:你都不让浏览器发资源请求了,这缓存咋更新?
很好,相信有人想到了办法:通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。好像这样:

下次上线,把链接地址改成新的版本,就更新资源了不是。OK,问题解决了么?!
当然没有!大公司的变态又来了,思考这种情况:

页面引用了3个css,而某次上线只改了其中的a.css,如果所有链接都更新版本,就会导致b.css,c.css的缓存也失效,那岂不是又有浪费了?!
重新开启变态模式,我们不难发现,要解决这种问题,必须让url的修改与文件内容关联,也就是说,只有文件内容变化,才会导致相应url的变更,从而实现文件级别的精确缓存控制。
什么东西与文件内容相关呢?我们会很自然的联想到利用 数据摘要要算法 对文件求摘要信息,摘要信息与文件内容一一对应,就有了一种可以精确到单个文件粒度的缓存控制依据了。好了,我们把url改成带摘要信息的:

这回再有文件修改,就只更新那个文件对应的url了,想到这里貌似很完美了。你觉得这就够了么?大公司告诉你:图样图森破!
唉~~~~,让我喘口气
现代互联网企业,为了进一步提升网站性能,会把静态资源和动态网页分集群部署,静态资源会被部署到CDN节点上,网页中引用的资源也会变成对应的部署路径:


这次发布,同时改了页面结构和样式,也更新了静态资源对应的url地址,现在要发布代码上线,亲爱的前端研发同学,你来告诉我,咱们是先上线页面,还是先上线静态资源?
- 先部署页面,再部署资源:在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。
- 先部署资源,再部署页面:在部署时间间隔之内,有旧版本资源本地缓存的用户访问网站,由于请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种情况下页面展现正常;但没有本地缓存或者缓存过期的用户访问网站,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。
好的,上面一坨分析想说的就是:先部署谁都不成!都会导致部署过程中发生页面错乱的问题。所以,访问量不大的项目,可以让研发同学苦逼一把,等到半夜偷偷上线,先上静态资源,再部署页面,看起来问题少一些。
但是,大公司超变态,没有这样的“绝对低峰期”,只有“相对低峰期”。So,为了稳定的服务,还得继续追求极致啊!
这个奇葩问题,起源于资源的 覆盖式发布,用 待发布资源 覆盖 已发布资源,就有这种问题。解决它也好办,就是实现 非覆盖式发布。

看上图,用文件的摘要信息来对资源文件进行重命名,把摘要信息放到资源文件发布路径中,这样,内容有修改的资源就变成了一个新的文件发布到线上,不会覆盖已有的资源文件。上线过程中,先全量部署静态资源,再灰度部署页面,整个问题就比较完美的解决了。
什么是灰度?
软件开发通常是逐个版本不断迭代的过程。尽管新版本在上线前经过了测试,但即使如此,也无法确保没有问题。
因此,在公司里,上线新版本代码通常通过灰度系统。灰度系统能够将流量分为多个部分,其中一部分流向新版本代码,另一部分流向旧版本代码。

而且,灰度系统可以设置流量的比例。例如,可以将走新版本代码的流量设置为 5%,确认没有问题后再逐步增加到 10%,50%,最终到达 100% 的全量。这样做可以将出现问题的影响降到最低。
否则,如果一开始就直接使用全量流量,一旦出现线上问题,就可能引发重大事故。
此外,灰度系统不仅仅用于此,例如,当产品不确定某些更改是否有效时,需要进行 A/B 实验,将流量分为两部分,一部分走 A 版本代码,另一部分走 B 版本代码。
那么这样的灰度系统是如何实现的呢?实际上,很多都是通过 nginx 实现的。
nginx 是一个反向代理的服务,用户的请求发送给它,然后由它转发给具体的应用服务器。

它的工作流程如下图所示:

首先,需要对流量进行染色,即对每个用户进行标注,让某些用户访问服务1,而其他用户访问服务2。染色的方法有很多种,可以通过cookie来实现。不同的用户携带不同的cookie。一开始所有用户都访问服务1。
然后,在用户进行第二次访问时,nginx 根据用户携带的cookie将其转发到不同的服务,从而实现灰度访问。
好了,灰度部署的介绍就到这里。回到原文提到的先全量部署静态资源,再灰度部署页面,这是什么意思呢?
当进行静态资源的部署时,不必删除原有的静态资源,而是复制新的静态资源过去。由于文件名采用了摘要算法重命名,因此不会出现重名的问题。
在灰度部署动态页面方面,部分用户访问旧页面,而另一部分用户访问新页面。对于访问旧页面的用户,其请求仍指向旧资源并直接使用缓存。对于访问新页面的用户,他们访问的是已经完成部署的新资源,避免了访问旧资源导致页面错误的情况。
最后,根据用户访问情况,通过灰度系统逐步将访问旧页面的用户过渡到新页面上。
部署方案总结
所以,大公司的静态资源优化方案,基本上要实现这么几个东西:
- 配置超长时间的本地缓存
- 节省带宽,提高性能采用内容摘要作为缓存更新依据
- 精确的缓存控制静态资源CDN部署
- 优化网络请求更资源发布路径实现非覆盖式发布
- 平滑升级
全套做下来,就是相对比较完整的静态资源缓存控制方案了,而且,还要注意的是,静态资源的缓存控制要求在前端所有静态资源加载的位置都要做这样的处理。是的,所有!什么js、css自不必说,还要包括js、css文件中引用的资源路径,由于涉及到摘要信息,引用资源的摘要信息也会引起引用文件本身的内容改变,从而形成级联的摘要变化,大概示意图就是:

好了,目前我们快速的学习了一下前端工程中关于静态资源缓存要面临的优化和部署问题,新的问题又来了:这™让工程师怎么写码啊!!!
要解释优化与工程的结合处理思路,又会扯出一堆有关模块化开发、资源加载、请求合并、前端框架等等的工程问题,以上只是开了个头,解决方案才是精髓,但要说的太多太多,有空再慢慢展开吧。或者大家可以去我的blog看其中的一些拆解:https://github.com/fouber/blog
总之,前端性能优化绝逼是一个工程问题!
以上不是我YY的,可以观察 百度 或者 facebook 的页面以及静态资源源代码,查看它们的资源引用路径处理,以及网络请中静态资源的缓存控制部分。再次赞叹facebook的前端工程建设水平,跪舔了。
建议前端工程师多多关注前端工程领域,也许有人会觉得自己的产品很小,不用这么变态,但很有可能说不定某天你就需要做出这样的改变了。而且,如果我们能把事情做得更极致,为什么不去做呢?
另外,也不要觉得这些是运维或者后端工程师要解决的问题。如果由其他角色来解决,大家总是把自己不关心的问题丢给别人,那么前端工程师的开发过程将受到极大的限制,这种情况甚至在某些大公司都不少见!
妈妈,我再也不玩前端了。。。。5555
10.29 日更新
在评论中, @陈钢@fleuria @林翔 提到了rails,刚刚去看了一下,确实是完成了以上所说的优化细节,对整个静态资源的管理上的思考于本答案描述的一致。很遗憾我直到今天(2014-10-29)才了解到rails中的assets pipeline。这里向以上3位同学道歉,原谅我的无知。
不过整篇回答没有讲解到具体的解决方案实现思路,只是介绍了前端在工程化方向的思考,答案本身是可用的,了解rails的人也可以把此答案当做是对rails中assets pipeline设计原理的分析。
rails通过把静态资源变成erb模板文件,然后加入<%= asset_path 'image.png' %>,上线前预编译完成处理,不得不承认,fis的实现思路跟这个几乎完全一样,但我们当初确实不知道有rails的这套方案存在。
10.31 日更新
用 FIS3(https://fis.baidu.com/) 包装了一个小工具,完整实现整个回答所说的最佳部署方案,并提供了源码对照,可以感受一下项目源码和部署代码的对照。
- 源码项目:fouber/static-resource-digest-project · GitHub
- 部署项目:fouber/static-resource-digest-project-release · GitHub
- 部署项目可以理解为线上发布后的结果,可以在部署项目里查看所有资源引用的md5化处理。
这个示例也可以用于和assets pipeline做比较。fis没有assets的目录规范约束,而且可以以独立工具的方式组合各种前端开发语言(coffee、less、sass/scss、stylus、markdown、jade、ejs、handlebars等等你能想到的),并与其他后端开发语言结合。
assets pipeline的设计思想值得独立成工具用于前端工程,fis就当做这样的一个选择吧。
1v1私教,帮大家拿到满意的 offer
我目前在做一个 前端训练营 ,主打的就是:1v1 私教,帮大家拿到满意的 offer 。
可以点击这里查看详情
也可以直接加我微信沟通,备注【训练营】:

相关文章:
大公司里怎样开发和部署前端代码?
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello,大家好,我是 Sunday。 昨天的时候有同学问到前端部署相关的内容,正好在知乎中看到…...
API接口:原理、设计与实践
一、引言 随着互联网的发展,应用程序之间的交互变得越来越频繁,API接口成为了不同应用程序之间进行数据交换的重要手段。本文将详细介绍API接口的原理、设计与实践,以期帮助读者更好地理解和应用这一技术。 二、API接口概述 API࿰…...
2023年TIOBE指数TOP50的编程语言写“Hello World!”
这篇文章列出了TIOBE指数TOP50的编程语言(TIOBE Index - TIOBE)如何写“Hello World!”。“Hello World!”代码应该是每个程序员学习一门编程语言最先实现的程序,给我们带来了很多美好的回忆,下面我们就一次…...
spring、springmvc、springboot、springcloud简介
spring简介 spring是什么? spring: 春天spring: 轻量级的控制反转和面向切面编程的框架 历史 2002年,首次推出spring雏形,interface 21框架2004年,发布1.0版本Rod Johnson: 创始人,悉尼大学,音乐学博士…...
立仪科技光谱共焦位移传感器:应用领域的广泛性
在科技日新月异的今天,光谱共焦位移传感器以其精确、稳定的特性,在各个领域得到了广泛的应用。本文将详细介绍光谱共焦位移传感器的应用情况,以期让大家对其有更深入的了解。我们来理解一下什么是光谱共焦位移传感器。 它是一种通过测量物体表…...
neo4j图数据库安装和测试
neo4j图数据库安装和测试 1. 下载合适的neo4j软件版本。 https://we-yun.com/doc/neo4j/ https://neo4j.com/deployment-center/#enterprise 2. 下载JAVAJDK 由于neo4j是一个用Java编写的图形数据库,因此在安装和运行Neo4j之前,需要先安装Java Developm…...
爬取豆瓣电影top250的电影名称(完整代码与解释)
在爬取豆瓣电影top250的电影名称之前,需要在安装两个第三方库requests和bs4,方法是在终端输入: pip install requestspip install bs4 截几张关键性图片: 豆瓣top250电影网页 运行结果 测试html文件标签的各个方法的作用…...
tidb 集成 flyway 报错 denied to user for table global_variables
报错内容: Caused by: java.sql.SQLException: connection disabled at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1181) at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.jav…...
很实用的ChatGPT网站—在线编程模块增补篇
很实用的ChatGPT网站(http://chat-zh.com/)——增补篇 今天介绍一个好兄弟开发的ChatGPT网站,网址[http://chat-zh.com/]。这个网站功能模块很多,包含生活、学习、医疗、法律、经济等很多方面。今天跟大家分享一下,新…...
A股风格因子看板 (2024.01第01期)
该因子看板跟踪A股风格因子,该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子,用以分析市场风格切换、组合风格暴 露等。 今日为该因子跟踪第1期,指数组合数据截止日2024-12-01,要点如下 近1年A股风格因子检验统…...
基于gamma矫正的照片亮度调整(python和opencv实现)
import cv2 import numpy as npdef adjust_gamma(image, gamma1.0):invGamma 1.0 / gammatable np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8")return cv2.LUT(image, table)# 读取图像 original cv2.imread("tes…...
LeetCode-Java(29)
29. 两数相除 结果肯定落在dividend上,于是对这个区间每一个数进行二分查找,判断方法就是 while (l < r) {long mid l r 1 >> 1;if (mul(mid, y) < x) {l mid;} else {r mid - 1;}} 其中mul是一个要定义的快速乘法。 完整代码如下 …...
腾讯云导入导出镜像官方文档
制作与导出 Linux 镜像 https://cloud.tencent.com/document/product/213/17814 制作与导出 Windows 镜像 https://cloud.tencent.com/document/product/213/17815 云服务器 导出镜像-操作指南-文档中心-腾讯云 (tencent.com) 轻量应用服务器 管理共享镜像-操作指…...
keras 深度学习框架实现 手写数字识别
阅读本文之前,请先参考--------win10搭建keras深度学习框架 安装运行环境 阅读本文之前,请先参考--------keras人工智能框架 MNIST 数据集 随机展示 查看训练图片 完整代码如下图: 在sublimeText中 使用ctrlB运行代码,结果如…...
SELinux策略语法以及示例策略
首发公号:Rand_cs 本文来讲述 SELinux 策略常用的语法,然后解读一下 SELinux 这个项目中给出的示例策略 安全上下文 首先来看一下安全上下文的格式: user : role : type : level每一个主体和客体都有一个安全上下文,通常也称安…...
电路笔记 :自激振荡电路笔记 电弧打火机
三极管相关 三极管的形象描述 二极管 简单求解(理想) 优先导通(理想) 恒压降 稳压管(二极管plus) 基础工作模块 理想稳压管的工作特性 晶体管之三极管(“两个二极管的组合” ) 电弧打火机电路 1.闭合开…...
prometheus grafana linux服务器监控
文章目录 前传node-exporter安装配置promethues监控node节点grafana操作查看监控:外传 前传 prometheus grafana的安装使用:https://nanxiang.blog.csdn.net/article/details/135384541 本文说下监控nginx,prometheus grafana linux 安装配…...
有哪些有用的工作技巧?
有效沟通免去麻烦 说起职场的工作技巧,首先不得不提的便是有效沟通。高效的职场沟通不仅能显著提高工作效率,通过清晰准确地传递信息,减少误解和错误,还能促进团队间的紧密合作,建立起相互信任和理解的环境。在面临挑…...
k8s的网络类型
部署 CNI 网络组件 部署 flannel K8S 中 Pod 网络通信: Pod 内容器与容器之间的通信 在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命名空间, 相当于它们在同一台机器上一样,可以用 localho…...
《元宇宙2086》团队发布AI创作的元宇宙之歌
《元宇宙2086》团队发布AI创作的元宇宙之歌 数字科技领域著名IP——《元宇宙2086》的团队发布AI创作的《元宇宙之歌》,歌词是AI与人共同完成,作曲、混音、人声合成全部由AI完成并且演唱,歌曲描绘了未来的元宇宙世界。 “踏入元宇宙的奇境&am…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
