成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何閱讀大型前端開源項(xiàng)目的源碼,授人以魚不如授人以漁

開發(fā) 前端
這篇文章主要講的是閱讀大型的前端開源項(xiàng)目比如 React、Vue、Webpack、Babel 的源碼時(shí)的一些技巧。目的是讓大家在遇到需要閱讀源碼才能解決的問題時(shí),可以更快的定位到自己想看的代碼。授人以魚不如授人以漁,希望大家可以通過這篇博客,了解到閱讀大型前端項(xiàng)目源碼時(shí)的切入點(diǎn)。在之后遇到好奇的問題時(shí),可以自己去探索。

目前網(wǎng)上有很多「XX源碼分析」這樣的文章,不過這些文章分析源碼的范圍有限,有時(shí)候講的內(nèi)容不是讀者最關(guān)心的。同時(shí)我也注意到,源碼是在不斷更新的,文章里寫的源碼往往已經(jīng)過時(shí)了。因?yàn)檫@些問題,很多同學(xué)都喜歡自己看源碼,自己動(dòng)手,豐衣足食。

這篇文章主要講的是閱讀大型的前端開源項(xiàng)目比如 React、Vue、Webpack、Babel 的源碼時(shí)的一些技巧。目的是讓大家在遇到需要閱讀源碼才能解決的問題時(shí),可以更快的定位到自己想看的代碼。授人以魚不如授人以漁,希望大家可以通過這篇博客,了解到閱讀大型前端項(xiàng)目源碼時(shí)的切入點(diǎn)。在之后遇到好奇的問題時(shí),可以自己去探索。

問題驅(qū)動(dòng)——不要為了看源碼而看源碼

首先我們要明確一點(diǎn),看源碼的目的是什么?

我個(gè)人的意見是,看源碼是為了解決問題。開源項(xiàng)目的源代碼并沒有什么非常特殊的地方,也都是普通的代碼。這些代碼的數(shù)量級(jí)一般都挺大,如果想是從源碼中學(xué)到東西,直接瀏覽整個(gè) Codebase 無疑是大海撈針。

但如果是帶著問題去看源碼,比如想了解一下 React 的合成事件系統(tǒng)的原理,想了解 React 的 setState 前后發(fā)生了什么,或者想了解 Webpack 插件系統(tǒng)的原理。也有可能是遇到了一個(gè) bug,懷疑是框架/工具的問題。在這樣的情況下,帶著一個(gè)具體的目標(biāo)去看源碼,就會(huì)有的放矢。

看***版的源碼

之前看到一種說法,看源碼要從項(xiàng)目的***個(gè) commit 開始看。如果是為了解決前文中對(duì)框架/工具產(chǎn)生的困惑,那自然要看當(dāng)前項(xiàng)目中用到的框架/工具的版本。

如果是為了學(xué)習(xí)源碼,我也建議看***的源碼。因?yàn)橐粋€(gè)項(xiàng)目是在不斷迭代和重構(gòu)的。不同版本之間可能是一次完全的重寫。比如 Vue 2.x 和 React 16。重構(gòu)導(dǎo)致了代碼架構(gòu)上的一些變化,Vue 2.x 引入了 Vritual DOM,Pull + Push 的數(shù)據(jù)變化檢測(cè)方式讓整個(gè)代碼的結(jié)構(gòu)變的更清晰了,所以 2.x 的代碼其實(shí)比 1.x 的更容易閱讀。React 16 重寫了 Reconciler,引入了 fiber 這個(gè)概念,整個(gè)代碼倉庫結(jié)構(gòu)也更清晰,所以更推薦閱讀。

前置條件

看源碼怎么看,當(dāng)然不能一把梭了。 

[[247850]]

看源碼之前需要對(duì)項(xiàng)目的原理有一個(gè)基本的了解。所謂原理就是,這個(gè)項(xiàng)目有哪些組成部分,為了達(dá)到最終的產(chǎn)出,要經(jīng)過哪幾步流程。這些流程里,業(yè)界主流的方案有哪幾種。

比如前端 View 層框架,要渲染出 UI,組件要經(jīng)過 mount、 render 等等步驟。數(shù)據(jù)驅(qū)動(dòng)的前端框架,在 mounted 之后,就會(huì)進(jìn)入一個(gè)循環(huán),當(dāng)用戶交互觸發(fā)組件數(shù)據(jù)變化時(shí),會(huì)更新 UI。其中數(shù)據(jù)的檢測(cè)方式又有分 Push 和 Pull 兩種方案。渲染 UI 可以是全量的字符串模板替換,也可以是基于 Virtual DOM 的差量 DOM 更新。

又比如前端的一些工具,Webpack 和 Babel 這些工具都是基于插件的。基本的工作流程就是讀取文件,解析代碼成 AST,調(diào)用插件去轉(zhuǎn)換 AST,***生成代碼。要了解 Webpack 的原理,就要知道 Webpack 基于一個(gè)叫 tapable 的模塊系統(tǒng)。

那我們要如何了解這些呢?要了解這些,可以去各大網(wǎng)站和博客上的《XXX源碼解析》系列。通過這些文章,我們可以對(duì)我們要看的框架/工具的原理有一個(gè)大致的了解。

本地build

不過最終我們還是要直接看源碼。筆者真正看源碼的***步就是把項(xiàng)目的代碼倉庫 clone 到本地。然后按項(xiàng)目 README 上的構(gòu)建指南,在本地 build 一下。

如果是前端框架,我們可以在 HTML 中里直接引入本地 build 出的 umd bundle(記得用 development build,不然會(huì)把代碼壓縮,可讀性差),然后寫一個(gè)簡單的 demo,demo 里引入本地的 build。如果是基于 Nodejs 的工具,我們可以用 npm link 把這個(gè)工具的命令 link 到本地。也可以直接看項(xiàng)目的 package.json 的入口文件,直接用 node 運(yùn)行那個(gè)文件。

這里要強(qiáng)調(diào)一下,大型的開源項(xiàng)目一般都會(huì)有一個(gè) Contribution Guide,目的是讓想貢獻(xiàn)代碼的開發(fā)者更快上手。里面就有講怎么在本地構(gòu)建代碼。

以 React 為例,React 的 Contributing Guide 里就 Development Workflow 這一節(jié)。里面有這么一段話:

  • The easiest way to try your changes is to run yarn build core,dom –type=UMD and then open fixtures/packaging/babel-standalone/dev.html. This file already uses react.development.js from the build folder so it will pick up your changes.

所以 React 倉庫中的 fixtures/packaging/babel-standalone/dev.html 就是一個(gè)方便的 demo 頁。我們可以在這個(gè)頁面快速查看我們?cè)诒镜貙?duì)代碼的改動(dòng)。

你可以嘗試著在項(xiàng)目的入口文件中加入一句 log,看看是不是可以在控制臺(tái)/終端看到這句 log。如果可以的話,恭喜你,你現(xiàn)在可以隨便把玩這個(gè)項(xiàng)目了!

理清目錄結(jié)構(gòu)

在看具體的代碼之前,我們需要理清項(xiàng)目的目錄結(jié)構(gòu),這樣我們才能更快的知道在哪里地方找相關(guān)功能的代碼。

我們看看 React 的目錄結(jié)構(gòu)。React 是一個(gè) monorepo。也就是一個(gè)倉庫里包含了多個(gè)子倉庫。我們?cè)?packages 目錄下可以看到很多單獨(dú)的 package:

如何閱讀大型前端開源項(xiàng)目的源碼,授人以魚不如授人以漁

在 React 16 之后,React 的代碼分為 React Core,Renderer 和 Reconciler 三部分。這是因?yàn)?React 的設(shè)計(jì)讓我們可以把負(fù)責(zé)映射數(shù)據(jù)到 UI 的 Reconciler 以及負(fù)責(zé)渲染 Vritual DOM 到各個(gè)終端的 Renderer 和 React Core 分開。React Core 包含了 React 的類定義和一些*** API。大部分的渲染和 View 層 diff 的邏輯都在 Reconciler 和 Renderer 中。

Babel 也是一個(gè) monorepo。Babel 的核心代碼是 babel-core 這個(gè) package,Babel 開放了接口,讓我們可以自定義 Visitor,在AST轉(zhuǎn)換時(shí)被調(diào)用。所以 Babel 的倉庫中還包括了很多插件,真正實(shí)現(xiàn)語法轉(zhuǎn)換的其實(shí)是這些插件,而不是 babel-core 本身。

如何閱讀大型前端開源項(xiàng)目的源碼,授人以魚不如授人以漁

Vuejs 的代碼比較典型,核心代碼在 src 目錄下,按功能模塊劃分。因?yàn)?Vue 也支持多平臺(tái)渲染,所以把平臺(tái)相關(guān)的代碼都放到了 platform 文件夾下,core 文件夾中是 Vue 的核心代碼,compiler 是 Vue 的模板編譯器,把 HTML 風(fēng)格的模板編譯為 render function。

如何閱讀大型前端開源項(xiàng)目的源碼,授人以魚不如授人以漁

Webpack 和 Babel 一樣,可以說都是基于插件的系統(tǒng)。Webpack 的主要源碼在 lib 目錄下,里面的 webpack.js 就是入口文件。

上面說了四個(gè)項(xiàng)目的目錄結(jié)構(gòu),那我們遇到一個(gè)新的開源項(xiàng)目,應(yīng)該怎么了解它的目錄結(jié)構(gòu)呢?

如果這個(gè)項(xiàng)目是一個(gè) monorepo,首先我們要找到核心的那個(gè) package,然后看里面的代碼。

不是 monorepo 的話,一般來說,如果這個(gè)項(xiàng)目是一個(gè) CLI 的工具,那 bin 目錄下放的就是命令行界面相關(guān)的入口文件,lib 或者 src 下面就是工具的核心代碼。如果這個(gè)項(xiàng)目是一個(gè)前端 View 層框架,那目錄結(jié)構(gòu)就和 Vue 類似。

作為驗(yàn)證,大家可以看一下打包工具 parcel 和前端 View 層庫 moon 的目錄結(jié)構(gòu)。目錄結(jié)構(gòu)這個(gè)東西往往是大同小異,多看幾個(gè)項(xiàng)目就熟悉了。

debugger && 全局搜索大法

運(yùn)行了本地的 build,了解了目錄結(jié)構(gòu),接下來我們就可以開始看源碼了!之前說了,我們要以問題驅(qū)動(dòng),下面我就以 React 調(diào)用 setState 前后發(fā)生了什么這個(gè)問題作為例子。

我們可以在 setState 的地方打一個(gè)斷點(diǎn)。首先我們要找到 setState 在什么地方。這個(gè)時(shí)候之前的準(zhǔn)備工作就派上用處了。我們知道 React 的共有 API 在 react 這個(gè) package 下面。我們就在那個(gè) package 里面全局搜索。我們發(fā)現(xiàn)這個(gè) API 定義在 src/ReactBaseClasses.js 這個(gè)文件里。

于是我們就在這里打一個(gè)斷點(diǎn): 

  1. Component.prototype.setState = function(partialState, callback) {  
  2. invariant(  
  3. typeof partialState === 'object' ||  
  4. typeof partialState === 'function' ||  
  5. partialState == null 
  6. 'setState(...): takes an object of state variables to update or a ' +  
  7. 'function which returns an object of state variables.' 
  8. );  
  9. debugger;  
  10. this.updater.enqueueSetState(this, partialState, callback, 'setState');  
  11. }; 

然后運(yùn)行本地 React build 的 demo 頁面,讓組件觸發(fā) setState,我們就可以在 Devtool 里看到斷點(diǎn)了。

我們走進(jìn) this.updater.enqueueSetState 這個(gè)調(diào)用,就來到了 ReactFiberClassComponent 這個(gè)函數(shù)中的 enqueueSetState,這里調(diào)用了 enqueueUpdate 和 scheduleWork 兩個(gè)函數(shù),如果要深入 setState 之后的流程,我們只需要再點(diǎn)擊 走進(jìn)這兩個(gè)函數(shù)里看具體的代碼就可以了。

如果想看 setState 之前發(fā)生了什么,我們只需要看 Devtool 右邊的調(diào)用棧:

如何閱讀大型前端開源項(xiàng)目的源碼,授人以魚不如授人以漁

點(diǎn)擊每一個(gè) frame 就可以跳到對(duì)應(yīng)的函數(shù)中,并且恢復(fù)當(dāng)時(shí)的上下文。

結(jié)合一步一步的代碼調(diào)試,我們可以看到框架的函數(shù)調(diào)用棧。對(duì)于每個(gè)重要的函數(shù),我們可以在倉庫里搜索到源碼,進(jìn)一步研究。

Node 工具的調(diào)試方法也是相似的,我們可以在運(yùn)行 node 命令時(shí)加上 –inspect 參數(shù)。

其實(shí)大家都知道單步調(diào)試這種辦法,但在哪里打斷點(diǎn)才是最關(guān)鍵的。我們?cè)谑煜た蚣艿脑碇螅涂梢栽诳蚣艿年P(guān)鍵鏈路上打斷點(diǎn),比如前端 View 層框架的聲明周期鉤子和 render 方法,Node 工具的插件函數(shù),這些代碼都是框架運(yùn)行的必經(jīng)之地,是不錯(cuò)的切入點(diǎn)。

如果是為了了解一個(gè)特定的問題,大家可以直接在自己覺得有問題的地方打斷點(diǎn)。然后把源碼運(yùn)行起來,想辦法讓代碼運(yùn)行到那個(gè)地方。我們?cè)跀帱c(diǎn)可以看到局部變量等等信息,有助于定位問題。

來自開發(fā)團(tuán)隊(duì)的資源

其實(shí)開源項(xiàng)目的開發(fā)團(tuán)隊(duì)也都致力于讓更多的人參與到項(xiàng)目中來,降低項(xiàng)目的門檻。所以我們?cè)诰€上其實(shí)可以找到很多來自開發(fā)團(tuán)隊(duì)的資源。這些資源可以幫助我們?nèi)ダ斫忭?xiàng)目的原理。

關(guān)注核心開發(fā)者

每個(gè)項(xiàng)目都有一些核心開發(fā)者,比如 React 的 Dan Abramov, Andrew Clark 和 Sebastian Markbåge。Webpack 的 Tobias Koppers 和 Sean Larkin。Vue 的 Evan You。我們可以在 Twitter 上關(guān)注他們,了解項(xiàng)目的動(dòng)態(tài)。

關(guān)注官方博客和演講視頻

如果我們關(guān)注了上面的核心開發(fā)者,就會(huì)發(fā)現(xiàn)他們時(shí)常會(huì)發(fā)布一些和源碼/項(xiàng)目原理有關(guān)的博客或者視頻。

React 的官方博客最近就有很多和項(xiàng)目開發(fā)有關(guān)的博客。

Behind the Scenes: Improving the Repository Infrastructure 這篇介紹的是 React 項(xiàng)目倉庫的基礎(chǔ)設(shè)施。

Sneak Peek: Beyond React 16

Andrew Clark 一開始就寫了一篇介紹 fiber 架構(gòu)的文檔。 Dan Abramov 最近在 JSConf 上對(duì) React 未來的一些新特性的介紹 – Beyond React 16。React 博客中的 Sneak Peek: Beyond React 16 也是對(duì)這次 Talk 的介紹。

Evan You 介紹前端框架數(shù)據(jù)變化偵測(cè)原理的 Talk。Vue 文檔中也有 Reactivity in Depth 這樣的介紹原理的章節(jié)。

Sean Larkin 的 Everything is a plugin! Mastering webpack from the inside out 介紹了 Webpack 的核心組件 Tapable。

James Kyle 的 How to Build a Compiler 可以讓我們了解 Babel 轉(zhuǎn)譯代碼的基本流程。

寫在***

本文最核心的觀點(diǎn)就是,看源碼的目的是為了解決問題。我們鼓勵(lì)大家在本地把大型項(xiàng)目的源碼跑起來,自己隨意把玩,研究。因?yàn)樵创a也是普通的代碼,并沒有太多門檻。唯一的門檻可能就來源于開源項(xiàng)目作者和普通開發(fā)者之間的信息不對(duì)稱,普通開發(fā)者對(duì)項(xiàng)目的原理和目錄結(jié)構(gòu)不夠了解。

我們可以從開發(fā)者那里獲取資源,同時(shí)也可以多閱讀社區(qū)里的源碼分析文章,這些都有助于我們理解項(xiàng)目的原理,為后續(xù)的源碼分析打下基礎(chǔ)。

責(zé)任編輯:未麗燕 來源: 簡書
相關(guān)推薦

2009-11-09 09:28:49

2015-07-20 10:56:22

DockerKubernetes云計(jì)算

2018-12-12 11:02:45

2022-03-22 08:03:08

ReactTsTypeScript

2017-01-10 14:59:03

開發(fā)者故事

2021-08-02 09:50:47

Vetur源碼SMART

2013-10-10 22:02:09

移動(dòng)開發(fā)講師

2021-08-26 10:24:52

Linux 系統(tǒng)分析高負(fù)載

2012-04-16 14:47:46

博雅立方

2020-10-10 07:14:08

前端項(xiàng)目斷點(diǎn)

2015-12-08 09:13:05

開發(fā)維護(hù)Java項(xiàng)目

2021-09-16 10:36:34

開源技術(shù) 項(xiàng)目

2020-08-25 08:47:15

開源軟件技巧

2019-02-21 23:36:09

源碼框架讀源碼

2014-04-14 09:58:18

開源項(xiàng)目

2017-09-22 13:45:55

氚云學(xué)院

2023-01-26 00:54:57

2021-06-17 11:44:13

智慧城市智能路燈物聯(lián)網(wǎng)

2024-12-26 08:00:38

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 性一交一乱一透一a级 | 国产9久 | 免费在线成人网 | 国产乱码精品一区二区三区忘忧草 | 97超碰在线免费 | 亚洲人人 | 最新中文字幕久久 | 色毛片| 国产高清视频 | 久久这里只有精品首页 | 剑来高清在线观看 | 国产欧美一区二区三区久久 | 日韩欧美一区二区三区在线播放 | 国产精品v | 欧美日日 | 2020国产在线| 亚洲成人在线免费 | 免费毛片在线 | 免费久久精品视频 | 国产精品国产成人国产三级 | 中文字幕精品一区 | 免费一级网站 | 午夜精品一区二区三区在线观看 | 毛色毛片免费看 | 操亚洲| 亚洲国产精品久久人人爱 | 久久精品成人 | 人和拘一级毛片c | 日本精品裸体写真集在线观看 | 欧美精品久久久久 | 国产日韩精品视频 | 精品一区二区三区在线观看国产 | 91视频精选 | 国产精品久久久久9999鸭 | 精品国产91| 国产精品中文在线 | 欧美乱淫视频 | 精品国产不卡一区二区三区 | 97久久精品午夜一区二区 | 91亚洲精选 | 免费在线播放黄色 |