Fork me on GitHub

webpack13--webpack与浏览器缓存

webpack与浏览器缓存

我们先修改一波index.js里面的代码:

1
2
3
4
5
6
import _ from 'lodash';
import $ from 'jquery';
const dom = $('<div>');
dom.html(_join(['wd','lj']),'-')
$('body').append(dom);

然后我们执行打包命令npm run build

会发现有警告,提示我们打包的文件内容太大(同时引入lodash和jquery会使得体积过大),这里我们去webpack.common.js里面配置一波,在里面添加一项叫做performance:false,让webpack打包的时候不要提示我们关于性能的问题.

这里为了便于学习,我们把prod配置里面的source-map也给注释掉,然后会发现打包出来两个js文件:main.jsvendors~main.js

重新在common.js里面配置一波打包生成文件的名称:

1
2
3
4
5
6
7
8
9
10
splitChunks: { // 代码分割的配置
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name:'vendors'
},
}
}

这样打包就会生成main.jsvendors.chunk.js

然后我们把dist目录下面的的文件部署到服务器上面.

缓存问题

这之后如果要我们要修改index.js里面的代码,然后重新打包生成同样的js文件,我们再次把他们部署到服务器上面去的话,这时用户访问到的页面仍然是原来的页面.

为了解决这个缓存问题,我们可以引入一个概念叫做content-hash,我们先把webpack.common.js里面的output输出文件项剪切掉,然后去dev和prod环境里面分别重新配置一波output输出项

开发环境因为有热模块更新,所以不用配置hash值
webpack.dev.js

1
2
3
4
output:{
filename: '[name].js',
chunkFilename: '[name].chunk.js',
}

但是prod因为要部署到线上去,所以要设置一波hash值

webpack.prod.js

1
2
3
4
output:{
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
}

这样每次打包出来的js文件都会和上一次不同,就可以解决之前的缓存问题.

这里对于webpack的老用户来说,你没有修改源代码,但是两次npm run build出来的结果却可能是不一样的,这个时候就需要做一些配置.

在common的optimization配置项里面加上一个runtimeChunk配置项

1
2
3
runtimeChunk:{
name:'runtime'
},

Shimming的使用(垫片)

在webpack打包过程中,我们经常要做一些代码的兼容和打包过程的兼容(利用之前的profill.js,为了解决Promise不支持低版本浏览器),其实这就是一个webpack的垫片.

我们这里举个例子:
新建一个ui.js

1
2
3
export function ui (){
$('body').css('background','red');
}

在index.js里面使用一波

1
2
3
4
5
6
7
8
9
import _ from 'lodash';
import $ from 'jquery';
import { ui } from './jquery.ui';
ui();
const dom = $('<div>');
dom.html(_.join(['wd' , 'lj'],'--'));
$('body').append(dom);

然而当我们运行npm run server的时候会发现页面上的内容并没有正确的显示,原因是ui里面的$符号并不存在.(jquery这个模块里面的东西不会到ui这个函数里面去,我们要使用就得自己引入)

这里我们去common.js里面配置一波垫片

1
2
3
4
5
const webpack = require('webpack');
// ...some code
new webpack.ProvidePlugin({
$:'jquery'
}),

这个时候再去运行npm run dev,就可以使用了.

如果我们想让我们所有模块里面的this指向为指向window,我们需要新安装一个loader(一般默认this的指向会指向当前这个模块)

npm install imports-loader -D

1
2
3
4
5
6
7
8
9
{
test: /\.js$/,
exclude:/node_modules/,
use: [{
loader:'babel-loader'
},{
loader:'imports-loader?this=>window'
}]
},

这个时候当我们打包js的时候,js文件里面的this指向都会指向window

我们在index.js里面

1
console.log(this===window); // true

这个值就为true了.

环境变量的使用

我们把之前在webpack.dev.jswebpack.prod.js里面配置的一些merge参数直接删除掉.
直接在webpack.common.js里面去进行全局的相关环境的配置.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// webpack.dev.js
module.exports = devConfig;
// webpack.prod.js
module.exports = prodConfig
// webpack.common.js
const merge = require('webpack-merge');
const devConfig = require('./webpack.dev.js');
const prodConfig = require('./webpack.prod.js')
const commonConfig = {
// ... some codes...
}
module.exports = (env) =>{
if(env&&env.production){
return merge(commonConfig,prodConfig);
}else {
return merge(commonConfig,devConfig);
}
}

然后通过配置package.json里面的打包启动参数来改变相对应的值

1
2
3
4
5
"scripts": {
"dev-build": "webpack --config ./build/webpack.common.js",
"dev": "webpack-dev-server --config ./build/webpack.common.js",
"build": "webpack --env.production --config ./build/webpack.common.js"
},

对于dev-build和dev我们是不必往里面传一些相对应的值的,因为这个时候env为空,它会自动去往devConfig这个里面去进行合并,而对于线上环境而言,我们在里面给定相对应的参数env.production,这样在运行上线打包命令的时候就回去合并相对应的prodConfig文件.

这里我们也可以在env.production的后面加上一些参数,--env.prod==abc,然后在webpack.common.js那边进行一系列的判断即可.

-------------本文结束感谢您的阅读-------------