手记

webpack 浏览器缓存(16)

获取全套webpack 4.x教程,请访问瓦力博客

小菜之前写过关于浏览器是如何缓存的nginx 缓存{:target="_blank"},感兴趣的小伙伴们可以看看。在前面小菜写的配置都是如何去缓存

//build/output.js

const srcPath = require('./base/path');
const config = require('./base/config');

let output = {
	path: srcPath.dist,
	filename: '[name].[hash].js',
	publicPath: config.publicPath
}

module.exports = output;

如果output.js中这样写filename:'[name].[hash].js',每次打包都会重新生成js文件(文件名不重名),上传到服务器,用户在客户端上刷新都会重新从服务器上拉取js文件,这样就会造成请求资源浪费。

1.演示

安装loadsh

之前没有安装过loadsh库伙伴需要安装一下

yarn add loadsh

index.js

import _ from 'loadsh';

let arr = ['hello','world'];

let str = _.join(arr,'--');
console.log(str)

编译webpack

yarn run prod

修改index.js

import _ from 'loadsh';

+  let arr = ['hello','wali'];

let str = _.join(arr,'--');
console.log(str)

编译webpack

yarn run prod

从上面两个截图可以发现,当我们修改index.js文件的代码后,重新打包生成main.jsvendors~main后面的hash值变了。因为我们修改index.js文件的代码,在index.js中引用的第三方库文件,loadsh是不需修改的,所以打包后我们希望mian.js的hash值变,而vendors~main的hash值不变。

2.配置webpack

为了实现上面的功能,我们需要对webpack配置做一些改变

build/output.js

const dirPath = require('./base/path');
const config = require('./base/config');

let output = {
	path:dirPath.dist,
+	filename: config.NODE_ENV == 'development'?'[name].js':'[name].[contenthash].js',
+	chunkFilename: config.NODE_ENV == 'development'?'[name].js':'[name].[contenthash].js',
	publicPath: config.publicPath
}

module.exports = output

build/optimization.js

let optimization = {
	usedExports: true,
	splitChunks: {
		chunks: 'all',
		minSize: 30000,
		maxSize: 0,
		minChunks: 1,
		maxAsyncRequests: 5,
		maxInitialRequests: 3,
		automaticNameDelimiter: '~',
		name: true,
		cacheGroups: {
			vendors: {
				test: /[\\/]node_modules[\\/]/,
				priority: -10
			},
			default: {
				minChunks: 2,
				priority: -20,
				reuseExistingChunk: true
			}
		}
	},
+	runtimeChunk:{
+		name: entrypoint => `runtimechunk~${entrypoint.name}`
+	}
}

module.exports = optimization

build/plugins.js

const dirpath = require('./base/path');
const config = require('./base/config');

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');    //生成html文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');  //清除
const MiniCssExtractPlugin = require("mini-css-extract-plugin");  //css样式提取


let plugins = [
	new HtmlWebpackPlugin({
		title: '瓦力博客',
		template: dirpath.src + '/index.html'   //以src/index.html为编译模板
	}),
	new  MiniCssExtractPlugin({
		filename: config.NODE_ENV == 'development'?'[name.css]': `${dirpath.css}/[name].[hash].css`,
		chunkFilename: config.NODE_ENV == 'development'?'[id].css': `${dirpath.css}/[id].[hash].css`
	}),   //css提取
	new CleanWebpackPlugin(),
-	new webpack.HotModuleReplacementPlugin()	
]

+ if('development' == config.NODE_ENV){
+	plugins.push(new webpack.HotModuleReplacementPlugin());
+ }

module.exports = plugins;

index.js

import _ from 'loadsh';

let arr = ['hello','world'];

let str = _.join(arr,'--');
console.log(str)

运行webpack

yarn run prod

修改index.js

import _ from 'loadsh';

+ let arr = ['hello','wali'];

let str = _.join(arr,'--');
console.log(str)

运行webpack

yarn run prod

从上面两张截图中可以看出来,当我们修改index.js文件内容。main.js后面的hash值发生改变,vendors~main.js后面hash值保持不变。当用户在浏览页面时,我们修改本地代码,打包上传后,用户刷新浏览器,浏览器只会请求hash改变的js文件,而hash值没变的文件依旧从浏览器缓存读取。

3.总结

写本小节的时候,小菜遇到了两个问题,分享给大家

[contenthash]打包报错

小菜在调式时,直接在build/output.js文件中这样写

let output = {
	path:dirPath.dist,
+	filename: '[name].[contenthash].js',
+	chunkFilename: '[name].[contenthash].js',
	publicPath: config.publicPath
}

在运行yarn run prod报错,报错信息

ERROR in chunk runtimechunk~main [entry]
[name].[contenthash].js
Cannot use [chunkhash] or [contenthash] for chunk in '[name].[contenthash].js' (use[hash] instead)

不能使用[chunkhash][contenthash]在网上找到资料解决连接{:target="_blank"}。在用new webpack.HotModuleReplacementPlugin()热更新插件的时候是不能使用[chunkhash][contenthash],所以小菜build/plugins.js中修改配置,添加了判断,只有在development模式下才在使用new webpack.HotModuleReplacementPlugin(),然后在output.js中添加判断,问题就解决了

const dirPath = require('./base/path');
const config = require('./base/config');

let output = {
	path:dirPath.dist,
+	filename: config.NODE_ENV == 'development'?'[name].js':'[name].[contenthash].js',
+	chunkFilename: config.NODE_ENV == 'development'?'[name].js':'[name].[contenthash].js',
	publicPath: config.publicPath
}

module.exports = output

运行yarn run dev命令本地服务器不来

说起来很搞笑,按道理到上面配置基本都没问题了,小菜就运行yarn run dev启动本地服务,发现页面起不来

这个问题排查了很久,最终发现小菜在build/base/config.js中将

let _mode = process.argv[process.argv.length - 1];
let env = _mode.replace(/--mode=(.+)/g,"$1");

let config = {
	NODE_ENV: env == 'development'?'development':'production',  //development 开发 production 线上
-	publicPath: env == 'development'?'./':'http://www.waliblog.com',
+	publicPath: env == 'development'?'/':'http://www.waliblog.com',
	apiUrl:'http://www.waliblog.com',
	port: 9999
}

module.exports = config;

本地服务路径./弄错了,所以服务起起来但是一直找不到根路径,页面也无法访问。当时这么写是因为想在生成index.html查看路径,后面一直没有改才会碰到这个问题。这个问题找到后,小菜将webpack-14{:target="_blank"}这节配置重新写了一遍,之后又重新跑了一遍,所以小伙伴们可能遇不到我这个问题。

0人推荐
随时随地看视频
慕课网APP