webapck 4.x

webpack 浏览器缓存(16)

2019-06-12  本文已影响6人  瓦力博客

获取全套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
ssl

修改index.js

import _ from 'loadsh';

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

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

编译webpack

yarn run prod
ssl

从上面两个截图可以发现,当我们修改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
ssl

修改index.js

import _ from 'loadsh';

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

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

运行webpack

yarn run prod
ssl

从上面两张截图中可以看出来,当我们修改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启动本地服务,发现页面起不来

ssl ssl

这个问题排查了很久,最终发现小菜在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"}这节配置重新写了一遍,之后又重新跑了一遍,所以小伙伴们可能遇不到我这个问题。

上一篇下一篇

猜你喜欢

热点阅读