资讯专栏INFORMATION COLUMN

webpack dll打包重复问题优化

NicolasHe / 2796人阅读

摘要:关于的使用,我这里不做过多介绍,网上都有,一撸一大把,今天我要说的是在使用过程中出现的一个包依赖问题,这个问题导致打出来的包会包含重复的代码。

关于webpack dll的使用,我这里不做过多介绍,网上都有,一撸一大把,今天我要说的是在使用dll plugin过程中出现的一个包依赖问题,这个问题导致打出来的包会包含重复的代码。

优化背景

最近在给公司项目优化的时候,由于内部CDN上传文件大小限制了500K,所以用了webpack dll来进行拆分打包,我将拆分的包分为三部分:

vue生态包(vuevuexvue-routervuex-classvue-class-component等周边生态的库)

vue插件包(vee-validate、内部UI库,图片预览等vue插件库)

第三方包(axios、内部一些错误统计、上报,员工水印等这些脱离于vue的第三方库)

三部分的包名分别是vue.dll.jsplugin.dll.jslib.dll.js,这样的好处是结构清晰,最重要的原因还是分解包的大小,降低到500K以内

但是在进行dll打包后,我惊奇地发现vue.dll.jsplugin.dll.js中会包含重复的vue的dist代码

下面是分别是前两部分的bundle分析图

可以看到这俩dll都包含了vue

那么要分析问题原因,先说一下我的DLL的配置吧

DLL配置

因为webpack支持多entry,所以一般多入口dll打包的话,首先会考虑一个webpack配置,多个entry入口,所以可能会出现

// webpack.dll.conf.js

module.exports = {
    // 其他配置先省略
        entry: {
             vue: ["vue", "vuex", "vue-router", ...],
             plugin: ["vee-validate", "内部UI库", ...],
             lib: ["axios", "dayjs", ...]
        },
    plugins: [
        new webpack.DllPlugin({
            // dll.配置
        })
    ]
}

但是亲测这样打包出来的文件依然有上述问题

所以结合我在之前公司所实践的webpack multi compiler方式,参考webpack multi compiler,我把webpack的配置一分为三,每一个dll包都有一个webpack配置,即

// config.js

exports.dll = [
    {
        name: "vue",
        libs: ["vue", "vuex", "vue-router", "vuex-class", "vue-class-component"]
    },
    {
        name: "lib",
        libs: [axios", "dayjs", "第三方库"]
    },
    {
        name: "plugin",
        libs: ["vee-validate", "v-viewer", "vue插件库"]
    }
]
// webpack.dll.conf.js

module.exports = config.dll.map(function (vendor) {
    return {
        // 省略其他配置
        entry: {
            [vendor.name]: vendor.libs
        },
        plugins: [
            new webpack.DllPlugin({
                // dll.配置
            })
        ]
    }
})
// dll.js

const dllConfig = require("./webpack.dll.conf")

webpack(dllConfig, function (err, stats) {
    if (err) throw err
    // 处理stats相关信息
})

本以为这样可以解决问题,但是现实却是不能,所以得先分析一下问题所在

分析问题

经过仔细的排查,发现是由于内部UI库中多带带引用了vue,即在库中有

import Vue from "vue"

// ...
// Vue相关操作
// Vue.prototype.$isServer等

这样不管是多入口打包还是multi compiler方式下都会出现重复的包

解决方法

分析dll的原理,其实dll在打包的时候会将所有包含的库做一个索引,写在一个manifest文件中,然后在引用dll的时候只需要引用这个manifest文件即可

所以我就在想,如果plugin.dll.js依赖于vue.dll.js中的vue,那么是否可以先打包vue.dll.js,然后在打包plugin.dll.js的时候引用vue.dll.js呢?

心动不如行动,赶紧尝试一下,做出如下修改

// config.js

exports.dll = [
    {
        name: "vue",
        libs: ["vue", "vuex", "vue-router", "vuex-class", "vue-class-component"]
    },
    {
        name: "lib",
        libs: [axios", "dayjs", "第三方库"]
    },
    {
        name: "plugin",
        libs: ["vee-validate", "v-viewer", "vue插件库"],
        ref: "vue"
    }
]
// webpack.dll.conf.js

// generate config
const gen = function (vendors) {
    return vendors.map(function (item) {
        const base = {
            entry: {
                [item.name]: item.libs
            },
            plugins: [
                new webpack.DllPlugin({
                    // dll配置
                })
            ]
        }
        
        if (item.ref) {
            // 重点在这
            // 在有ref的dll配置中,插入dll reference的plugin,内容是所依赖的dll包的manifest
            base.plugins.push(new webpack.DllReferencePlugin({
                // dll reference其他配置
                manifest: "所依赖的dll包的manifest文件路径"
            }))
        }
        
        return base
    })
}

// 根据是否有ref依赖项,区分base config和ref config
const [baseVendors, refVendors] = config.dll.vendors.reduce((config, v) => {
    config[v.ref ? 1 : 0].push(v)
    return config
}, [
    [],
    []
])

// 生成base config
const getConfig = function () {
    return gen(baseVendors)
}

// 生成ref config
const getRefConfig = function () {
    return gen(refVendors)
}

module.exports = {
    getConfig,
    getRefConfig
}
// dll.js

const dllConfig = require("./webpack.dll.conf")

// 因为ref config依赖于base config,所以要保证base config先打包出来
const runWebpack = function (config) {
    return new Promise(function (resolve) {
        webpack(config, function (err, stats) {
            if (err) throw err
            // ...
            resolve()
        })
    })
}

module.exports = function run () {
    runWebpack(dllConfig.getConfig())
        .then(() => runWebpack(dllConfig.getRefConfig()))
}

整体变成了如下结构

最关键的一步就是plugin.dl.js会引用vue.dll.js的manifest文件,这样公共部分vue,就只会出现在vue.dll.js中了,plugin.dll.js打包后的bundle分析图如下

可以很明显地看到plugin.dll.js中已经没有vue dist的身影了,包的体积得到了优化✌️

可优化项

上述优化其实只考虑了一个依赖项,那么如果plugin.dll.js同时依赖于vue.dll.js和lib.dll.js呢?如果此时vue.dll.js也依赖于lib.dll.js呢?

如果出现上述情况,那么请先考虑dll包是否需要拆分?拆分是否合理?

然后再思考如何根据依赖顺序思考打包顺序,以及如果出现循环依赖,该怎么办?

由于目前优化需求中还未出现这种情况(这种情况应该很少很少很少见),所以我这边就没有解决这些问题了

总结

参考平常打包通过dll reference plugin来引用dll包的manifest的方式,如果多个dll包内出现了依赖,导致打包重复,那么是可以在依赖包中运用dll reference plugin来引用被依赖包的dll manifest,不过这样的话,需要注意dll包的打包顺序,被依赖包的dll要先于依赖包dll进行打包

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98253.html

相关文章

  • React系列---Webpack环境搭建(三)打包性能优化

    摘要:的选项中,是文件的输出路径是暴露的对象名,要跟保持一致是解析包路径的上下文,这个要跟下面要配置的保持一致。最后修改一下模板,增加引用文件给入口文件再加点依赖模块,方便打包观察运行打包可以看到,入口文件里依赖的,模块,直接引用了。 React系列---Webpack环境搭建(一)手动搭建React系列---Webpack环境搭建(二)不同环境不同配置React系列---Webpack环境...

    Jason_Geng 评论0 收藏0
  • 记一次使用 vue-admin-template 的优化历程

    摘要:同时也要引入对应版本的先引入引入组件库因为依赖是从外部引入的,所以需要告知在打包时,依赖的来源。然后在中加入一条命令执行或者即可完成打包。因此将此次优化记录下来,并传上了中。 本文原文 前言 公司有好几个项目都有后台管理系统,为了方便开发,所以选择了 vue 中比较火的 后台模板 作为基础模板进行开发。但是,开始用的时候,作者并没有对此进行优化,到项目上线的时候,才发现,打包出来的文件...

    xumenger 评论0 收藏0
  • webpack 基础与项目优化实践总结

    摘要:前言本文基于,主要涉及基本概念基本配置和实际项目打包优化。关于概念方面参考官网,常用配置来自于网络资源,在文末有相关参考链接,实践部分基于自己的项目进行优化配置。同一文件中,修改某个影响其他。 前言:本文基于weboack4.x,主要涉及webpack4 基本概念、基本配置和实际项目打包优化。关于概念方面参考官网,常用配置来自于网络资源,在文末有相关参考链接,实践部分基于自己的项目进行...

    Scorpion 评论0 收藏0
  • webpack4.0优化那些事儿

    摘要:配置以何种方式导出库。当检测文件不再发生变化,会先缓存起来,等等待一段时间后之后再通知监听者,这个等待时间通过配置。发布到线上给用户使用的运行环境。 一 缩小文件搜索范围 1 include & exclude 1) action 限制编译范围 2) useage module: { rules: [ { test...

    levy9527 评论0 收藏0
  • 【Vue项目总结】webpack常规打包优化方案

    摘要:由于新建项目发版打包时间大概需要分钟,发版时严重拖慢下班时间,所以特意查看了相关文档来优化打包速度,争取早点下班,。分析打包文件要优化,先分析。 由于新建项目发版打包时间大概需要30分钟,发版时严重拖慢下班时间,所以特意查看了相关文档来优化打包速度,争取早点下班,^_^。 分析打包文件 要优化,先分析。我们先要知道到底是哪里拖慢我们的打包速度呢? 打包后生成文件分析 可以利用webpa...

    andong777 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<