最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 老工程打包提速折腾记(上)- roadhog 打包提速

    正文概述 掘金(破秋风)   2021-05-31   1024

    背景

    2019年的时候,项目这套前端框架,build常常达到900s以上,开发环境修改代码重新编译也需要10-20s左右,严重影响开发效率,优化刻不容缓。

    环境

    硬件:I5-6200U 4核 @2.3GHz, 8G内存,固态硬盘。

    软件:win10,node v8.12.0, webpack v3.12.0,npm v6.2.0。

    前端框架:dva + antd, dva v1.2.1,antd v2.13.13,roadhog v1.3.4。

    现状

    涉及模块108个,首次构建:87.1s,再次构建:43.3s,打包:760.8s,打包文件大小:90.7M。

    改进过程

    升级相关构建工具,比如node、webpack,或者roadhog和dva都会多少提升一部分速度,但是盲目升级后续导致的依赖错误排查,甚至相关组件功能不可用是非常令人头疼的,因此当系统已经稳定,并且各业务模块比较繁多的情况下,我们并没有考虑这种方案。

    去掉多余模块和无效引用

    当前项目是另一个老旧项目改造而来,功能模块上一开始有80%的相似,因此项目初期直接把老项目的前端框架拿来用了,因此存在着很多老项目的模块在当前项目下实际上是无用的;另外代码中充斥着大量无效引用,如下

    import xx from 'xxx';
    

    事实上业务实现并没有用到XX,必须及时删除已经停止使用的相关库,从源码中移除相关依赖。

    通过去掉多余模块和无效引用,打包速度快了100多秒,上面的现状其实已经是经过该部分优化工作后的结果。

    但是随着后续业务拓展和迭代,模块还是会越来越多,这种方式的优化还是比较局限。

    webpack-visualizer-plugin分析

    非常好用的插件,该插件可以让你清楚的看到代码的组成部分,细化到每个文件中,每个模块的百分比,以及在项目中可能存在的多版本引用的问题。

    该插件roadhog已内置,只要在webpack中加入以下代码,构建的时候会生成一个stats.html文件。

    const Visualizer = require('webpack-visualizer-plugin');
      
    webpackConfig.plugins.push(
        new Visualizer()
    );
    

    stats.html内容如下:

    老工程打包提速折腾记(上)- roadhog 打包提速

    发现排第一的echarts占用了2M多,排第二的tf-ag-grid((公司内部使用的封装的一个表格组件))也占用了1.4M,其他的就是css-loader,lodash,moment,antd。

    externals

    简单来说 external 就是把我们的依赖申明为一个外部依赖,外部依赖通过

    针对打包大小占第一的echarts,我们只是在首页用到了,完全可以从项目中剥离出来,采用外部引入的方式。

    在 webpack.config.js 中,加入如下代码:

    webpackConfig.externals = {
        'echarts': 'echarts'
    };
    

    这样我们代码中import echarts from 'echarts'这种情况,echarts实际上是从window全局变量上拿,构建的时候也不会打包进去。当然对应的entry文件就要通过script方式引入。

    打包:711.6s,打包文件大小:90M。变化不大。

    DllPlugin和DllReferencePlugin

    针对lodash和moment这种公共库,同样也可以用external的方式处理,但是我们项目中试了下,在stats.html中仍然赫然在列。经过分析以moment为例,是因为antd中又依赖了moment,导致构建的时候仍然包含进去了。这个时候就可以用DllPlugin的方式来处理。

    用过 Windows 系统的人应该会经常看到以 .dll 为后缀的文件,这些文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据。我们把这种思路用到web构建中,为什么会大大提升构建速度呢? 原因在于包含大量复用模块的动态链接库只需要编译一次,在之后的构建过程中被动态链接库包含的模块将不会在重新编译,而是直接使用动态链接库中的代码。 由于动态链接库中大多数包含的是常用的第三方模块,例如 react、react-dom,只要不升级这些模块的版本,动态链接库就不用重新编译。

    Webpack 已经内置了对动态链接库的支持,需要通过2个内置的插件接入,它们分别是:

    1. DllPlugin 插件:用于打包出一个个单独的动态链接库文件。
    2. DllReferencePlugin 插件:用于在主要配置文件中去引入 DllPlugin 插件打包好的动态链接库文件。

    这块内容的配置可以参考这里,配置也不算繁琐。简单来说 DllPlugin 的作用是预先编译一些模块,而 DllReferencePlugin 则是把这些预先编译好的模块引用起来。这边需要注意的是 DllPlugin 必须要在 DllReferencePlugin 执行前,执行过一次。

    所幸的是低版本的roadhog已经支持了DllPlugin的模式,不过仅仅是对开发环境的支持,正式环境的打包仍然不支持。这边的配置主要参考了这个issue。

    1. 默认关闭
    2. 通过 .roadhogrc 的 dllPlugin 配置开启,可以配 exclude 和 include 的包
    3. 提供 roadhog buildDll 命令手动打 dll bundle
    4. 开启 dllPlugin 后,roadhog server 时检到没有 manifest.json,提醒执行 roadhog buildDll
    5. 然后用户还需手动在调试的 html 里引入 roadhog.dll.js

    我试了一下,第2条里的exclude和include设置了并没有生效,要开启DllPlugin,只需在.roadhogrc.js里面增加dllPlugin: true即可;同时还得先运行roadhog buildDll脚本预先生成 roadhog.dll.js。

    老工程打包提速折腾记(上)- roadhog 打包提速

    因此在package.json里script下添加如下命令:

    "scripts": {
        "dll": "roadhog buildDll"
    }
    

    执行npm run dll,生成roadhog.dll.js。

    老工程打包提速折腾记(上)- roadhog 打包提速

    我们可以在node_modules\roadhog-dlls中看到roadhog.dll.js和roadhog.json,roadhog.json描述了动态链接库文件中包含哪些模块,其中就包含了lodash和moment。

    并在entry文件index.ejs中引入,初次构建 62.3s,再次构建 27.5s。用webpack-visualizer-plugin分析了下,lodash和moment已经不参与构建了,但是antd仍然会参与构建,这点roadhog的作者也说了。dll的方式并不会影响生产打包,因此这种方式我们只针对开发环境,速度提升也是非常明显。对于生产打包,我们对几个打包大头文件采用commonChunkPlugin的方式。

    commonChunkPlugin

    看一下目前的打包文件大小,打包后js文件110个,将近 90M,有49个js文件达到1M以上。

    老工程打包提速折腾记(上)- roadhog 打包提速

    我们通过stats.html分析看到,体积过大主要是重复打包了tf-ag-grid、moment、antd,因此我们的思路是通过CommonsChunkPlugin 将公用模块抽离到 vendor.js。我们在webpack.config.js中针对线上环境加入以下代码(开发环境已经用DllPlugin优化):

    if (env === 'production') {
        webpackConfig.entry = {
            index: './src/index.js',
            vendor: [
                'moment',
                'lodash',
                'react',
                'react-dom',
                'tf-ag-grid'
            ]
        }
        webpackConfig.plugins.push(
            // 抽取出通用的部分
            new webpack.optimize.CommonsChunkPlugin({
                name: ['vendor'],
                filename: '[name].[hash].js',
                minChunks: Infinity,
            })
        )
    }
    

    打包测试结果如下:

    tf-ag-grid不参与公共提取打包:打包时间 656.4s,打包文件大小 66.6M,大部分文件体积瘦身 300-400KB

    老工程打包提速折腾记(上)- roadhog 打包提速

    tf-ag-grid参与公共提取打包:打包时间 355.0s,打包文件大小 34.0M,部分文件体积瘦身达1M以上。

    老工程打包提速折腾记(上)- roadhog 打包提速

    可以看到tf-ag-grid参与公共打包后,打包效率有了巨大的飞跃,结果令人满意。当然如果把项目中antd里面使用频率较高的模块如果也单独抽离打包到antd.js中的话,效果肯定会更好,这里就不做展开,留待后续优化,可以参考这个issue 解决 roadhog 单页应用提取公共模块的问题。

    测试结果

    优化动作初次构建时间(s)再次构建时间(s)打包时间(s)打包文件大小(M)
    未优化87.143.3760.890.7externals85.339.6711.690DllPlugin62.327.5720.190commonChunkPlugin(exclude tf-ag-grid)60.528.7656.466.6commonChunkPlugin(include tf-ag-grid)62.829.6355.034.0

    最终方案

    1. echarts配置externals,通过script引入地址;
    2. 开发环境配置DllPlugin,预编译常用模块;
    3. 线上环境通过commonChunkPlugin抽离公共模块,提升打包速度。

    后续研究

    1. 此次打包速度研究,还尝试过happyPack、PrefetchPlugin、webpack-uglify-parallel,但是要么受限于roadhog,要么优化速度不明显,不知道是配置的问题还是其他,作为后续研究;
    2. 对于antd,后续可以用commonChunkPlugin抽离高频模块,继续提高打包速度。

    最后

    其实还有一个拖慢打包速度的元凶,这个幕后黑手不仅拖慢打包速度,还影响svn更新、npm install甚至文件复制速度,就是IT给我们安装的McAfee。当然这个我们也没有办法,毕竟公司安全需要。最终我们还是要就事论事,从我们的框架层面去优化。

    参考

    • [1] Boost webpack build performance | Optimising webpack build performance | Webpack 构建性能优化探索
    • [2] roadhog 构建优化 - 狂流 - 博客园
    • [3] 考虑集成 dll 功能用以提升调试效率 · Issue #2 · sorrycc/roadhog · GitHub
    • [4] 4-2 使用 DllPlugin · 深入浅出 Webpack
    • [5] 解决 roadhog 单页应用提取公共模块的问题

    起源地下载网 » 老工程打包提速折腾记(上)- roadhog 打包提速

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元