写点什么

基于 webpack 的应用治理

  • 2020-03-25
  • 本文字数:2543 字

    阅读完需:约 8 分钟

基于 webpack 的应用治理

当前市面上大部分前端应用都是基于 webpack 进行构建,而随着应用日益庞大,webpack 应用就会出现构建速度慢,构建结果体积大等一系列问题。

一、webpack 应用治理应该从哪个方向入手?

随着应用的不断迭代,webpack 应用最常见的两个问题就是:


  1. 构建速度慢;

  2. 构建体积大。


有一个很简单的划分方式,就是以构建(build)为分界线,分成前向治理和后向治理:


  • 前向治理:提升构建速度;

  • 后向治理:保证构建结果质量。


我们的治理方向,就是围绕前向治理和后向治理。


二、前向治理包含哪些内容?

前向治理的核心概念,就是一个字 `快`,目的就是提升构建速度,市面上大部分 webpack 优化文章都是这一类提升构建速度的文章,所以这里就简单介绍一些不错的实践


1. 利用 SMP 采集 webpack 数据指标



数据先行,通过 speed-measure-webpack-plugin 采集性能指标,可以得到 webpack 在整个编译过程中在 loader、plugin 上花费的时间,基于该数据可以专项的进行优化和治理。


2. 开启缓存


如果通过 SMP 分析得知在 loader 编译过程耗时较多,那么可以在核心 loader,例如 babel-loader 中添加缓存。


{  loader: 'babel-loader',    options: {      cacheDirectory: true    }}
复制代码


3. 开启 happyPack 多线程编译


如果通过 SMP 分析得知在 loader 编译过程耗时较多,还可以通过使用 happyPack,开启多线程编译,提升开发效率。


4. 使用 dll 技术


dll 可以简单理解成提前打包,例如 lodash、echarts 等大型 npm 包,可以通过 dll 将其提前打包好,这样在业务开发过程中就不用再重复去打包了,可以大幅缩减打包时间。


5. 升级到 webpack5


webpack5 利用 `持久缓存` 来提高构建性能,或许升级 webpack 后,前述的各种优化,都将成为历史。

三、后向治理包含哪些内容?

后向治理主要保证构建结果的质量


1. 可视化分析构建结果



很常见的就是 webpack-bundle-analyzeer,提供打包结果的可视化展示,如上图给予的决策帮助是:


  • 是否需要按需加载;

  • 是否需要提取公共代码;

  • 是否需要制定 cacheGroup 的策略。


2. 清理 deadcode


业务开发过程中,随着业务迭代,经常有些文件、模块及代码被废弃,这些废弃代码随着时间推移,将逐渐变为历史包袱,所以针对构建后结果,我们要做的就是清理其中的 deadcode。


前面 webpack-bundle-analyzeer 虽然是最常用的插件,但依旧有一些缺陷:


1)体积超小的 deadcode 模块引用,无法被准确识别。



例如上图:


lodash 体积大一下子就能被发现,就会意识到重复引用或者是未使用


但 deadcode 模块 c 体积很小,即便被 chunk1、chunk2 都引用了,也不一定能立刻发现,很容易被带到线上


而且这种 deadcode 也无法通过 splitchunk 来进行优化,因为 splitchunk 根据引用次数提取公共代码,无法分辨是否是废弃代码,所以对模块 c.js 这种的 deadcode 就无力了


2)tree-sharking 只保留有用的代码,但 deadcode 还在那里。


tree-sharking 大家都了解,摇掉不需要的代码,做为最终的输出结果,但反过来说,这些废弃代码依旧在本地真实不虚的存在着。


所以如何能准确的清理掉 deadcode 呢?这就需要通过 webpack 的 统计信息(stats) 来进行更细节的分析


3. 统计信息(stats)


stats 是通过 webpack 编译源文件时,生成的包含有关于模块的统计数据的 JSON 文件,这些统计数据不仅可以帮助开发者来分析应用的依赖图表,还可以优化编译的速度。


webpack --profile --json > compilation-stats.json
复制代码


通过上述全局命令即可输出统计信息,例如:


{  "version": "1.4.13", // Version of webpack used for the compilation  "hash": "11593e3b3ac85436984a", // Compilation specific hash  "time": 2469, // Compilation time in milliseconds  "filteredModules": 0, // A count of excluded modules when `exclude` is passed to the `toJson` method  "assetsByChunkName": {    // Chunk name to emitted asset(s) mapping    "main": "web.js?h=11593e3b3ac85436984a",    "named-chunk": "named-chunk.web.js",    "other-chunk": [      "other-chunk.js",      "other-chunk.css"    ]  },  "assets": [    // A list of asset objects  ],  "chunks": [    // A list of chunk objects  ],  "modules": [    // A list of module objects  ],  "errors": [    // A list of error strings  ],  "warnings": [    // A list of warning strings  ]}
复制代码


其中:modules:表示 module 的集合


  • module:webpack 依赖树中的真实模块;

  • chunks:表示 chunk 的集合;

  • chunk:包含 entry 入口、异步加载模块、代码分割(code spliting)后的代码块。


通过对 modules 和 chunks 加以分析,就可以得到 webpack 完整的依赖关系,从而梳理出废弃文件及废弃代码,同时也可以根据业务形态进行定制。


4. webpack-deadcode-plugin


前面提到分析 stats.json,但因为是原始数据,数据量比较大,有一定处理和清洗成本,所以可以使用开源的 webpack-deadcode-plugin 这个插件



通过 webpack-deadcode-plugin,可以快速筛选出:


1)未使用的文件;


2)未使用的已暴露变量。


5. 结合 eslint、tslint 进行治理


lint 可以快速的扫描出未使用的变量,这能够极大的提升我们的 deadcode 清理效率。


1)首先通过 lint 对未使用变量进行清理;


2)再通过 webpack-deadcode-plugin 再扫描出未使用文件和未使用的导出变量。


顿时整个应用干干净净,舒舒服服!

四、参考

speed-measure-webpack-plugin:


https://github.com/stephencookdev/speed-measure-webpack-plugin


happyPack:


https://github.com/amireh/happypack


webpack-bundle-analyzeer:


https://github.com/webpack-contrib/webpack-bundle-analyzer


stats:


https://webpack.js.org/api/stats/


webpack-deadcode-plugin:


https://github.com/MQuy/webpack-deadcode-plugin


作者介绍


阿里影业高级开发工程师 百命


相关阅读


电影垂直行业的云智开放平台如何炼成?


阿里工程师带你了解 B 端垂类营销中心如何设计?


云智前端技术如何赋能场馆院线?


60 秒售出 5 万张票!电影节抢票技术揭秘


电影行业提升 DCP 传输效率,还能这样做!


超大型场馆的绘座选座解决方案


大型赛事稳定性保障:Dpath 为世界军人运动会护航


世界顶级赛事的票务支撑:百万座位与限时匹配


前端技术:Webpack 工程化最佳实践


电影票房数据查询服务高性能与高可用实践


2020-03-25 10:003057

评论

发布
暂无评论
发现更多内容

SRv6故障管理

穿过生命散发芬芳

8月月更 SRv6

LeaRun模型驱动开发框架 重塑企业生产力

力软低代码开发平台

Go-Excelize API源码阅读(四)——Save()

Regan Yue

Go 开源 源码刨析 8月日更 8月月更

借问变量何处存,牧童笑称用指针,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang类型指针(Pointer)的使用EP05

刘悦的技术博客

入门 教程 Go web 教程分享 入门介绍

开源一夏 | jQuery对于链和捕获的实战研究

恒山其若陋兮

开源 8月月更

企业进行知识共享的好处有哪些?

Geek_da0866

MySQL权限管理

武师叔

8月月更

分门别类输入输出,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本数据类型和输入输出EP03

刘悦的技术博客

golang 编程 教程 教程分享 golang 面试

文档管理系统对于企业来说有哪些作用?

Baklib

Spring Cloud Stream 消息发送

急需上岸的小谢

8月月更

头脑风暴:打家劫舍2

HelloWorld杰少

算法 LeetCode 动态规划 8月月更

开源一夏 | 基于 Serverless一键体验FastAPI

六月的雨在InfoQ

阿里云 开源 Serverless FC 8月月更

什么是Shell?从小白到入门你只差一个它

Albert Edison

Linux centos 运维 shell脚本编程 8月月更

【高并发】别闹了,要实现亿级流量下的分布式限流,这些算法你必须掌握!!

冰河

并发编程 多线程 高并发 协程 异步编程

openEuler 资源利用率提升之道02:典型应用下的效果

openEuler

开源 数据 cpu 操作系统 openEuler

培训预告 | 企业应用现代化实用教程——DevOps方法论及最佳实践篇 8月11日上线

York

DevOps 云原生 团队建设 降本增效 应用现代化

低代码实现探索(四十七)低的不止前端,还有后端

零道云-混合式低代码平台

企业“数字化转型”成功的2个必备条件!

优秀

数字化转型

Netty入门 -- 什么是Netty?

Bug终结者

Netty 8月月更

阿里云数据库PolarDB开源人才培养计划发布!万元好礼等你来拿!

阿里云数据库开源

数据库 阿里云 开源 认证 polarDB

开源一夏 | RuntimeException 子类

六月的雨在InfoQ

开源 8月月更

如何让您的wiki内容更高级?

Geek_da0866

经验分享|低成本快节奏搭建企业知识管理系统的方法

Baklib

深度解读 | 关于SBOM最基础元素,你需要知道的(Part I)

安势信息

开源 漏洞 SCA SBOM 最基础元素

Linux下Docker安装部署以及云原生的理解

Geek_acae888666

云原生 Docker 镜像

Unity Metaverse(四)、接入环信IM SDK 实现用户登录注册

CoderZ

Unity 登录验证 环信im 8月月更

超人飞来!Flutter 实现满屏的力量感动画!

岛上码农

flutter ios 移动端开发 安卓开发 8月月更

兼容并蓄广纳百川,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang复合容器类型的声明和使用EP04

刘悦的技术博客

golang go doc 教程 教程分享 golang 面试

舔狗至高境界,学会这个技巧让你从舔狗升华到海王【Python趣味爬虫】

Geek_ac6fb9

后端

运筹帷幄决胜千里,Python3.10原生协程asyncio工业级真实协程异步消费任务调度实践

刘悦的技术博客

Python 协程 Async Python3 协程原理

如何用精益敏捷组合管理,提升研发效能?|ONES 研发管理大师课

万事ONES

基于 webpack 的应用治理_文化 & 方法_阿里巴巴文娱技术_InfoQ精选文章