webpack与浏览器缓存(caching)
我们使用 webpack 来打包我们的模块化后的应用程序,webpack 会生成一个可部署的 /dist 目录,然后把打包后的内容放置在此目录中。只要 /dist 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 缓存 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快,然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。
[contenthash]
将根据资源内容创建出唯一 hash。当资源内容发生变化时,[contenthash]
也会发生变化。
module.exports = {
...
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
};
Shimming的作用
Shimming 预置全局变量
webpack
compiler 能够识别遵循 ES2015 模块语法、CommonJS 或 AMD 规范编写的模块。然而,一些 third party(第三方库) 可能会引用一些全局依赖(例如 jQuery
中的 $
)。因此这些 library 也可能会创建一些需要导出的全局变量。这些 "broken modules(不符合规范的模块)" 就是 shimming(预置依赖) 发挥作用的地方。
不推荐使用全局依赖!webpack 背后的整个理念是使前端开发更加模块化。也就是说,需要编写具有良好的封闭性(well contained)、不依赖于隐含依赖(例如,全局变量)的彼此隔离的模块。请只在必要的时候才使用这些特性。
之前用过的 lodash
,例如把这个应用程序中的模块依赖,改为一个全局变量依赖。要实现这些,需要使用 ProvidePlugin
插件。
使用 ProvidePlugin
后,能够在 webpack 编译的每个模块中,通过访问一个变量来获取一个 package。如果 webpack 看到模块中用到这个变量,它将在最终 bundle 中引入给定的 package。让移除 lodash
的 import
语句,改为通过插件提供它:
index.js
function component() {
const element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.ProvidePlugin({
_: 'lodash',
}),
],
};
我们本质上所做的,就是告诉 webpack 遇到了至少一处用到 _
变量的模块实例,就将 lodash
包引入进来,并将其提供给需要用到它的模块。
还可以使用 ProvidePlugin
暴露出某个模块中单个导出,通过配置一个“数组路径”(例如 [module, child, ...children?]
)实现此功能。所以,假设,无论 join
方法在何处调用,我们都只会获取到 lodash
中提供的 join
方法。
index.js
function component() {
const element = document.createElement('div');
element.innerHTML = join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.ProvidePlugin({
join: ['lodash', 'join'],
}),
],
};
这样就能很好的与 tree shaking 配合,将 lodash
库 中的其余没有用到的导出去除。
细粒度Shimming 更改 this 指向
一些模块的 this
指向的是模块自身而不是全局的 window 对象
index.js
console.log(this)
通过使用 imports-loader
覆盖 this
指向
安装 imports-loader
npm install imports-loader --save-dev
webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: require.resolve('index.js'),
use: 'imports-loader?this=>window'
}
]
},
plugins: [
new webpack.ProvidePlugin({
join: ['lodash', 'join']
})
]
};