开发、生产环境的拆分代码

    目前我们打包的 js 代码,都在一个文件内,这会让这个文件变得非常大;项目中不可避免要使用第三方库,比如:Jquery react vue 等等,这些在项目上线后,依然需要依赖的库相关的 JS 代码,我们需要单独拆分出来,并打包到一个文件内,这些代码因为基不会发生改变,所以单独分离出来,因为有了缓存的缘故,也能加快编译速度。项目中一段代码在很多页面都有调用,这部分代码也需要拆分出来,单独生成一个文件。

一:单独打包

(1)修改webpack.test.conf.js的entry如下:
entry:{
    app:[path.resolve(__dirname, 'src/index.js')],
    vendor: ["jquery","vue",'vue-router']
},
 

先将jquery,vue,vue-router这三个项目依赖打包到一个文件中去,执行npm test。配置BundleAnalyzerPlugin,终端中会输出这样一句话Webpack Bundle Analyzer is started at http://127.0.0.1:9528 。在浏览器中打开这个链接地址,就可以看到打包的项目各js文件中的依赖关系,可以看到在vendor.js和app.js中都打包了jquery,这说明我们的打包是正确的,app.js中没有vue 是因为在页面中并没有引入vue,实际项目是肯定会引入的。
我们需要实现的是:vendor.js中存放所有我们引入的第三方库,而其他页面中的js文件不再再次打包这些文件,这样才是正确的打包。

 

(2)修改webpack.test.conf.js文件,添加optimization的配置:

optimization: {
    splitChunks: {
        cacheGroups: {
            a: {
                chunks:'initial',
                test: /[\\/]node_modules[\\/]/,
                name: 'vendor',
                priority: 10,
                enforce: true,
            },
        }
    },
    // runtimeChunk: {
    //     name: 'manifest'
    // },
},

再次运行npm test 控制台可以看到前后两次打包的app.js和vendor.js的体积大小,打开http://127.0.0.1:9528看文件依赖关系,一目了然,app.js已经没有了jquery。从控制台看两次打包文件后缀的hash值可以发现,两次打包的hash值都发生了变化,但是其实并没有修改任何js文件,hash值的变化,说明webpack每次都重新打包了这些js文件,但是我们没有做修改的文件,再次打包,那就是在浪费时间,项目大的话,打包速度可能会非常非常慢,这里我们要实现每次只打包有修改的文件,未做修改的文件,依然沿用上次打包的文件。
       我们取消对optimization.runtimeChunk的注释,先运行一遍npm test,可以看到,这时是多了一个叫manifest.js的文件,
然后我们修改src/index.js文件,随便添加点什么东西~有修改就行,然后再次执行npm test,比较这两次打包的文件hash值变化,会发现,vendor.js的hash值并未发生变化,这说明我们的目的达到了。

 

二:多插件拆分,单独打包

(1)新增入口配置:
entry:{
    app:[path.resolve(__dirname, 'src/index.js')],
    superSlide: [path.resolve(__dirname, 'src/assets/js/jquery.SuperSlide.2.1.1.js')],
    vendor: ["jquery","vue",'vue-router']
},

(2)新增缓存组:
cacheGroups: {
    a: {
    chunks:'initial',
    test: /[\\/]node_modules[\\/]/,
    name: 'vendor',
    priority: 10,
    enforce: true,
    },
    b: {
    chunks:'initial',
    test: /[\\/]src[\\/]assets[\\/]js[\\/]/,
    name: 'superSlide',
    priority: 10,
    enforce: true,
    },
}
需要注意这里test需要匹配到该插件的目录所在位置,否则拆分可不会成功~
我们再次执行npm test,然后运行http://127.0.0.1:9528,可以看到,app.js中已经不存在superSlide的依赖了,而是被单独打包成一个独立文件,app.js体积再次缩小~
 

三:打包优化-终章

     对于webpack打包优化的方法,网上有一种使用 DllPlugin 和 DllReferencePlugin 配合来提取那些我们不需要经常更新,
并且每个页面都有引用的第三方库的方法,并且做到不让其他模块的变化污染dll库的hash缓存,在webpack4中我们不需要使用者两个插件,也能实现这种效果,我们只需要配置好optimization的配置即可。

首先说一个项目我们往往都会抽离的几个chunk包:
(1)common:将被多个页面同时引用的依赖包打到一个包中,一般都是引入2次以上,即打入该包中。也可以根据自己项目的页面数量来调整


(2)dll:这个就是网上使用 DllPlugin 和 DllReferencePlugin 配合打出的包。


(3)manifest: webpack运行时代码,每当依赖包变化,webpack运行时代码也会变化,这个需要单独抽离,以减少common包的hash值变化的可能性


(4)页面入口文件对应的app.js


我们要实现的效果是:项目的每次迭代发布,尽量减少 chunk hash值得改变,那么以上这些要求,在webpack4我们都可以通过optimization的配置项来实现。

1:runtimeChunk

在webpack4中,抽离manifest,只需要配置runtimeChunk即可:
optimization: {
    runtimeChunk: {
        name: 'manifest'
    },
},


2:splitChunks

     这个配置,可以让我们以一定的规则抽离想要的包,其中的cacheGroups字段,每增加一个key值,就相当于多一个抽包规则。该配置的maxInitialRequests字段,表示在一个入口中,最大初始请求chunk数(不包含按需加载的,也就是页面中通过script引入的chunk),默认是3个,但是我们抽离的包common,dll,manifest,app.js,一个页面最少引入4个js 所以这个也需要重新配置,修改我们现有的配置,修改后如下:
entry:{
    app:[path.resolve(__dirname, 'src/index.js')],
    superSlide: [path.resolve(__dirname, 'src/assets/js/jquery.SuperSlide.2.1.1.js')],
},

optimization: {
    splitChunks: {
        maxInitialRequests: 6,
        cacheGroups: {
            dll: {
                chunks:'all',
                test: /[\\/]node_modules[\\/](jquery|vue|vue-router)[\\/]/,
                name: 'dll',
                priority: 2,
                enforce: true,
                reuseExistingChunk: true
            },
            superSlide: {
                chunks:'all',
                test: /[\\/]src[\\/]assets[\\/]js[\\/]/,
                name: 'superSlide',
                priority: 1,
                enforce: true,
                reuseExistingChunk: true
            },
            commons: {
                name: 'commons',
                minChunks: 2,//Math.ceil(pages.length / 3), 当你有多个页面时,获取pages.length,至少被1/3页面的引入才打入common包
                chunks:'all',
                reuseExistingChunk: true
            }
        }
    },
    runtimeChunk: {
        name: 'manifest'
    },
},

(1)修改过后,执行npm test 再次查看http://127.0.0.1:9528,发现core-js被多次打包,本项目在引用superSlide插件时,因为没有core-js而报错,
我们下载了该插件,此时它也属于项目依赖包,我们也需要将其打包到dll中,修改dll缓存组配置:
dll: {
    chunks:'all',
    test: /[\\/]node_modules[\\/](jquery|core-js|vue|vue-router)[\\/]/,
    name: 'dll',
    priority: 2,
    enforce: true,
    reuseExistingChunk: true
},
(2)再次执行npm test,可以看到,core-js 已经被提取到dll包中去了,我们看包依赖发现,虽然我们配置了vue vue-router 但是在打包后,项目中并没有打包这两个库的任何文件,那是因为虽然我们配置了这两个库需要打包到dll中,但实际项目中,我们并没有做任何引用~,所以不会打包进项目。

3:module chunk moduleIds namedChunks介绍

      前端经常说到模块化,也就是module,而webpack打包又有chunk的概念,webpack有xxxModuleIdsPlugin以及xxxChunksPlugin这些插件,那么在webpack中module和chunk到底是一种什么样的关系呢?
(1)chunk: 是指代码中引用的文件(如:js、css、图片等)会根据配置合并为一个或多个包,我们称一个包为 chunk。
(2)module: 是指将代码按照功能拆分,分解成离散功能块。拆分后的代码块就叫做 module。可以简单的理解为一个 export/import 就是一个 module。

每个chunk包可以包含多个module,比如我们打包的dll.xxxxxxxx.js, chunk 的 id 为dll,包含了jquery,core-js两个module。
一个module 还能跨chunk引用另一个module,也就是跨js引用功能块。

webpack 内部维护了一个自增的 id,每个 module 都有一个 id。所以当增加或者删除 module 的时候,id 就会变化,导致其它文件虽然没有变化,但由于 id 被强占,只能自增或者自减,导致整个 id 的顺序都错乱了。

我们上面配置runtimeChunk时,保证了hash的稳定性,但是在chunk包内部的module的id因为webpack的这个机制,在我们对包做增删操作时,其实会有所改变,进而可能影响所有 chunk 的 content hash 值,这就会导致缓存失效,为了解决这个问题,我们不用它的自增id就行了,改为使用它的hash为id,在webpack4中,我们只需要这样配置就行:
optimization: {
    moduleIds: 'hashed',
}
那么除了moduleId,每个分离出的chunk也有其chunkId,同样的,在webpack4中,我们只需配置如下参数即可:
optimization: {
    namedChunks: true,
}


四:完整optimization配置

module.exports={

  optimization: {
    namedChunks: true,
    moduleIds: 'hashed',
    splitChunks: {
        maxInitialRequests: 6,
        cacheGroups: {
            dll: {
                chunks:'all',
                test: /[\\/]node_modules[\\/](jquery|core-js|vue|vue-router)[\\/]/,
                name: 'dll',
                priority: 2,
                enforce: true,
                reuseExistingChunk: true
            },
            superSlide: {
                chunks:'all',
                test: /[\\/]src[\\/]assets[\\/]js[\\/]/,
                name: 'superSlide',
                priority: 1,
                enforce: true,
                reuseExistingChunk: true
            },
            commons: {
                name: 'commons',
                minChunks: 2,//Math.ceil(pages.length / 3), 当你有多个页面时,获取pages.length,至少被1/3页面的引入才打入common包
                chunks:'all',
                reuseExistingChunk: true
            }
        }
    },
    runtimeChunk: {
        name: 'manifest'
    },
 }

}
此时的webpack配置,已经可以说是非常完整了

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KunQian_smile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值