媒介
webpack,作为一个处置惩罚模块加载、资本依靠治理、构建化的东西,已逐步成为了前端工程化范畴的新贵。其创造性的把每一个静态资本归为一个 module(模块)并能被其壮大的 loader 所加载的这类体式格局,胜利的拓荒了前端工程界的另一大生态。基于其官网文档的圆满度较高,这篇文章就不对 webpack 的主要内容做过量的引见,而是回归到本文的主题,即经由过程引见几款 webpack 相干的插件,来处理一个罕见的工程题目:如何做到静态资本途径可以在差别的环境下自动切换。
题目申明
这究竟是个如何的题目?设想一下,在运用 webpack 打包编译以后,它会天生一个 js 文件,随后我们须要在 html 或许模板文件里指定这个文件的途径确保其被准确的引入,
<script type="javascript" src="app.js"></script>
关于开辟环境下的单进口文件(稍后会引见 webpack 打包到多个进口的处理方案 ),这个标签内的引入文件途径完全可以写死,而且在 webpack-dev-server 热替代机制的协助下,我们也不必经由过程对打包天生的文件增加 hash 值来处置惩罚因浏览器缓存的原因引发的援用不到最新资本。
但在产物形式下,我们异常有必要在 webpack 的 output 属性里的 filename 里设置一个 chunkhash 来变向的为静态资本注入版本号,以下,
output: {
filename: [name].[chunkhash].js,
}
以便上线以后页面可以引入版本更新后的代码。chunkhash 是一个基于文件内容,经由过程择要算法(如md5)天生的一个被称之为文件指纹
的序号,即只有当文件内容发作转变的时刻,这个值才会响应变动。
经由过程给静态资本注入 hash 值来作为版本号的优点主要有两个:
完成 long term caching 战略。当宣布新版本时,我们只须要更新变动了的资本。这比起将新版资本存放在比方
/v1.3/xx.js
这类带版本号的途径或文件夹下的布置体式格局会显得更科学一点:削减手动设置版本号的分外操纵、已缓存过且缓存还没有逾期的浏览器只须要求更新过的资本,确保未变动过的资本可以照旧从缓存内读取。完成非掩盖式宣布战略。张云龙先生的原文中提到的这类腻滑的版本晋级体式格局越发圆满的处理了静态资本布置至CDN涌现的题目。
这个时刻我们再来看下线上的 script 引入,
<script type="javascript" src="http://xxx.cdn.com/app.82076244596568c8c929.js
"></script>
Fine, 或许你会说我可以手动 copy/paste 这个版本号当你须要从开辟切到产物环境,额额,单个进口文件这么处置惩罚虽是可以,但设想下当有多个进口文件的时刻。。。(认为我的左手大拇指肌腱炎又要犯了。。),这么典范的题目webpack早已预备好了它的处理方案。
从 webpack 的编译数据里猎取开辟与临盆的资本途径对应关联
这一部份的事情可以说是处理这个题目的一个中心环节,即我们须要经由过程 webpack 来天生相似以下一张对应关联图:
{
'app.js': 'http://xxx.cdn.com/app.82076244596568c8c929.js'
}
像在 webpack 的 plugin 属性里设置以下,我们就可以经由过程返回 webpack 的编译数据里猎取到带有 chunkhash 的文件信息:
// webpack.config.js
module.exports = {
...
plugins: [
function() {
this.plugin("done", function(stats) {
require("fs").writeFileSync(
path.join(__dirname, "..", "stats.json"),
JSON.stringify(stats.toJson()));
});
}
]
}
将 stats.json
require 到项目中,经由过程读取 publicPath
、 assetsByChunkName
属性,可以获得开辟与线上环境资本途径的对应关联。
webpack 官方也引荐了几个有一样结果,我个人认为更好用的插件:assets-webpack-plugin 或许 webpack-manifest-plugin 来天生出一个 JSON 对应关联文件。
切换资本途径
接下来的事情基本上就是如何应用这个对应关联来切换对应环境下的途径。这个还要取决于你的页面是不是会涉及到服务端的衬着。
服务端衬着资本途径
以 node 作为服务端言语,handlebars(或许ejs)为模板言语为例,我们经由过程编写模板言语的 helper 来读取由 assets-webpack-plugin
天生的 stats.json,在差别的环境下完成途径切换:
stats.json — webpack 跑开辟设置
{
"app": {
"js": "app.js"
}
}
stats.json — webpack 跑临盆设置
{
"app": {
"js": "http://xxx.cdn.com/app.82076244596568c8c929.js"
}
}
example.handlebars
<script type="text/javascript" src="{{app.js}}"></script>
背景经由过程 require stats.json
数据并传入到模板即可完成依据环境动态衬着资本途径。
假如你的背景是运用 Rails 来搭建的话,那末这篇文章更细致的引见了处置惩罚这类状况下处置惩罚资本切换的题目
前端衬着页面模板
假如你的项目不依靠任何后端衬着,那末 html-webpack-plugin
这款插件可以为你动态天生一个带有 css、js 等资本途径的 html 文件。
html-webpack-plugin
详细的用法可以点击这里,个中 inject
这个属性可以让你将 script 标签插进去到 dom 的指定位置。为了可以更大权限的将 webpack 编译过的资本可以插进去到 html 文件的恣意位置,我们可以在 HtmlWebpackPlugin
里指定的 template 文件里写入以下代码:
<% for (var css in htmlWebpackPlugin.files.css) { %>
<link href="<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
<% } %>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script src="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>
就可以一样完成静态资本的切换,所以关于前端衬着模板的这类状况,我们不必再天生一个 json 文件,关于运用诸如 react、vue 这类框架,仅运用这个插件也是极好的。
htmlWebpackPlugin
详细另有哪些属性可以设置,可以参考下这个 default template 检察完全例子