babel源碼閱讀 ~ 準備工做

前言

學習一個庫的源碼,我認爲不能直接打開 src 或者 lib 目錄去直接找入口文件着去閱讀,而應該去了解下庫的做者是如何梳理、debug 源碼的vue

本着這個原則,咱們須要在閱讀源碼以前,理清楚整個項目是如何 debug 的,一些 pkg.json 裏的命令是如何執行的node

如下代碼所有出自於 babel-7.9.6 這個版本,源碼地址:https://github.com/babel/babel/tree/v7.9.6react

package.json

拿到一個 nodejs 的庫,首先應該看他根目錄下的 package.json 文件。git

做爲閱讀者和學習者,咱們應該關注它的 scriptsbin 兩個字段下的內容。github

因爲 babelbin 命令都散落在 packages 中的各個包中,因此這裏咱們只須要關注 scripts 字段:typescript

"scripts": {
    "bootstrap": "make bootstrap",
    "codesandbox": "make bootstrap-only; make build-no-bundle",
    "build": "make build",
    "fix": "make fix",
    "lint": "make lint",
    "test": "make test"
}

咱們發現全部的 script,所有使用 make 命令觸發。npm

此時會在根目錄下尋找名爲 makefile 或者 Makefile 的文件,找到後則執行相應的內容。json

Makefile

lint: make lint 爲例:gulp

找到 Makefile 中的 lint 命令的註冊位置:bootstrap

lint: lint-js lint-ts

注:Makefile 的主要語法爲:

target : Array<prerequisites> 
    List<command>

具體爲:

  • target: 命令 label,或者 target 文件 => 這裏只作一個命令的名稱
  • prerequisites: 依賴的命令或目標文件 => 能夠理解成執行該命令前須要執行的命令, 能夠沒有,也能夠不少不少
  • command: 具體的指令,純 bash

好的回過頭來,咱們發現他有兩處 prerequisites

  1. lint-js
  2. lint-ts

因此此時去找到兩個依賴的命令:

# YARN 這個變量賦值爲 `yarn --silent`
YARN := yarn --silent

# SOURCE 變量賦值爲: `packages codemods eslint` 
SOURCES = packages codemods eslint

# lint-js 不包含依賴,只有一條命令
lint-js:
    # 帶入 YARN 和 SOURCE 變量後,執行的命令就是: 
    # BABEL_ENV=test yarn --silent eslint scripts packages codemods eslint '*.js' --format=codeframe
	BABEL_ENV=test $(YARN) eslint scripts $(SOURCES) '*.js' --format=codeframe

lint-ts:
    # 直接執行 scripts 目錄下的 lint-ts-typigs.sh 這個腳本
	scripts/lint-ts-typings.sh

咱們能夠看到,lint-js 命令就至關於咱們在控制檯中輸入:

BABEL_ENV=test yarn --silent eslint scripts packages codemods eslint '*.js' --format=codeframe

能夠看到執行的是 eslint 命令,咱們能夠將 --silent 去掉後看到 eslint 命令的位置:

/Users/anning/Desktop/babel-7.9.6/node_modules/.bin/eslint scripts packages codemods eslint '*.js' --format=codeframe

注:其實通常都在 /node_modules/bin 裏找...

說完這個例子以後,咱們折回來講咱們學習時 debug 的方式。

scripts 裏咱們是沒能找到相似 vue-next 之類的 "dev": "node scripts/dev.js", 之類的命令的,因此也不可以像 vue-next 那樣直接 yarn dev [packageName] 的去 debug 某個具體的包

這時候咱們有注意到 CONTRIBUTING 裏有一段:

Fork the babel repository to your GitHub Account.

Then, run:

$ git clone https://github.com/<your-github-username>/babel
$ cd babel
$ make bootstrap

Then you can either run:

$ make build

to build Babel once or:

$ make watch

to have Babel build itself and incrementally build files on change.

因此咱們嘗試去尋找 Makefile 中的 watch 指令:

watch: build-no-bundle
	BABEL_ENV=development $(YARN) gulp watch

這裏也給出 build-no-bundle 的各個依賴的配置和註釋:

# 先執行 clean, clean-lib
build-no-bundle: clean clean-lib
    # 控制權交到 gulp 和 Gulpfile. 執行 Gulpfile 裏的 build-no-bundle task
	BABEL_ENV=development $(YARN) gulp build-no-bundle
	# Ensure that build artifacts for types are created during local
	# development too.
	// 而後執行到 makefile 裏的 generate-type-helpers 和 build-typings 命令
	$(MAKE) generate-type-helpers
	$(MAKE) build-typings

# 執行 `node packages/babel-types/scripts/generateTypeHelpers.js` 這條命令
generate-type-helpers:
	$(NODE) packages/babel-types/scripts/generateTypeHelpers.js
	
# 執行 build-flow-typings build-typescript-typings 兩條前置依賴的指令
build-typings: build-flow-typings build-typescript-typings

# 編譯 flow 的類型文件
build-flow-typings:
	$(NODE) packages/babel-types/scripts/generators/flow.js > packages/babel-types/lib/index.js.flow

# 編譯 ts 的類型文件
build-typescript-typings:
	$(NODE) packages/babel-types/scripts/generators/typescript.js > packages/babel-types/lib/index.d.ts

# 先執行 test-clean 命令
# 然後刪除一些文件夾 - -。。
clean: test-clean
	rm -f .npmrc
	rm -rf packages/babel-polyfill/browser*
	rm -rf packages/babel-polyfill/dist
	rm -rf coverage
	rm -rf packages/*/npm-debug*

# 執行 clean-source-test 這個變量下的命令
test-clean:
	$(foreach source, $(SOURCES), \
		$(call clean-source-test, $(source)))

# 執行 clean-source-lib 這個變量下的命令		
clean-lib:
	$(foreach source, $(SOURCES), \
		$(call clean-source-lib, $(source)))

# clean-source-lib定義
define clean-source-lib
	rm -rf $(1)/*/lib
	
endef

# clean-source-test 定義
define clean-source-test
	rm -rf $(1)/*/test/tmp
	rm -rf $(1)/*/test-fixtures.json

endef

Gulpfile

咱們能夠看到前置執行了 build-no-bundle 以後,執行的是:

BABEL_ENV=development yarn --silent gulp watch

因此控制權交回到 gulpGulpfile 中的各個 task 中,咱們看到 gulp watch 對應的腳本是:

const defaultSourcesGlob = "./@(codemods|packages|eslint)/*/src/**/*.js";
gulp.task("build-no-bundle", () => buildBabel());

gulp.task(
  "watch",
  gulp.series("build-no-bundle", function watch() {
    gulp.watch(defaultSourcesGlob, gulp.task("build-no-bundle"));
  })
);

比較明顯的就是會監聽 defaultSourcesGlob 下的文件,監聽到修改時就會從新執行 build-no-bundletask,然後從新執行 buildBabel()

咱們嘗試執行 make watch 以後,控制檯打印以下信息:

[11:50:26] Using gulpfile ~/Desktop/babel-7.9.6/gulpfile.js
[11:50:26] Starting 'watch'...
[11:50:26] Starting 'build-no-bundle'...
[11:50:26] Compiling 'packages/babel-helper-builder-react-jsx-experimental/src/index.js'...
[11:50:27] Compiling 'packages/babel-helper-compilation-targets/src/debug.js'...
@babel/preset-env: `DEBUG` option

Using targets:
{
  "node": "10.15"
}

Using modules transform: false

Using plugins:
  proposal-numeric-separator { "node":"10.15" }
  proposal-nullish-coalescing-operator { "node":"10.15" }
  proposal-optional-chaining { "node":"10.15" }
  syntax-json-strings { "node":"10.15" }
  syntax-optional-catch-binding { "node":"10.15" }
  syntax-async-generators { "node":"10.15" }
  syntax-object-rest-spread { "node":"10.15" }
  syntax-dynamic-import { "node":"10.15" }

.......

在經歷了不少不少文件的輸出以後,咱們看到最後兩句:

[11:50:44] Finished 'build-no-bundle' after 18 s
[11:50:44] Starting 'watch'...

一切如咱們所見。

咱們修改以後,被修改的文件會從新被編譯:

[11:50:44] Finished 'build-no-bundle' after 18 s
[11:50:44] Starting 'watch'...
[11:55:17] Starting 'build-no-bundle'...
[11:55:18] Compiling 'packages/babel-core/src/index.js'...
[11:55:18] Finished 'build-no-bundle' after 700 ms
[11:55:27] Starting 'build-no-bundle'...
[11:55:27] Compiling 'packages/babel-core/src/index.js'...
[11:55:27] Finished 'build-no-bundle' after 422 ms
[11:55:47] Starting 'build-no-bundle'...
[11:55:47] Compiling 'packages/babel-core/src/index.js'...
[11:55:48] Finished 'build-no-bundle' after 376 ms
[11:55:50] Starting 'build-no-bundle'...
[11:55:50] Compiling 'packages/babel-core/src/index.js'...
[11:55:50] Finished 'build-no-bundle' after 362 ms

至此,咱們就能夠邊調試邊學習了~

相關文章
相關標籤/搜索