前端打包拆分技术调研

简介: 随着单页应用的发展和前端应用需要处理的业务复杂度越来越高,我们不得不面临的问题是前端的代码量也变得越来越大。代码量的庞大一方面造成了开发编辑等待时间加长,影响开发效率,另一方面首屏加载需要更长的时间和带宽加载更庞大体积的文件。为了解决单页应用打包拆分的需求,webpack很早就开始支持多种拆分的方案...

前言

随着单页应用的发展和前端应用需要处理的业务复杂度越来越高,我们不得不面临的问题是前端的代码量也变得越来越大。代码量的庞大一方面造成了开发编辑等待时间加长,影响开发效率,另一方面首屏加载需要更长的时间和带宽加载更庞大体积的文件。

为了解决单页应用打包拆分的需求,webpack很早就开始支持多种拆分的方案。最早支持的两个方案就是多entry打包和静态或动态的Code Splitting,随着webpack升级到4.0、5.0版本,代码拆分的能力和稳定性也逐渐增强。本文主要是调研了目前最新的打包拆分技术的各种方案,并且以webpack为例,具体阐释了webpack打包拆分的具体原理。

概念术语

什么是entry?

entry就是webpack的打包入口或者叫做入口文件。从入口文件开始分析,webpack可以找到整个文件依赖的关系。

什么是bundle

bundle就是webpack经过编译、压缩、拆分后得到的一系列文件,这些文件可以直接在浏览器中运行。

什么是chunk

chunk就是webpack编译过程中,将某些模块聚合在一起,组件一个单独的文件,这就是一个chunk。一般来说,一个bundle分成多个chunk后,单个chunk无法在浏览器中直接运行。

代码拆分技术分类

以webpack为例,目前webpack提供了四种拆包的方式

  1. 多bundle技术或者多entry方式,这个方式本质就是基于多路由或者微前端将一个应用拆分成多个应用。

  2. bundle init splitting,创建许多小的chunk,但是chunk之间必须同时加载才能运行。

  3. bundle dynamic splitting,创建许多小的chunk,允许chunk按需加载

  4. Module Federation:共享模块

下面我们分别介绍下四种技术的优缺点。

多bundle技术

除了webpack内置支持的多entry实现多bundle之外,下面列举了四种多bundle技术:

基于路由的多entry

这个就是webpack内置支持的多entry方案,迁移比较简单,只需要简单修改webpack配置和配置反向代理即可。

iframe容器化

基于iframe的方案,将需要拆分的模块独立放置于iframe中。这种方式可以兼容多种不同的前端框架,但是缺点是改造成本比较高,框架通信也比较复杂。

微件化

SLS日志应用就是采取了微件化的方案,这个方案本质就是将每个app独立的打包成一个js文件(内部包含css和js)。每个app的大小都比较小,而且app的依赖可以和主项目共用,由主项目注入。微件化的方案适用于单一的前端框架,否则很难把控单个js文件的大小。

微前端

微前端是目前比较火的说法,主要是由single-spa这个项目引发的,国内比较著名的是基于single-spa的qiankun。这类方案的特点就是能够兼容多种不同的前端框架,并且提供了统一的环境、隔离机制、通信机制、生命周期等。

bundle init splitting

bundle init splitting就是将某一些文件单独打包,但是也必须和入口文件共同加载。这个方式与配置webpack的external类似,主要适用于将一些大型的库打包成外部依赖,一方面开发的时候可以加速编译时间,另一方面也能开启外部依赖的长效缓存机制。

这个方式有一个比较大的缺点就是每次页面加载的时候,被打包出去的依赖必须同时被浏览器加载、编译、运行的,如果这个包首屏用不到,会对首屏性能有一些影响。

下面是一个简单的bundle init splitting的Demo。

bundle dynamic splitting

bundle dynamic splitting就是webpack所谓的动态加载代码。这个方式的优点是代码是按需加载的,对首屏优化有非常大的帮助,而且特别适合用于react和vue组件的动态加载。缺点是代码的改造成本是比较高的,改造的时候需要借助webpack-bundle-analyzer等技术理清楚所有模块的依赖关系。

动态加载代码目前可以分为动态加载函数和动态加载react或者vue等组件。这里区分这两种方式是因为分别要让函数和组件实现动态加载的代价是不一样的。

动态加载函数

假设我们有如下两个文件:

//index.js
import callA from 'a'

init () {
  // ...other code
	callA()
  // ...other code
}

//a.js
export default function callA() {
  console.log('a')
}

如果想要将a.js让webpack作为动态代码加载,需要将调用callA的地方改为异步执行。并且用到callA的所有其他文件也需要改造,成本很高。

//index.js
const callA import('a') //异步加载语法

const init = async () => {
  // ...other code
  await callA()
  // ...other code
}

//a.js
export default function callA() {
  console.log('a')
}

动态加载react和vue组件

动态加载组件相对于函数来说方便很多,react和vue都有对应动态加载的方式,这里以react为例,只需要如下改写代码:

// a.js
export function Acom() {
	return <div>Acom</div>
}

// b.js
const Acom = lazy(() => import('./a'))
<Suspense fallback={<div />}>
	<Acom />
</Suspense>

Module Federation

Module Federation是webpack5推出的最新方案,共享模块粒度自由掌控,小到一个单独组件,大到一个完整应用。既实现了组件级别的复用,又实现了微服务的基本功能。依赖自动管理,可以共享 Host 中的依赖,版本不满足要求时自动 fallback 到 Remote 中依赖。

缺点就是更新逻辑复杂,模块更新后其他应用需要同步发版更新,也缺少应用之间的隔离机制。

结语

本文主要介绍了当前流行的前端打包拆分技术的几个方案。目前SLS也在使用这些方案优化首屏性能,主要用到了微件化、bundle init splitting、bundle dynamic splitting等方案。就我们团队目前的实践来说,单纯依赖webpack的配置实现代码拆分是非常困难的,主要有以下痛点:

  • 打包工具的代码拆分策略配置复杂,调试困难

  • 完全依赖打包工具的算法,具有极大的不确定性,少量修改会引起巨大的包拆分的变化

  • 循环依赖无法解决,容易引起线上事故

  • 面对巨石应用,无法进行异步拆分的代码基数依旧庞大。

欢迎大家评论指正。

相关文章
|
6天前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
20天前
|
Cloud Native 前端开发 JavaScript
前端开发者必看:不懂云原生你就OUT了!揭秘如何用云原生技术提升项目部署与全栈能力
【10月更文挑战第23天】随着云计算的发展,云原生逐渐成为技术热点。前端开发者了解云原生有助于提升部署与运维效率、实现微服务化、掌握全栈开发能力和利用丰富技术生态。本文通过示例代码介绍云原生在前端项目中的应用,帮助开发者更好地理解其重要性。
53 0
|
13天前
|
前端开发 JavaScript API
惊呆了!这些前端技术竟然能让你的网站实现无缝滚动效果!
【10月更文挑战第30天】本文介绍了几种实现网页无缝滚动的技术,包括CSS3的`scroll-snap`属性、JavaScript的Intersection Observer API以及现代前端框架如React和Vue的动画库。通过示例代码展示了如何使用这些技术,帮助开发者轻松实现流畅的滚动效果,提升用户体验。
83 29
|
24天前
|
JavaScript 前端开发 Docker
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
在使用 Deno 构建项目时,生成的可执行文件体积较大,通常接近 100 MB,而 Node.js 构建的项目体积则要小得多。这是由于 Deno 包含了完整的 V8 引擎和运行时,使其能够在目标设备上独立运行,无需额外安装依赖。尽管体积较大,但 Deno 提供了更好的安全性和部署便利性。通过裁剪功能、使用压缩工具等方法,可以优化可执行文件的体积。
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
|
6天前
|
移动开发 前端开发 JavaScript
惊!这些前端技术竟然能让你的网站在移动端大放异彩!
随着互联网技术的发展,移动设备成为主要的上网工具。本文介绍了几种关键的前端技术,包括响应式设计、图片优化、字体选择、HTML5和CSS3的应用、性能优化及手势操作设计,帮助开发者提升网站在移动端的显示效果和用户体验。示例代码展示了如何实现简单的双向绑定功能。
15 3
|
6天前
|
数据采集 前端开发 安全
前端测试技术
前端测试是确保前端应用程序质量和性能的重要环节,涵盖了多种技术和方法
|
12天前
|
编解码 前端开发 JavaScript
前端界的黑科技:掌握这些技术,让你的网站秒变未来感十足!
【10月更文挑战第31天】前端技术日新月异,黑科技层出不穷,让网页更加美观、交互更加丰富。本文通过响应式布局与媒体查询、前端框架与组件化开发等案例,展示这些技术如何让网站充满未来感。响应式布局使网站适应不同设备,前端框架如React、Vue则提高开发效率和代码质量。
25 3
|
13天前
|
JSON 前端开发 搜索推荐
惊!这些前端技术竟然能让你的网站实现个性化推荐功能!
【10月更文挑战第30天】随着互联网技术的发展,个性化推荐已成为提升用户体验的重要手段。前端技术如JavaScript通过捕获用户行为数据、实时更新推荐结果等方式,在实现个性化推荐中扮演关键角色。本文将深入解析这些技术,并通过示例代码展示其实际应用。
44 4
|
13天前
|
前端开发 JavaScript 测试技术
前端小白逆袭之路:如何快速掌握前端测试技术,确保代码质量无忧!
【10月更文挑战第30天】前端开发技术迭代迅速,新手如何快速掌握前端测试以确保代码质量?本文将介绍前端测试的基础知识,包括单元测试、集成测试和端到端测试,以及常用的测试工具如Jest、Mocha、Cypress等。通过实践和学习,你也能成为前端测试高手。
32 4
|
12天前
|
前端开发 JavaScript 数据处理
前端界的宝藏技术:掌握这些,让你的网页秒变交互神器!
【10月更文挑战第31天】前端开发藏有众多宝藏技术,如JavaScript异步编程和Web Components。异步编程通过Promise、async/await实现复杂的网络请求,提高代码可读性;Web Components则允许创建可重用、封装良好的自定义组件,提升代码复用性和独立性。此外,CSS动画、SVG绘图等技术也极大丰富了网页的视觉和交互体验。不断学习和实践,让网页秒变交互神器。
21 2