Vue3 コンパイルプロセス - ソースコード分析

Vue3 コンパイルプロセス - ソースコード分析

序文:

Vue3 がリリースされてからかなり経ちますが、最近、会社のプロジェクトでVue3 + TypeScript + Vite技術スタックを使う機会があり、私も暇な時間に Vue3 のソースコードを読む時間を取っています。記憶力は悪いペンほど良くないという考えから、ソースコードを読みながらメモを取りました。また、ソースコードを読みたいが理解に苦労しているすべての学生の理解コストを削減するために、ソースコードの読み取りメモをいくつか書きたいと思っています。

Vue2.x のソースコードも簡単に読んでみました。Vue3 の再構築以降、Vue プロジェクトのディレクトリ構造も大きく変わりました。各機能モジュールはpackagesディレクトリに配置され、責任がより明確になり、ディレクトリ名から一目でわかるようになりました。今日は、Vue エントリ ファイルから始めて、単一の Vue ファイルがcompile-coreどのように宣言され、レンダリング関数にコンパイルされるかを見ていきます。

読者の便宜と記事の長さを抑えるため、ソースコードを読む際にあまり注意を払う必要のないロジックは折り返したり、/* ロジックを無視 */ などのコメントで無視したりします。

個人的には、ソース コード分析記事を読むときに、冒頭に長いコード セクションが表示されるのは好きではありません。これは、それを読んでいない学生を簡単に混乱させる可能性があるためです。そこで、このシリーズの記事では、キーコードのフローチャートを描いてみたいと思います。目的は同じで、全員が理解するためのコストを削減できるようにし、同時に生徒が次回自主的に読むときに参照できるフローチャートを提供することです。

1. Vueエントリファイルの解釈

Vue オブジェクトのエントリ ポイント、 packages/vue/index.tsからソース コードの読み取りを開始します。このエントリ ファイルのコードは比較的単純で、 compileToFunction関数が 1 つだけですが、関数本体の内容は非常に重要です。そのため、まずこの関数本体が何を実現するのかを正確に理解するために、画像を見てみましょう。

フローチャートを見た後は、一緒にコードを見てみましょう。この時点で、ほとんどの生徒は図のコードについて明確に理解していると思います。

すべてのコードをスキップして、ファイルの最後の 35 行を見てください。registerRuntimeCompiler 関数registerRuntiomCompiler呼び出され、 compileToFunction関数がパラメーターとして渡されます。このコード行は、フローチャートの先頭に対応しています。compile compileは、依存性注入を通じてruntimeに注入されます。依存性注入は、分離するための巧妙な方法です。この時点で、実行時にcompileコンパイル関数を呼び出すと、現在のcompileToFunction関数が呼び出されます。

コードの 17 行目を見ると、 compile-domライブラリによって提供されるcompile関数が呼び出され、戻り値からcode変数が分解されています。コンパイラ実行後に生成されるコンパイル結果です。コードはコンパイル結果のパラメータの 1 つであり、コード文字列です。例えば

<テンプレート>
  <div>
    こんにちは世界
  </div>
</テンプレート>

この単純なテンプレートをコンパイルすると、 codeによって返される文字列は次のようになります。

const _Vue = Vue return function render(_ctx, _cache) { with (_ctx) { const { openBlock: _openBlock, createBlock: _createBlock } = _Vue return (_openBlock(), _createBlock("div", null, "Hello World")) } }

この魔法のcompile関数の内部にある謎については、後ほど詳しく説明します。

このコード文字列の結果を取得した後、コードを見ていきます。25 行目ではrender変数を宣言し、生成されたコード文字列 code をnew Functionコンストラクターのパラメーターとして渡します。これはフローチャートの最後から 2 番目のステップで、 render関数を生成します。上記に入力したcode文字列をフォーマットすると、 render関数が、スコープ チェーンを拡張する関数を返すカリー化された関数であることがわかります。

最後に、エントリ ファイルはrender変数を返し、レンダリング関数をキャッシュします。

上記のソースコードの 1 行目を見ると、エントリ ファイルがcompileToFunction関数によって生成されたrender関数をキャッシュするためのcompileCacheオブジェクトを作成し、 templateパラメータをキャッシュ キーとして使用し、11 行目にキャッシュの判断を行う if 分岐があることがわかります。テンプレートが以前にキャッシュされていた場合、テンプレートはコンパイルされなくなり、キャッシュ内のrender関数が直接返されてパフォーマンスが向上します。

この時点で、 package/vue/index.tsのエントリ ファイルが解釈されています。最も興味深い部分は、コード文字列をコンパイルするために compile 関数を呼び出すことであることは皆さんもご存知だと思いますので、次にcompile関数について引き続き説明します。コンパイル機能には、 compile-domcompile-core 2 つのモジュールが含まれます。この記事では、主要なプロセスについてのみ説明します。詳細な分析は後続の記事に掲載されます。コンパイルの実行プロセスを見てみましょう。

2. コンパイル処理

compile関数は、 baseCompile関数の結果を直接返します。実行中、 baseCompile関数は AST 抽象構文木を生成し、 transformを呼び出して各 AST ノードを処理します。たとえば、vOn、v-if、v-for などの命令を変換します。最後に、処理された AST 抽象構文木は、generate 関数によって使用され、上記のコード文字列を生成し、コンパイル結果を返します。この時点で、 compile関数が実行されます。大まかなプロセスを理解したら、ソースコードを見てみましょう。

compile関数のソースコードパスはpackages/compiler-dom/src/index.tsです。compile compileの本体では、 baseCompileの処理結果が直接返されていることがわかります。 baseCompileのソースコード パスはpackages/compiler-core/src/compile.tsです。 baseCompile名前がなぜこのように付けられているのでしょうか? compile-coreコンパイルのコア モジュールであるため、外部パラメータを受け入れてルールに従ってコンパイルを完了します。compile-dom は、特にブラウザー シナリオでのコンパイルを処理するために使用されます。このモジュールでエクスポートされるコンパイル関数は、エントリ ファイルが実際に受け取るコンパイル関数です。 compile-domの compile 関数も、 baseCompileよりも高レベルのコンパイラです。たとえば、Vue が iOS または Android 上の weex などのネイティブ アプリで動作する場合、 compile-dom関連するモバイル コンパイル ライブラリに置き換えられることがあります。

以下の baseCompile 関数を見てみましょう。

まず、関数宣言から、 baseCompile template template と上位レベルの高レベルコンパイラによって処理されたコンパイルoptions options を受け取り、最後にCodegenResult型のコンパイル結果を返します。

エクスポートインターフェースCodegenResult {
  コード: 文字列
  プリアンブル: 文字列
  ast: ルートノード
  マップ?: RawSourceMap
}

CodegenResultのインターフェース宣言を通じて、返された結果にcode文字列、処理された AST 抽象構文ツリー、および sourceMap が含まれていることが明確にわかります。

上記のソース コードの 12 行目を見て、 templateが文字列かどうかを判断します。文字列の場合は文字列が解析され、文字列でない場合はtemplate直接 AST として使用されます。実際、私たちが通常記述する単一ファイルの Vue コードは文字列として渡されます。

次のソースコードは 16 行目です。これは、 transform関数を呼び出し、命令変換やノード変換などのツール関数を渡して、テンプレートによって生成された AST を変換します。

最後に、32 行目で、変換された AST を生成に渡し、 CodegenResult型の戻り結果を生成します。

compile-core モジュールでは、AST 解析、 transformcodegencompile 、およびparse関数はすべて独立した小さなモジュールです。内部実装は非常に洗練されており、コンパイラに関する今後の記事で 1 つずつ紹介されます。

この記事では、エントリ ファイルから始まるコンパイルの一般的なプロセスについて説明します。コンパイラのこのモジュールのコードを読むときに、誰もがプロセスを明確に理解できるようにし、フローチャートとともに読むとさらに興味深くなることを願っています。

これで、Vue3 コンパイルプロセス - ソースコード分析に関するこの記事は終了です。Vue3 コンパイルプロセスの関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • アイデアコンパイラvueインデントエラー問題シナリオの分析
  • Vue でリッチテキストエディタ wangEditor3 を使用する方法
  • Vue3 テンプレートコンパイルの原理に関する深い理解
  • Vue-cliがes6をコンパイルできない問題を解決する
  • Vue プロジェクトのパッケージ化とコンパイルの最適化ソリューション
  • vue プロジェクトをコンパイルする webpack によって生成されるコード探索についての簡単な説明
  • Vue テンプレートのコンパイルの詳細

<<:  Docker インストール Nginx チュートリアル 実装図

>>:  MySQLのデッドロックチェック処理の通常の方法

推薦する

スタックメニューを実装するためのjQueryプラグイン

jQueryプラグインの毎日の積み重ねメニュー、参考までに、具体的な内容は次のとおりです。スタックメ...

Web でよく使われるフォントの紹介 (iOS および Android ブラウザでサポートされているフォント)

年末なので仕事も少なくなっています。私が何もせずにいるのを見ると、上司はきっと不快に思うでしょう。そ...

WeChatアプレットリクエストの前処理方法の詳細な説明

質問一部のページでは、onload でデータを要求してからビューをレンダリングするため、ミニプログラ...

Quickjs は JavaScript サンドボックスの詳細をカプセル化します

目次1. シナリオ2. 基盤となるAPIを簡素化する2.1 自動的に破棄を呼び出す2.2 VM値を作...

フォーム入力ボックスに関するWebデザインのヒント

この記事では、Web デザインにおけるフォーム入力ボックスに関するヒントとコードをいくつか紹介します...

Linux の vsftpd サービス構成の簡単な分析 (匿名、ユーザー、仮想ユーザー)

vsftpd の概要vsftpd は「very secure FTP daemon」の略称で、セキ...

Centos7 でスーパーバイザ デーモンをインストールして設定する方法

初心者は自分で録音しましょう1. スーパーバイザーをインストールします。 Supervisor は ...

CentOS7でFTPサーバーを設定する方法

FTP は主にファイル転送に使用され、Linux では vsftpd で実装されるのが一般的です。F...

Docker基盤技術の適用に関する詳細な説明 名前空間Cgroup

Docker の基盤技術: Docker の基盤となる 2 つのコア テクノロジーは、名前空間とコ...

HTML シンプルな Web フォーム作成例の紹介

<input> はユーザー情報を収集するために使用され、終了ステートメントはありません。...

MySQLの行ロックとテーブルロックの意味と違いの詳細な説明

1. はじめに行ロックとテーブルロックの違いは面接で頻繁に出てくるはずです。MySQL のロックにつ...

Webデザインチュートリアル(1):手順と全体レイアウト

<br />注:ウェブサイトの種類を示すものを除くすべてのテキストは、企業サイト用です。...

Nginx 外部ネットワーク アクセス イントラネット サイト構成操作

背景:サイトはフロントエンドとバックエンドから分離されています: vue+springbootフロン...

Windows Server 2012 でファイル サーバーを構築するための詳細な手順

ファイル サーバーは、企業内で最も一般的に使用されるサーバーの一つであり、主にファイル共有を提供する...

JS ES6 スプレッド演算子の魔法のような使い方

目次1. 属性を追加する2. 複数のオブジェクトを結合する3. オブジェクトのプロパティを削除する4...