我经历过 Webpack 1、2、3、4 变迁后,深度拆解了Webpack


640?wx_fmt=jpeg

摘要:Webpack 是一个现代 JavaScript 应用程序的静态模块打包器,目前最流行的打包神器。本文将详述Wepack运行机制,带你深度理解Webpack

随着前端工程化的不断发展,构建工具也在不断完善。作为大前端时代的新宠,Webpack渐渐成为新时代前端工程师不可或缺的构建工具,随着Webpack4的不断迭代,我们享受着构建效率不断提升带来的快感,配置不断减少的舒适,也一直为重写的构建事件钩子机制煞费苦心,为插件各种不兼容心灰意冷,虽然过程痛苦,但结果总是美好的。

1.Webpack运行机制

1.1.Webpack运行机制概述

在阅读本文之前,我就默认电脑前的你已经掌握了WebPack的基本配置,能够独立搭建一款基于Webpack的前端自动化构建体系,所以这篇文章不会教你如何配置或者使用Webpack,自然具体概念我就不做介绍了,直面主题,开始讲解Webpack原理。

Webpack的运行过程可以简单概述为如下流程:

初始化配置参数 -> 绑定事件钩子回调 -> 确定Entry逐一遍历 -> 使用loader编译文件 -> 输出文件

接下来,我们将对具体流程逐一介绍。

1.2.Webpack运行流程

1.2.1.Webpack事件流初探

在分析WebPack运行流程时,我们可以借助一个概念,便是WebPack的事件流机制。

什么是Webpack事件流?

Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。 Webpack 通过 Tapable 来组织这条复杂的生产线。 Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 Webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。 --吴浩麟《深入浅出webpack》

我们将webpack事件流理解为webpack构建过程中的一系列事件,他们分别表示着不同的构建周期和状态,我们可以像在浏览器上监听click事件一样监听事件流上的事件,并且为它们挂载事件回调。我们也可以自定义事件并在合适时机进行广播,这一切都是使用了webpack自带的模块 Tapable 进行管理的。我们不需要自行安装 Tapable ,在webpack被安装的同时它也会一并被安装,如需使用,我们只需要在文件里直接 require 即可。

Tapable的原理其实就是我们在前端进阶过程中都会经历的EventEmit,通过发布者-订阅者模式实现,它的部分核心代码可以概括成下面这样:

640?wx_fmt=png

因为webpack4重写了事件流机制,所以如果我们翻阅 webpack hook 的官方文档会发现信息特别繁杂,但是在实际使用中,我们只需要记住几个重要的事件就足够了。

1.2.2.webpack运行流程详解

在讲解webpack流程之前先附上一张我自己绘制的执行流程图:

640?wx_fmt=jpeg

  • 首先,Webpack会读取你在命令行传入的配置以及项目里的 webpack.config.js 文件,初始化本次构建的配置参数,并且执行配置文件中的插件实例化语句,生成Compiler传入plugin的apply方法,为Webpack事件流挂上自定义钩子。

  • 接下来到了entryOption阶段,Webpack开始读取配置的Entries,递归遍历所有的入口文件

  • Webpack进入其中一个入口文件,开始compilation过程。先使用用户配置好的loader对文件内容进行编译(buildModule),我们可以从传入事件回调的compilation上拿到module的resource(资源路径)、loaders(经过的loaders)等信息;之后,再将编译好的文件内容使用acorn解析生成AST静态语法树(normalModuleLoader),分析文件的依赖关系逐个拉取依赖模块并重复上述过程,最后将所有模块中的require语法替换成__webpack_require__来模拟模块化操作。

  • emit阶段,所有文件的编译及转化都已经完成,包含了最终输出的资源,我们可以在传入事件回调的compilation.assets 上拿到所需数据,其中包括即将输出的资源、代码块Chunk等等信息。

1.2.3.什么是AST?

在1.2.2中,我们看到了一个陌生的字眼——AST,上网一搜:

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现;而类似于 if-condition-then 这样的条件跳转语句,可以使用带有两个分支的节点来表示。 --维基百科

其实,你只要记着,AST是一棵树,像这样:

640?wx_fmt=jpeg

转换成AST的目的就是将我们书写的字符串文件转换成计算机更容易识别的数据结构,这样更容易提取其中的关键信息,而这棵树在计算机上的表现形式,其实就是一个单纯的Object。

640?wx_fmt=jpeg

示例是一个简单的声明赋值语句,经过AST转化后各部分内容的含义就更为清晰明了了。

1.2.4.webpack输出结果解析

接下来,我们来看看webpack的输出内容。如果我们没有设置splitChunk,我们只会在dist目录下看到一个main.js输出文件,过滤掉没用的注释还有一些目前不需要去考虑的Funciton,得到的代码大概是下面这样:

640?wx_fmt=png

我们都知道其实webpack在浏览器实现模块化的本质就是将所有的代码都注入到同一个JS文件里,现在我们可以清晰明了地看出webpack最后生成的也不过只是一个IIFE,我们引入的所有模块都被一个function给包起来组装成一个对象,这个对象作为IIFE的实参被传递进去。

但如果我们配置了splitChunk,这时候输出的文件就和你的Chunk挂钩了

这时候,IIFE的形参也变成了摆设,所有我们的模块都被放在了一个名为 webpackJsonp 的全局数组上,通过IIFE里的 webpackJsonpCallback 来处理数据。

1.3.总结

纵观webpack构建流程,我们可以发现整个构建过程主要花费时间的部分也就是递归遍历各个entry然后寻找依赖逐个编译的过程,每次递归都需要经历 String->AST->String 的流程,经过loader还需要处理一些字符串或者执行一些JS脚本,介于node.js单线程的壁垒,webpack构建慢一直成为它饱受诟病的原因。这也是happypack之所以能大火的原因,我们可以来看一段happypack的示例代码:

640?wx_fmt=png

大家如果有用过pm2的话就能很容易明白了,其实原理是一致的,都是利用了node.js原生的cluster模块去开辟多进程执行构建,不过在4之后大家就可以不用去纠结这一问题了,多进程构建已经被集成在Webpack本身上了,除了增量编译,这也是4之所以能大幅度提升构建效率的原因之一。

我经历过 Webpack 1、2、3、4 变迁,以上内容仅是我Webpack专题课当中的冰山一角,我的Webpack专题课上线以后已经有超过570+人购买,并获得了100%好评。

我是谁?

  • 我是志佳老师

  • 曾就职于 百度LBS搜索研发部 腾讯MIG地图平台部

  • 深度实践过 FIS1、2、3

  • 经历过 Webpack 1、2、3、4 变迁

我将如何带你从0到1 深度理解webpack?

我的Webpack教程是基于 4.x 版本,从配置到源码的5大关键点深研Webpack,让你可以游刃有余的配置自己的工程化环境,并深度理解Webpack的整体运作流程。适合有一定前端开发经验的同学。

【Webpack专题课】是5次录播大课+1次答疑课,我将通过先点、后线、再面的方式帮你占领Webpack每一个重要的阵地,并提前带你熟知使用Webpack过程中会遇到的坑。

如果你报名了我的Webpack专题课,我希望你能认真学完,因为它不仅仅能缓解你的知识焦虑,更重要的是让你学会实操技能,并运用到工作当中,相信你一定会成为下一个精通Webpack的前端工程师。

【你将学到】

附上课程大纲,供你参考我的Webpack专题课是否适合你。

基于 4.x 版本,从配置到源码 深研Webpack。

01、 使用Webpack快速构建SPA应用

  • 讲解SPA的技术始末 以及项目结构

  • 讲解Webpack在工程化领域的作用

  • 讲解SPA开发中常见loader的应用

  • 讲解SPA开发中常见plugin的应用

02、 使用Webpack快速构建MPA应用

  • 已Nset.js为基础介绍MPA与SPA的区别

  • 讲解MPA应用中入口的自动化收集

  • 讲解开发自定义的属于MPA的plugin

  • 介绍将MPA构建为SPA的一些技巧

03、 Webpack在一线开发中的优化

  • 介绍如Happypack优化Webpack手段

  • 介绍Webpack打包结果分析的利器

  • 介绍对生产环境加快Webpack编译常用库

  • 前端性能优化Webpack有用的plugin如(workbox-

  • webpack-plugin)

04、 Webpack核心源码分析原理课

  • 编写属于自己的loader&plugin

  • 了解Webpack整体运行流程

  • 熟悉AST 抽象语法分析树的运用

  • 分析Tapable插件实现的原理

  • 分析Webpack Template类的实现

05 手把手带你实现一个Webpack

  • 从0开始实践一个Webpack的雏形,能够让大家更加深入了解Webpack

【购课福利】

【Webpack专题课】原价98元,限时限量发放10张30元优惠券,68元即可让你在年后跳槽中双倍提升核心竞争力!

现在更有 【web前端开发】 粉丝专属福利:购买Webpack专题课的第5、10、15、20位用户将获赠价值98元的精致伦敦巴士充电宝(10000mAh)一个

640?wx_fmt=jpeg

请购买专题课之后务必添加微信:yidengxuetang,海洋老师将邀请你加入课程专属VIP群,跟300位前端工程师一起成长,还会提供答疑服务哦。

赶快扫描下方二维码报名吧!

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值