zoukankan      html  css  js  c++  java
  • 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'
                    }
                }
            }
        }
    };
    

    【 阅读更多 webpack 系列文章,请看 webpack学习笔记

    版权声明:本博客属于个人维护博客,未经博主允许不得转载其中文章。
  • 相关阅读:
    java实现打印倒直角三角形
    java实现打印倒直角三角形
    java实现打印倒直角三角形
    java实现打印直角三角形
    java实现打印直角三角形
    java实现打印直角三角形
    计算一个班的平均分
    计算一个班的平均分
    计算一个班的平均分
    Creating a Message Queue in PHP Without External Libraries
  • 原文地址:https://www.cnblogs.com/wsmrzx/p/11503171.html
Copyright © 2011-2022 走看看