掌握源码阅读的技巧 - Webpack 篇 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
FrankFang128
V2EX    分享发现

掌握源码阅读的技巧 - Webpack 篇

  •  
  •   FrankFang128 2021-03-11 13:05:42 +08:00 1735 次点击
    这是一个创建于 1688 天前的主题,其中的信息可能已经有所发展或是发生改变。

    高级前端面试中经常有这么几道题:

    1. 说一说 loader 和 plugin 的区别
    2. webpack 构建流程是怎样的
    3. 编写 webpack loader 的思路
    4. 编写 webpack plugin 的思路

    网上能搜到一些答案,但是这些答案我一一看过了,要么过于肤浅留于表面,要么冗长繁杂难以卒读。

    如果面试岗位的工资是 20k 以上,面试官必定会追问到更深层次。

    因此,我花了一个星期把 Webpack 5 的源码逐行扫了一遍,理出了主要脉络。整个阅读过程我录制成了视频,,总时长不到 3 小时,但把 Webpack 的整体架构、打包思路、loader 实现思路、plugin 实现思路、parser 运行流程等都讲到了,最重要的是,通过视频你会掌握「阅读源码的技巧」。

    如果你需要此视频课程,请加微信 xiedaimala03 留言「 webpack 源码课」即可。

    接下来是文字教程(文字教程并不适合用来阐述源码,但好在免费):


    webpack 流程分析.png

    webpack-cli 是如何调用 wepack 的

    webpack = require('webpack') compiler = webpack(options, callback) 

    hooks.xxx.call 是什么

    Tapable 是 webpack 团队为了写 Webpack 而写的一个事件 /钩子库

    用法

    定义一个事件 /钩子 this.hooks.eventName = new SyncHook(["arg1", "arg2"]); 监听一个事件 /钩子 this.hooks.eventName.tap('监听理由', fn) 触发一个事件 /钩子 this.hooks.eventName.call('arg1', 'arg2') 

    Webpack 的整体流程是怎样的

    至少有 env init run beforeCompile compile compilation make finishMake seal optimize afterCompile emit 等钩子

    读取 index.js 并分析和收集依赖是在哪个阶段?

    make - finishMake 阶段

    make - finishMake 之间,做了什么

    • 搜索 make.tap ,发现很多地方监听了 make 事件
    • 凭借我们的直觉,我们直接打开 EntryPlugin
    • EntryPlugin 的 addEntry 函数就是 make 阶段最重要的事情之一

    factory.create 中的 factory 是什么东西?

    这个 factory 是哪里来的?

    是从 factorizeModule(options 的 options.factory 来的。

    这个 options.factory 是哪里来的?

    是从 moduleFactory 来的。

    moduleFactory 哪里来的?

    是用 this.dependencyFactories.get(Dep) 得到的。

    this.dependencyFactories.get(Dep) 是个啥?

    你搜 compilation.tap 就知道,它是 normalModuleFactory,简称 nmf

    老师,你 TM 怎么知道要搜这个?

    我把所有钩子都搜了,搜了半个小时,能不知道吗?

    结论:factory 就是 nmf,所以 factory.create 就是 nmf.craete

    nmf.create 做了什么?

    • nmf.create 得到了一个 module 对象
    • 后续操作是 addModule 和 buildModule

    addModule 做了什么?

    • 跟前面课程的思路类似,把 module 添加到 compilation.modules 里
    • 而且还通过检查 id 防止重复添加

    buildModule 做了什么?

    • 看名字就知道是重要操作,它调用了 module.build()
    • 来到 NormalModule.js 看 build 源码,发现了 runLoaders
    • 然后来到 processResult(),发现了 _source = ... 和 _ast = null
    • 这是要做什么?显然是要把 _source 变成 _ast 了!
    • 来到 doBuild 的回调,发现了 this.parser.parse() !
    • parse 就是把 code 变成 ast
    • 问题来了,parser 是什么,parse() 的源码在哪?
    • 继续跟代码会发现 parser 来自于 acorn 库,需要编译原理知识,不跟进了
    • 如果你想要学习编译原理知识,可以购买我的科班课程

    Webpack 如何知道 index.js 依赖了哪些文件

    • blockPreWalkStatement() 对 ImportDeclaration 进行了检查
    • 一旦发现 import 'xxx',就会触发钩子,对应的监听函数会处理依赖
    • 其中 walkStatements() 对 ImportExpression 进行了检查
    • 一旦发现 import('xxx'),就会触发钩子,对应的监听函数也会处理依赖
    • 这里不讨论 require,大家有兴趣可以自己研究

    Webpack 是怎么把 modules 合并成一个文件的?

    • 看 compilation.seal(),该函数会创建 chunks 、 为每个 chunk 进行 codeGeneration,然后为每个 chunk 创建 asset
    • seal() 之后,emitAssets()、emitFiles() 会创建文件( emit 就是射)
    • 最终得到 dist/main.js 和其他 chunk 文件

    今年,我将研读更多前端项目源码并做成新的视频课程,敬请期待。

    如果有什么开源项目的源码是你想了解的,欢迎留言。

    完。

    7 条回复    2021-03-18 15:25:10 +08:00
    66beta
        1
    66beta  
       2021-03-12 14:32:17 +08:00
    视频卖多少钱?
    FrankFang128
        2
    FrankFang128  
    OP
       2021-03-12 16:24:55 +08:00
    Lanayaaa
        3
    Lanayaaa  
       2021-03-12 20:57:45 +08:00
    有 v 友众筹吗
    Cbdy
        4
    Cby  
       2021-03-14 19:10:45 +08:00 via Android
    啊这,已经在生产环境用上了 snowpack,感觉良好
    467469274
        5
    467469274  
       2021-03-15 14:36:15 +08:00
    好家伙 我以为是干货呢
    lyhiving
        6
    lyhiving  
       2021-03-17 06:17:16 +08:00   1
    一个前端的打包工具居然要这样,除了本文是软文,也层面说明 webpack 是一坨屎
    leelz
        7
    leelz  
       2021-03-18 15:25:10 +08:00
    期待出 vite 源码视频
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5395 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 06:38 PVG 14:38 LAX 23:38 JFK 02:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86