静态资源(Static Resources): js、css、img 等非服务器动态运行生成的文件。css
在通常的网站中,静态资源使用频率高,流量占用大。对于有追求(访问量稍大)的网站,都会把静态资源放置到 CDN 服务器,不占用业务服务器的网络带宽,而达到更好的用户体验。那大公司的静态资源是怎么发布的呢?html
如非自建 CDN,推荐 又拍云,阿里云,七牛云。前端
在不修改线上静态资源的状况下,发布新的静态资源。即 CDN 上的静态资源必须共存多个静态资源版本。webpack
负责百度 FIS 的核心功能开发者张云龙已经给出了 部署的方案,非覆盖式发布。他的文中提到:nginx
先部署页面,再部署资源:在两者部署的时间间隔内,若是有用户访问页面,就会在新的页面结构中加载旧的资源,而且把这个旧版本的资源当作新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,不然在资源缓存过时以前,页面会一直执行错误。git
先部署资源,再部署页面:在部署时间间隔以内,有旧版本资源本地缓存的用户访问网站,因为请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种状况下页面展示正常;但没有本地缓存或者缓存过时的用户访问网站,就会出现旧版本页面加载新版本资源的状况,致使页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。github
更新静态资源,只更新修改的部分。不能修改未更新的资源的引用。web
在 CDN 的配置中,会把缓存的时间设置很长。文件的更新就须要一种灵活的机制,也不能每次发布版本就把全部文件更新一遍,全量更新静态资源对于用户和服务提供者来讲都是很是不友好的,极度浪费 CDN 资源和用户的流量。
好比: a.html
页面引用了 100 个静态资源文件,可是本次发版本只修改了一个a.js
文件。那么就只能修改 a.js
文件的引用,可能修改成 a.hash.js
。算法
解决办法:根据文件的内容算出一个值,若是文件内容不改变,那么这个值就不会改变。gulp
张云龙的文章中给出了『精确的缓存控制』的原理————咱们会很天然的联想到利用 数据摘要要算法 对文件求摘要信息,摘要信息与文件内容一一对应,就有了一种能够精确到单个文件粒度的缓存控制依据了。
Grunt,gulp 也有对应的插件用来解决这个问题。若是你使用 webpack,那么能够配置下 chunkhash 或者 hash。更厉害的,文章末尾还有相关的解决方案。
若是咱们把静态资源的实际访问域名设置为 res.company.com
。
功能开发结束后,开发人员把静态资源提交到测试环境 Git 仓库。
测试人员在测试环境经过绑定 host 的方式测试,测试经过后,进入发布阶段,须要静态资源代码提交到产品环境 Git 仓库。(使用测试和产品两个仓库,是为了测试和产品环境彻底隔离)
源站(origin.res.company.com)从产品环境 Git 拉取静态资源的代码,而且为静态资源提供访问服务(nginx 等),该域名不提供文件缓存服务,仅仅做为 CDN 的回源地址。因此代码中必定不要写源站的信息。
在 CDN 服务商提供的空间中,将回源地址配置为源站(origin.res.company.com)。
CDN 服务器会提供一个默认的访问域名,好比 cdn-1.res.cdn_company.com
, 而后把实际需求访问的静态资源域名 res.company.com
CNAME 到 cdn-1.res.cdn_company.com
。
代码发布完毕。用户访问的时候,会访问到最近的 CDN 阶段。CDN 结点去文件中心取文件,若是不存在文件则回源到源站,获取文件。(有些 CDN 产品提供文件存储功能,异地备份)
经过这样的流程,就能让用户访经过 CDN 访问到咱们的实际资源。
结论:咱们会按照目录来划分业务的静态资源。
res.company.com
域名下面会共存多个业务。A 业务、B 业务都是使用一样的发布方案。
好比某静态资源的访问路径为:http://res.company.com/:业务名/js/test.de5b0b0c.js
。
多个团队可使用同一个静态资源仓库,res.git
,而后按照目录来区分业务。web 服务器直接指向到 res/
便可。静态资源更新只须要 pull 代码便可,而不需求作其余改动。
结论:同步源站文件到 CDN 能确保实现非覆盖式发布。
又拍云等 CDN 服务商都提供了这些贴心的服务,就算你提交了新的同名文件,那也是不会生效的。
终端用户就近访问 CDN 加速节点上的资源
若 CDN 加速节点上不存在资源,则回源获取资源
回源获取的资源持久化存储到 CDN
返回资源内容给终端用户
当终端用户再次访问相同的资源时,CDN 的加速节点将直接返回资源内容,不须要从新回源获取
另外我还作了测试,在未作源站迁移的状况下,删掉源站文件,会出现大面积的 404 响应。