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学习笔记

    版权声明:本博客属于个人维护博客,未经博主允许不得转载其中文章。
  • 相关阅读:
    HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
    二分图最大匹配总结
    HDU 4022 Bombing (STL应用)
    HDU 1847 Good Luck in CET4 Everybody!(组合博弈)
    HDU 1556 Color the ball(树状数组)
    HDU 4023 Game(博弈)
    HDU 1406 完数(水题)
    HDU 4021 24 Puzzle
    Oracle 多表查询优化
    【编程之美】字符串移位包含的问题(续)
  • 原文地址:https://www.cnblogs.com/wsmrzx/p/11503171.html
Copyright © 2011-2022 走看看