Open johnnychq opened 6 years ago
本文针对的阅读对象是想系统了解时间戳机制,对应部署机制,尤其是与HTML结合部分的同学,需要对前端运维有一定了解。
关于前端资源时间戳问题,知乎上有个经典的回答 大公司里怎样开发和部署前端代码,详细讲述了,时间戳问题的起因以及对应2种解决方案:
手动维护时间戳
信息摘要时间戳
以及在静态资源部署在cdn情况下覆盖式发布和非覆盖式发布
覆盖式发布
非覆盖式发布
不过,答案中未对时间戳如何更新到HTML中作详细的介绍,本文主要讲解这个HTML及其时间戳部署问题及解决方案
HTML及其时间戳部署
接下来的讨论,假定用的是信息摘要时间戳以及非覆盖式发布机制
非覆盖式发布机制
时间戳部署问题,指的是将生成的时间戳更新到对应HTML的资源引用链接当中,当资源内容发生变化后,通过工程化的手段,自动更新对应的时间戳。
<link rel="stylesheet" href="http://static.xxx.com/a_{timestamp}.css"/> <script src="http://static.xxx.com/a_{timestapm}.js"></script>
页面刷新时,用户永远能够访问到最新的文件内容,即通过一种机制让timestamp永远保持最新。
timestamp
不同条件下的部署方案是不同的,主要受 HTML存储在哪里,HTML部署的哪里,解决过程采用编译时还是运行时三方面的影响。
HTML存储在哪里
HTML部署的哪里
解决过程采用编译时还是运行时
这里的HTML存储的哪里指的是在代码托管上,HTML(也可能是服务端模板)是否与静态资源(js/css/img)在同一个代码仓库中。不关心HTML是否是服务端(java/php/nodejs)模板生成,只要是在同一个代码仓库,文件层面上在一起即可。
HTML存储的哪里
是否在同一代码仓库中非常重要,因为如果是,那么在文件目录结构上HTML与资源具有物理上的关联,那么在生成文件时间戳的同时可以根据关联关系立即更新/部署对应HTML的时间戳;否的话,必须提供一种异步机制,让二者产生关联。
传统/全栈开发
纯粹的前后端分离
传统的前后端分离
HTML与静态资源如果不在同一个仓库时,必须建立一个中间存储机制,保存静态资源文件对应的时间戳,然后在HTML编译或运行时环境中,获取并匹配中间存储对应的时间戳进行更新/部署。
幸运的是,现在主流的研发模式里,越来越推崇全栈或纯粹的前后端分离了,两种方式都极大的简化了时间戳的部署方式。尤其是后者,更加简单,Webpack提供了专门的html插件,自动创建html的同时帮你完成时间戳部署的事情。
全栈
在传统开发中,HTML均以服务端模板的方式存在于应用服务器中,通过域名www.xxx.com即可访问。其中,静态资源如果同机部署的话,也可以用www.xxx.com进行访问;如果静态资源分开部署到了oss/cdn中的话,则用要用static.xxx.com访问,但不影响用www.xxx.com访问HTML。
www.xxx.com
static.xxx.com
但在纯粹的前后端分离方案中,如果把HTML当做普通静态资源部署到oss/cdn中的话,就只能通过static.xxx.com/index.html访问到HTML文件,这对用户极其不友好,我们传达给用户的域名应该是www.xxx.com;另外,也无法做不同路径url映射同一个html的功能(browserHistory)。所以需要对这种情况下的HTML部署做特殊处理。
static.xxx.com/index.html
纯粹的前后端分离在部署时,将HTML作为特殊静态资源,单独打包部署到nginx中;其他资源单独部署到oss/cdn中。这个主要影响的是打包和部署策略,跟运维同学沟通清楚即可。
上述问题只会存在于将普通静态资源单独部署到oss/cdn情况,且采用纯粹的前后端分离方案下,其他情况不存在此问题。但因为纯粹的前后端分离是当下主流的研发模式,且涉及运维层面(前端对运维可能不是特别清楚),因此单独提出来。
能够预编译解决的问题,尽可能的不要选择运行时,让生产环境保持简单意味着生产环境更加稳定和高效。
代码的上线过程:开发 -> 发布 -> 运行,时间戳的部署可以选择在发布过程中的预编译环节,也可以在运行时解决,优先选择编译时。
在HTML存储在哪里小节中其实已经讲过了,如果HTML与静态文件在同一仓库,那么预编译时,在生成静态文件时间戳的同时,根据仓库的文件路径关系,找到对应的HTML页面,更新/部署对应的时间戳即可。所以全栈开发, 纯粹前后端分离开发的同学尽情享用这种方式把。
全栈开发
纯粹前后端分离
如果HTML与静态文件隶属不同仓库,就麻烦了,那先编译生成静态文件时间戳并存储到中间存储;再编译HTML,与此同时获取刚才中间存储中的最新时间戳;最后更新/部署HTML中的时间戳。不过这里有个缺点:编译时序依赖,要求你在发布前,要严格保证发布的顺序,先发布前端仓库,后发布后端。人肉保证比较困难,系统保证感觉有点重,自己权衡把。
编译时序依赖
运行时动态获取最新时间戳可以解决编译时序依赖问题,但必须通过模板宏及运行时获取中间存储时间戳的机制,增加了生产环境的复杂度。
运行时
前文讲解偏理论,本文看下常见前后端开发模式下的具体案例,假定前端资源基于webpack。
此模式下,HTML与静态资源统一存放,部署时假定要求cdn,无视服务端代码是否同一仓库
html-webpack-plugin
dist
html.zip
static.zip
server.zip
step3, step5需要特别关注。
此模式下,HTML在服务端,服务端与前端代码同一仓库,是否部署cdn无所谓
step3需要特别关注。另外传统开发模式(非前后端分离)下也是此过程。
此模式下,HTML在服务端,服务端与前端代码不同仓库,是否部署cdn无所谓
timestamp.server
step2,3,4需要特被关注,尤其是需要保证编译的顺序
此模式下,HTML在服务端,服务端与前端代码不同仓库,是否部署cdn无所谓,运行时方案
step8是关键。
关于时间戳
关于前端资源时间戳问题,知乎上有个经典的回答 大公司里怎样开发和部署前端代码,详细讲述了,时间戳问题的起因以及对应2种解决方案:
手动维护时间戳
信息摘要时间戳
以及在静态资源部署在cdn情况下
覆盖式发布
和非覆盖式发布
不过,答案中未对时间戳如何更新到HTML中作详细的介绍,本文主要讲解这个
HTML及其时间戳部署
问题及解决方案关于HTML及其时间戳
时间戳部署问题,指的是将生成的时间戳更新到对应HTML的资源引用链接当中,当资源内容发生变化后,通过工程化的手段,自动更新对应的时间戳。
页面刷新时,用户永远能够访问到最新的文件内容,即通过一种机制让
timestamp
永远保持最新。影响部署方案的三个方面
不同条件下的部署方案是不同的,主要受
HTML存储在哪里
,HTML部署的哪里
,解决过程采用编译时还是运行时
三方面的影响。HTML存储在哪里
这里的
HTML存储的哪里
指的是在代码托管上,HTML(也可能是服务端模板)是否与静态资源(js/css/img)在同一个代码仓库中。不关心HTML是否是服务端(java/php/nodejs)模板生成,只要是在同一个代码仓库,文件层面上在一起即可。是否在同一代码仓库中非常重要,因为如果是,那么在文件目录结构上HTML与资源具有物理上的关联,那么在生成文件时间戳的同时可以根据关联关系立即更新/部署对应HTML的时间戳;否的话,必须提供一种异步机制,让二者产生关联。
传统/全栈开发
,所有代码均在一起,包括html和静态资源纯粹的前后端分离
,指除了数据/渲染上的前后端分离外,对应的HTML本身也在源码管理及部署层面上与后端应用进行剥离,作为资源交由前端进行管理。传统的前后端分离
,指对数据/渲染进行前后端分离,但HTML还存在方后端模板中HTML与静态资源如果不在同一个仓库时,必须建立一个中间存储机制,保存静态资源文件对应的时间戳,然后在HTML编译或运行时环境中,获取并匹配中间存储对应的时间戳进行更新/部署。
幸运的是,现在主流的研发模式里,越来越推崇
全栈
或纯粹的前后端分离
了,两种方式都极大的简化了时间戳的部署方式。尤其是后者,更加简单,Webpack提供了专门的html插件,自动创建html的同时帮你完成时间戳部署的事情。HTML部署的哪里
在传统开发中,HTML均以服务端模板的方式存在于应用服务器中,通过域名
www.xxx.com
即可访问。其中,静态资源如果同机部署的话,也可以用www.xxx.com进行访问;如果静态资源分开部署到了oss/cdn中的话,则用要用static.xxx.com
访问,但不影响用www.xxx.com访问HTML。但在
纯粹的前后端分离
方案中,如果把HTML当做普通静态资源部署到oss/cdn中的话,就只能通过static.xxx.com/index.html
访问到HTML文件,这对用户极其不友好,我们传达给用户的域名应该是www.xxx.com
;另外,也无法做不同路径url映射同一个html的功能(browserHistory)。所以需要对这种情况下的HTML部署做特殊处理。纯粹的前后端分离
在部署时,将HTML作为特殊静态资源,单独打包部署到nginx中;其他资源单独部署到oss/cdn中。这个主要影响的是打包和部署策略,跟运维同学沟通清楚即可。上述问题只会存在于将普通静态资源单独部署到oss/cdn情况,且采用
纯粹的前后端分离
方案下,其他情况不存在此问题。但因为纯粹的前后端分离
是当下主流的研发模式,且涉及运维层面(前端对运维可能不是特别清楚),因此单独提出来。解决过程采用编译时还是运行时
代码的上线过程:开发 -> 发布 -> 运行,时间戳的部署可以选择在发布过程中的预编译环节,也可以在运行时解决,优先选择编译时。
在
HTML存储在哪里
小节中其实已经讲过了,如果HTML与静态文件在同一仓库,那么预编译时,在生成静态文件时间戳的同时,根据仓库的文件路径关系,找到对应的HTML页面,更新/部署对应的时间戳即可。所以全栈开发
,纯粹前后端分离
开发的同学尽情享用这种方式把。如果HTML与静态文件隶属不同仓库,就麻烦了,那先编译生成静态文件时间戳并存储到中间存储;再编译HTML,与此同时获取刚才中间存储中的最新时间戳;最后更新/部署HTML中的时间戳。不过这里有个缺点:
编译时序依赖
,要求你在发布前,要严格保证发布的顺序,先发布前端仓库,后发布后端。人肉保证比较困难,系统保证感觉有点重,自己权衡把。运行时
动态获取最新时间戳可以解决编译时序依赖
问题,但必须通过模板宏及运行时获取中间存储时间戳的机制,增加了生产环境的复杂度。常见开发模式下的HTML及其时间戳部署
前文讲解偏理论,本文看下常见前后端开发模式下的具体案例,假定前端资源基于webpack。
纯粹前后端分离
html-webpack-plugin
自动生成htmldist
编译后资源(包括html)html.zip
static.zip
server.zip
html.zip
解压缩到nginx静态资源目录,自行配置nginx转发规则static.zip
发布到oss,cdn会自动回源server.zip
进行部署step3, step5需要特别关注。
传统前后端分离(同一仓库)
dist
编译后资源(包括html)static.zip
server.zip
static.zip
进行部署server.zip
进行部署step3需要特别关注。另外传统开发模式(非前后端分离)下也是此过程。
传统前后端分离(分开仓库/编译时)
dist
编译后资源(包括html)timestamp.server
中timestamp.server
取回最新时间戳,进行编译。static.zip
server.zip
static.zip
进行部署server.zip
进行部署step2,3,4需要特被关注,尤其是需要保证编译的顺序
传统前后端分离(分开仓库/运行时)
dist
编译后资源(包括html)timestamp.server
中static.zip
server.zip
static.zip
进行部署server.zip
进行部署timestamp.server
中的最新时间戳,实时编译生成最终htmlstep8是关键。