• webpack独立打包与缓存处理


    关于

    前言

    先前写了一篇webpack入门的文章《webpack入门必知必会》,简单介绍了webpack拆分、打包、压缩的使用方法。本文将在上篇文章的基础上进一步讲解在使用webpack构建的项目中存在的优化方案与解决方法。

    上篇文章中写了一份webpack最基本的配置文件来打包压缩我们的代码:

    var path = require('path');
    
    module.exports = {
      entry: './app/index.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      }
    }
    

    在入口文件index.js中我们引入了jQuery:

    // index.js
    var $ = require('jquery');
    var str = require('./hello.js');
    
    function main() {
        $('body').html(str);
    }
    
    main();
    

    这样我们虽然能够实现代码的统一打包,将jQuery、index.js、hello.js统统打包到了bundle.js里,但是会存在一个问题:每次打包都会生成一个体积较大的新bundle.js,浏览器无法缓存像jQuery这样的基本不会改动的框架库代码文件,影响加载速度。

    发现问题我们就来解决问题,我们最终希望的是将像jQuery这样的框架库代码与项目自身的代码分开打包,生成一个独立的打包文件,缩减单个文件体积,浏览器也不用每次都进行加载。

    步骤

    1.独立打包

    为了解决上述问题,我们需要修改我们的webpack配置文件:

    var webpack = require('webpack');
    var path = require('path');
    
    module.exports = {
        entry: {
            main: './app/index.js',
            vendor: ['jquery']
        },
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor'
            }),
        ]
    }
    

    上方我们将原本的单入口文件改成了多入口文件,并加入了vendor属性。vendor属性用于配置打包第三方类库,写入数组的类库名将统一打包到一个文件里。

    同时我们将输出的filename用[name]变量来自动生成文件名,最后我们添加了一个CommonsChunkPlugin的插件,用于提取vendor。

    配置完成后我们运行webpack命令:

    Hash: ee1daf95c1986768927a
    Version: webpack 2.3.2
    Time: 573ms
            Asset       Size  Chunks                    Chunk Names
          main.js  340 bytes       0  [emitted]         main
    vendor.js     274 kB       1  [emitted]  [big]  vendor
       [0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
       [1] ./app/hello.js 53 bytes {0} [built]
       [2] ./app/index.js 114 bytes {0} [built]
       [3] multi jquery 28 bytes {1} [built]
    

    最终发现我们成功将jQuery打包到了vendor.js中,实现了独立打包,但是问题又来了:每次打包后生成的文件名都是一样的,浏览器可能缓存上一次的结果而无法加载最新数据。

    2.添加hash

    为了解决上述问题,我们需要为打包后的文件名添加hash值,这样每次修改后打包的文件hash值将改变,修改配置文件如下:

    module.exports = {
        ...
            output: {
                filename: '[name].[chunkHash:5].js',
                path: path.resolve(__dirname, 'dist')
            },
        ...
    }
    

    上方我们在输出文件名中增加了[chunkHash:5]变量,表示打包后的文件中加入保留5位的hash值。我们再次运行打包命令:

    Hash: c7d1295f2f9a27c412d2
    Version: webpack 2.3.2
    Time: 603ms
              Asset       Size  Chunks                    Chunk Names
      main.2a7ad.js  337 bytes       0  [emitted]         main
    vendor.49eb4.js     274 kB       1  [emitted]  [big]  vendor
       [0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
       [1] ./app/hello.js 50 bytes {0} [built]
       [2] ./app/index.js 114 bytes {0} [built]
       [3] multi jquery 28 bytes {1} [built]
    

    上方我们发现打包后的文件成功加上了hash值,这样每次修改文件后hash值也会跟着变,就不怕浏览器缓存了,但是当我们尝试去修改一个js文件后再次打包,问题又来了:vendor.js的hash值也变了,我们并没有修改jQuery的源码。

    3.修改vendor配置

    上述问题产生的原因是因为CommonsChunkPlugin插件是用于提取公共代码的,上方我们只是提取了vendor作为公共代码。为了继续解决上述问题,其实方法很简单,我们需要修改CommonsChunkPlugin的配置,如下:

    module.exports = {
        ...
            plugins:[
                new webpack.optimize.CommonsChunkPlugin({
                    names: ['vendor', 'manifest']
                }),
            ]
        ...
    }
    

    如此我们修改一下hello.js中的代码,发现vendor的hash值并未改变,并且多了一个manifest.js的小文件。manifest.js为webpack的启动文件代码,它会直接影响到hash值,用mainfest单独抽出来了,这样vendor的hash就不会变了。

    4.生成index.html

    通过以上对webpack配置文件的一系列修改,我们成功实现了webpack的独立打包与缓存处理,但是还差最后一步。

    因为我们最终打包后生成的文件名中带有hash值,每次都是会变的,所以我们不能像目前这样在index.html中写死路径。

    index.html

    ...
    <body>
        <script src="./dist/main.js"></script>
        <script src="./dist/vendor.js"></script>
        <script src="./dist/manifest.js"></script>
    </body>
    ...
    

    以上写法是不对的,因为缺少了可变的hash值,因此我们希望每次打包后index.html中的路径也会自动加上hash值,解决方法如下:

    var HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        ...
            plugins:[
                ...
                new HtmlWebpackPlugin({
                    title: 'demo',
                    template: 'index.html' // 模板路径
                }),
                ...
            ]
        ...
    }
    

    上方我们引入了html-webpack-plugin这一个插件,该插件可以帮助我们根据模板生成html文件。在plugins设置中,title配置了生成html中的title部分,template为模板html的路径地址。

    我们需要下载html-webpack-plugin:

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

    安装和配置完毕后,运行打包命令:webpack

    Hash: 0c4b91e206579b31544d
    Version: webpack 2.3.2
    Time: 856ms
                Asset       Size  Chunks                    Chunk Names
      vendor.e1868.js     268 kB       0  [emitted]  [big]  vendor
        main.44412.js  337 bytes       1  [emitted]         main
    manifest.ed186.js    5.81 kB       2  [emitted]         manifest
           index.html  292 bytes          [emitted]
       [0] ./~/jquery/dist/jquery.js 267 kB {0} [built]
       [1] ./app/hello.js 50 bytes {1} [built]
       [2] ./app/index.js 114 bytes {1} [built]
       [3] multi jquery 28 bytes {0} [built]
    

    我们发现在dist目录下生成了一个index.html文件,打开该文件后代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>demo</title>
    </head>
    <body>
    <script type="text/javascript" src="manifest.ed186.js"></script>
    <script type="text/javascript" src="vendor.e1868.js"></script>
    <script type="text/javascript" src="main.44412.js"></script>
    </body>
    </html>
    

    至此我们实现了每次打包后index.html中的路径也会自动加上hash值的功能,因此dist目录下的index.html即为以后的首页文件,最后我们在浏览器中打开该文件成功显示:

    结语

    本文在webpack入门的基础上讲解了webpack独立打包与缓存处理的方式,实例代码已上传我的github,地址为:https://github.com/luozhihao/webpack-course/tree/master/vendor, 供参考。

  • 相关阅读:
    spring boot , spring security 安全的认证
    C# 插件编写
    linux diff命令详解 和 patch命令
    nginx location 匹配规则
    LVM扩容报错以及 xfs_growfs 和 resize2fs 区别
    shell ps命令 以及 ps命令 进程时间 格式转换
    shell ls 命令
    Ajax类库需要注意的问题
    JS中的基本运动逻辑思想总结
    Ajax读取文件时出现的缓存问题
  • 原文地址:https://www.cnblogs.com/luozhihao/p/6623819.html
Copyright © 2020-2023  润新知