webpack学习笔记(六) 缓存

简介: webpack学习笔记(六) 缓存

为什么要使用缓存呢?单就功能来讲,不用缓存也能达到同样的效果,使用缓存的目的其实是为了 提高性能

为此我们必须要确保 webpack 编译生成的文件能被客户端缓存,并且当文件发生变化后,客户端能得到新的文件


1、哈希命名


下面,我们先来搭建一个小小的项目,一步一步说明如何在 webpack 中配置使用缓存

创建一个空文件夹 Demo,作为项目的根目录,然后在该目录中运行以下命令安装依赖

> # 创建 package.json 文件
> npm init -y
> # 安装 webpack
> npm install --save-dev webpack
> npm install --save-dev webpack-cli
> # 安装 lodash 模块
> npm install --save lodash


在根目录下创建 srcdist 文件夹,分别用于存放资源文件和打包之后的输出文件

并在 src 文件夹下创建 index.js 文件,该文件的作用是添加一个 div 元素作为 body 的子节点

import _ from 'lodash';
function component() {
    var element = document.createElement('div');
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    return element;
}
let elem = component();
document.body.appendChild(elem);


之后,我们在根目录下创建一个 webpack.config.js 文件,用于指定 webpack 的一些配置

通过 hash,我们可以使得每次打包生成的文件命名都是唯一的

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    }
};


2、使用 HtmlWebpackPlugin 插件


这里有一个问题,如果每次打包之后生成的文件命名都不一样,那么我们要怎么引用文件呢?

答案是使用 HtmlWebpackPlugin,该插件会自动生成一个 HTML5 文件,动态添加每次编译后引用的资源

首先安装插件

> npm install --save-dev html-webpack-plugin


然后在 webpack.config.js 文件中进行配置

const path = require('path');
// 引入 HtmlWebpackPlugin 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        // 使用 HtmlWebpackPlugin 插件
        new HtmlWebpackPlugin()
    ]
};


3、使用 CleanWebpackPlugin 插件


另外一个问题,如果经过多次修改和打包,由于之前打包生成的文件也会残留下来,所以文件会越堆越多

要怎么解决呢?答案是使用 CleanWebpackPlugin,该插件可以在重新打包时,把没有用的文件自动清除

还是先安装插件

> npm install --save-dev clean-webpack-plugin


然后在 webpack.config.js 文件中进行配置

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入 CleanWebpackPlugin 插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin(),
        // 使用 CleanWebpackPlugin 插件
        new CleanWebpackPlugin()
    ]
};


4、提取模板


有的时候,将第三方库提取到独立的 chunk 文件是比较推荐的做法

因为它们很少被修改,所以利用客户端的长效缓存机制,可以最大限度减少客户端向服务器请求资源的次数

修改 webpack.config.js 文件如下

const path = require('path');
// 引入 webpack 内置插件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    entry: {
        main: './src/index.js',
        // 新增 vender 入口,指定第三方库
        vender: [
            'lodash'
        ]
    },
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        // 将指定的模块分离到单独的文件
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor'
        }),
        new HtmlWebpackPlugin(),
        new CleanWebpackPlugin()
    ]
};


5、使用 NamedModulesPlugin / HashedModuleIdsPlugin 插件


至此,还有最后一个问题,假如我们在 src 目录下添加一个文件 hello.js,文件内容如下

export function SayHello() {
    console.log('Hello World')
}


然后,我们在 src 目录下的 index.js 文件中引用新建的文件,修改 index.js 文件如下

import _ from 'lodash';
import { SayHello } from './hello.js';
function component() {
    SayHello()
    var element = document.createElement('div');
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    return element;
}
let elem = component();
document.body.appendChild(elem);


但是当我们重新打包的时候,却发现之前打包 vender 生成的 bundle 文件的 hash 也发生了改变

这是因为 module.id 会基于默认的解析顺序进行增量,所以 vender 生成的 bundle 文件的 hash 也会因此变化

对于这种情况,webpack 提供两种解决方法

一是使用 NamedModulesPlugin (适合开发环境使,二是使用 HashedModuleIdsPlugin (适合生产环境)

修改 webpack.config.js 文件如下

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    entry: {
        main: './src/index.js',
        vender: [
            'lodash'
        ]
    },
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor'
        }),
        // 使用 HashedModuleIdsPlugin 插件
        new webpack.HashedModuleIdsPlugin(),
        new HtmlWebpackPlugin(),
        new CleanWebpackPlugin()
    ]
};


【 更新:webpack.optimize.CommonsChunkPlugin 已弃用,请使用 config.optimization.splitChunks 】


对于报错信息,不针对上面的例子,下面是一个比较通用的写法

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new webpack.HashedModuleIdsPlugin(),
        new HtmlWebpackPlugin(),
        new CleanWebpackPlugin()
    ],
    optimization: {
        splitChunks: {
            chunks: 'all',  // 可选值有三个,initial(入口)、async(异步)和 all
            minSize: 30000, // 最小尺寸
            minChunks: 1,   // 最小引用次数
            maxAsyncRequests: 5,   // 最大请求异步 chunk 的次数
            maxInitialRequests: 3, // 最大请求入口 chunk 的次数
            cacheGroups: {
                vendor: { // 提取第三方库
                    test: /[\\/]node_modules[\\/]/, // 根据需求修改
                    name: 'vendor',
                },
                common: { // 提取公共文件
                    test: /[\\/]src[\\/]js[\\/]/, // 根据需求修改
                    name: 'common'
                }
            }
        }
    }
};



目录
相关文章
|
2月前
|
缓存 NoSQL 关系型数据库
数据库缓存一致性学习笔记(一)
数据库缓存一致性学习笔记(一)
|
4月前
|
JSON 监控 测试技术
《Webpack5 核心原理与应用实践》学习笔记-> 提升插件健壮性
《Webpack5 核心原理与应用实践》学习笔记-> 提升插件健壮性
53 0
|
4月前
|
缓存 前端开发 API
《Webpack5 核心原理与应用实践》学习笔记-> webpack插件开发基础
《Webpack5 核心原理与应用实践》学习笔记-> webpack插件开发基础
60 0
|
4月前
|
前端开发 JavaScript 测试技术
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader运行与调试
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader运行与调试
34 0
|
4月前
|
存储 缓存 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader开发技巧
《Webpack5 核心原理与应用实践》学习笔记-> webpack的loader开发技巧
43 1
|
4月前
|
缓存 监控 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> webpack极致性能优化
《Webpack5 核心原理与应用实践》学习笔记-> webpack极致性能优化
32 1
|
4月前
|
前端开发 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> webpack代码压缩
《Webpack5 核心原理与应用实践》学习笔记-> webpack代码压缩
44 0
|
4月前
|
监控 IDE 开发工具
《Webpack5 核心原理与应用实践》学习笔记-> webpack性能优化技巧
《Webpack5 核心原理与应用实践》学习笔记-> webpack性能优化技巧
62 0
|
4月前
|
JavaScript 前端开发 API
《Webpack5 核心原理与应用实践》学习笔记-> webpack并行构建
《Webpack5 核心原理与应用实践》学习笔记-> webpack并行构建
64 0
|
4月前
|
存储 缓存 前端开发
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
67 1

热门文章

最新文章