Vueコンポーネントドキュメントを自動生成する方法を分析する

Vueコンポーネントドキュメントを自動生成する方法を分析する

1. 現状

Vue フレームワークはフロントエンド開発で広く使用されています。複数の人が開発した Vue プロジェクトを長期間保守すると、多くの共通コンポーネントが沈殿することがよくあります。このとき、1 人の人がコンポーネントを開発している一方で、他の保守者や新人はコンポーネントの機能や使用方法を知らないことがよくあります。彼らはソースコードをもう一度調べる必要があり、コンポーネントの存在にさえ気付かないため、開発が重複することになります。現時点では、さまざまな開発者間の良好なコラボレーションを確保するために、対応するコンポーネント ドキュメントを維持することが非常に重要です。

しかし、従来の手作業によるドキュメントのメンテナンスでは、次のような新たな問題が発生します。

  • 効率が悪いです。ドキュメントを書くのは時間がかかり、肉体的にも大変な作業です。やっとコンポーネントを開発する時間ができたとしても、まだドキュメントを書かなければなりません。考えただけでも気が重くなります。
  • エラーが発生しやすく、ドキュメントの内容にエラーが発生しやすく、実際のコンポーネントの内容と一致しない可能性があります。
  • それは賢明ではありません。コンポーネントを更新するときは、ドキュメントへの変更を手動で同期する必要がありますが、時間がかかり、漏れが発生しやすくなります。

ドキュメントを保守する理想的な方法は次のとおりです。

  • 作業負荷が少なく、Vue コンポーネントと組み合わせることで関連情報を自動取得できるため、ドキュメントを一から作成する作業負荷が軽減されます。
  • 情報は正確であり、コンポーネントのキー情報はコンポーネントの内容とエラーなく一致しています。
  • インテリジェントな同期: Vue コンポーネントが反復的にアップグレードされると、情報の一貫性を手動で確認する必要なく、ドキュメント コンテンツが自動的に同期的に更新されます。

2. コミュニティソリューション

2.1 事業レビュー

上記の理想的な効果を実現するために、コミュニティ内のソリューションを検索して研究しました。現在、Vue は Vue-press を公式に提供しており、これを使用して Vue プロジェクトドキュメントをすばやく構築できます。また、Vue コンポーネントから情報を自動的に抽出できるライブラリもあります。

しかし、既存のサードパーティ ライブラリではニーズを完全に満たすことはできません。主に 2 つの問題があります。

  • 情報は包括的ではなく、v-model を処理できない、属性修飾子 sync を解析できない、メソッド内の関数入力パラメータの詳細情報を取得できないなど、いくつかの重要なコンテンツを取得できません。
  • 例えば、次の例では、value 属性と input イベントを組み合わせて v-model 属性を形成できますが、この情報は生成されたドキュメントには反映されず、ドキュメントの読者が自分で理解して判断する必要があります。また、生成されたドキュメントには同期がサポートされているかどうかは表示されません。

カスタム ロゴが多数あり、ロゴの命名がパーソナライズされすぎているため、元のコードへの大きな侵害が発生します。たとえば、下の図のコードでは、コメントをマークするために、元のビジネス コードに「@vuese」や「@arg」などの追加の識別子を追加する必要があり、これにより、ビジネスに関係のないコンテンツがビジネス コードに追加されます。

3. 技術的ソリューション

上記の問題とコミュニティ ソリューションの欠点に対応するため、私たちのチームは、Vue コンポーネント情報の取得とコンポーネント ドキュメントの出力に特化した小さなツールを開発しました。一般的な効果は次のとおりです。

上の図では、左側が一般的な Vue 単一ファイル コンポーネントで、右側が生成されたドキュメントです。コンポーネントから次の情報が正常に抽出されたことがわかります。

  • コンポーネントの名前。
  • コンポーネントの説明。
  • プロパティ、スロット、イベント、メソッドなど。
  • コンポーネントの注釈コンテンツ。

次に、コンポーネントからこの情報を抽出する方法について詳しく説明します。

3.1. Vueファイルの解析

Vue コンポーネントから情報を抽出したいので、最初の質問は Vue コンポーネントをどのように解析するかということです。 Vue は、Vue 解析専用の Vue-template-compiler ライブラリを公式に開発しており、ここでも同じアプローチを使用できます。ドキュメントを参照すると、Vue-template-compiler が元の Vue ファイルを処理するための parseComponent メソッドを提供していることがわかります。

'Vue-template-compiler' から { parseComponent } をインポートします。
const 結果 = parseComponent(VueFileContent, [オプション])

処理された結果は次のとおりです。ここで、template と script はそれぞれ Vue ファイル内の template と script のテキスト コンテンツに対応します。

エクスポートインターフェースSFCDescriptor {
  テンプレート: SFCBlock | 未定義;
  スクリプト: SFCBlock | 未定義;
  スタイル: SFCBlock[];
  カスタムブロック: SFCBlock[];
}

もちろん、テキストを取得するだけでは十分ではなく、より多くの情報を取得するにはテキストをさらに処理する必要があります。スクリプトを取得したら、babel を使用して js を js AST (抽象構文木) にコンパイルできます。この AST は、js を通じてトラバースして読み取ることができる共通の js オブジェクトです。Ast を使用すると、必要な詳細なコンポーネント情報を取得できます。

'@babel/parser' から { parse } をインポートします。
const jsAst = parse(スクリプト、[オプション]);

次に、テンプレートを見てみましょう。Vue-template-compiler のドキュメントを検索し続けると、compile メソッドが見つかります。Compile は、テンプレートを AST にコンパイルするために特に使用され、まさにニーズを満たしています。

'Vue-template-compiler' から { compile } をインポートします。
const templateAst = compile(テンプレート、[オプション]);

結果の ast はテンプレートのコンパイル結果です。

エクスポートインターフェースCompiledResult {
  ast: AST要素、
  レンダリング: 文字列、
  staticRenderFns: 配列<文字列>,
  エラー: 配列<文字列>
}

ファイル解析の最初のステップを通じて、スクリプト内の Vue テンプレートの AST と js の AST を正常に取得しました。次のステップでは、それらから必要な情報を取得できます。

3.2 情報抽出

同意が必要かどうかに応じて、情報は次の 2 つのタイプに分けられます。

  • 1 つは、props やイベントなど、Vue コンポーネントから直接取得できることです。
  • もう一方のタイプでは、コンポーネントの説明コメント、props プロパティの説明など、追加の合意された形式が必要です。この部分はコメント内に入れて、コメントを解析することで取得できます。

ast から情報を便利に読み取るために、js AST をトラバースするために babel によって提供される公式ライブラリであるツール @babel/traverse について簡単に紹介します。使い方:

'@babel/traverse' から traverse をインポートします

トラバース(jsAst、オプション);

オプションで該当コンテンツのコールバック関数を設定することで、目的の ast ノードを取得できます。具体的な使用方法については、公式ドキュメントを参照してください。

3.2.1. 直接アクセス可能な情報

コードから直接取得できる情報は、情報同期の問題を効果的に解決できます。コードがどのように変更されても、ドキュメントの重要な情報が自動的に同期されるため、手動で校正する手間が省けます。

直接取得できる情報は次のとおりです。

  • コンポーネントのプロパティ
  • 外部呼び出し用のメソッドを提供する
  • イベント
  • スロット

1 と 2 はどちらも、traverse を使用して、js AST 上の props および methods という名前のオブジェクト ノードを直接走査し、それらを取得できます。

イベントを取得するのは少し面倒です。$emit 関数を探すとイベントを見つけることができます。$emit 関数は、MemberExpress (複合型ノード) をトラバースでリッスンし、ノード上の属性名が '$emit' であるかどうかでイベントかどうかを判断できます。イベントの場合は、$emit 親の arguments フィールドを読み取ります。arguments の最初の要素はイベント名で、次の要素はイベント パラメータです。

this.$emit('event', arg);
トラバース(jsAst, {
 メンバー式(ノード) {
  // イベントかどうかを判定する
  if (Node.node.property.name === '$emit') {
  // 最初の要素はイベント名です const eventName = Node.parent.arguments[0];
  }
 }
});

イベントを正常に取得し、イベントと props を組み合わせた後、props 内の 2 つの特殊なプロパティをさらに特定できます。

  • v-model が存在するかどうか: props に value 属性があるかどうか、および Events に入力イベントがあるかどうかを確認します。
  • props のプロパティが同期をサポートしているかどうか: Events の時間名に update で始まるイベントがあるかどうか、およびイベント名がプロパティ名と同じかどうかを判断します。

スロットの情報は、上記のテンプレートの AST に保存されます。テンプレート AST を再帰的にトラバースして、slots という名前のノードを見つけ、ノード上の名前を見つけます。

3.2.2 合意が必要な情報

直接取得できるコンポーネント情報以外に、追加コンテンツについて合意する必要があるのはなぜですか?まず、直接取得できる情報は比較的薄く、比較的完全なコンポーネントドキュメントをサポートするには不十分です。次に、私たちは日常的にコンポーネントを開発するときに多くのコメントを書き込みます。いくつかのコメントを直接抽出してドキュメントに組み込むことができれば、ドキュメントメンテナンスの作業負荷を大幅に軽減できます。

合意できる事項としては次のようなものがあります。

  • コンポーネントの名前。
  • コンポーネントの概要。
  • プロパティ、イベント、メソッド、スロットのテキストによる説明。
  • メソッド タグと入力パラメータの詳細な説明。これらの内容はすべてコメントで保持できます。コメントで保持する理由は、前述の js AST と template AST からコメントを簡単に取得できるためです。Vue コンポーネント情報を解析するときに、対象となる指示のこの部分をまとめて解析できます。

次に、注釈を抽出する方法と、注釈を注釈付きコンテンツと一致させる方法に焦点を当てます。

js 内のコメントは、位置によって leadingComments と trailingComments に分けられます。異なる位置にあるコメントは、対応するフィールドに格納されます。コードは次のようになります。

//ヘッダーコメントエクスポートデフォルト{} //テーラーコメント

解析結果

定数エクスポートノード = {
  タイプ: "ExportDefaultDeclaration",
  主要コメント: [{
    タイプ: 'コメント行',
    値: 'ヘッダーコメント'
  }],
  末尾のコメント: [{
    タイプ: 'コメント行',
    値: '末尾のコメント'
  }]
}

同じ位置で、コメントは形式の違いにより、単一行コメント (CommentLine) とブロックレベルコメント (CommentBlock) に分けられます。2 種類のコメントの違いは、コメント ノードの type フィールドに反映されます。

/** * ブロックレベルコメント */ // 単一行コメントエクスポートデフォルト{}

解析結果

定数エクスポートノード = {
  タイプ: "ExportDefaultDeclaration",
  主要コメント: [
    {
      タイプ: 'コメントブロック',
      値: 'ブロックレベルコメント'
    },
    {
      タイプ: 'コメント行',
      値: '1行コメント'
    }
  ]
}

さらに、上記の解析結果から、コメント ノードがコメント付きエクスポート ノードにマウントされていることもわかります。これにより、上で説明した別の問題、つまりコメントとコメント付きノード間の関連付けを取得する方法も解決されます。実際、Babel はコードをコンパイルするときにこれを実行します。

テンプレートは、コメントとコメントされたコンテンツを別々に検索します。テンプレート内のコメントノードは、他のノードと同様に DOM ノードとして存在します。ノードをトラバースするときに、isComment フィールドの値が true であるかどうかを判断することで、コメントノードであるかどうかを判断します。コメントされたコンテンツは、兄弟ノードの後に​​配置されます。

<!--テンプレートのコメント--> <slot>コメントされたノード</slot>

解析結果

const テンプレートAst = [
  {
    isComment: true、
    テキスト: "テンプレートコメント",
    タイプ: 3
  },
  {
    タグ: "スロット",
    タイプ: 1
  }
]

コメントの処理方法がわかったので、コメントをさらに活用できるようになりました。たとえば、メソッドのコメントで @public タグを使用して、プライベート メソッドとパブリック メソッドを区別できます。詳細が必要な場合は、js コメントを解析するために特別に使用される別のライブラリである js-doc の形式を参照して、メソッドの入力パラメータをさらに説明し、ドキュメントのコンテンツを充実させることもできます。

注釈コンテンツを取得した後は、テキストを切り取って読むだけです。次に例を示します。

エクスポートデフォルト{
  メソッド: {
    /**
     * @公共
     * @param {boolean} 値パラメータの説明*/
    表示(値) {}
  }
}

もちろん、コードへの過度の侵入を避けるために、追加の識別子をできるだけ少なくする必要があります。パラメータの説明では、js-doc と同じ形式を使用します。これは主に、このソリューションがより一般的に使用されており、コード エディターが簡単な編集を自動的にサポートするためです。

IV. 結論

コンポーネントのドキュメントを作成することは、プロジェクト内のフロントエンド開発メンバー間のコラボレーションを改善する優れた方法です。適切に管理されたドキュメントは、開発エクスペリエンスを大幅に向上させます。さらにツールを活用してドキュメントのメンテナンスのプロセスを自動化できれば、開発の満足度はさらに向上します。

一連の調査と試行を経て、Vue コンポーネント情報を自動的に抽出するソリューションを見つけることができました。これにより、Vue コンポーネント ドキュメントの保守作業の負荷が大幅に軽減され、ドキュメント情報の精度が向上しました。具体的な実装としては、まずはvue-template-compilerを使ってVueファイルを処理して、テンプレートASTとjs ASTを取得します。この2つのASTがあれば、より詳しい情報を得ることができます。これまでに生成したドキュメントで取得できる内容と取得方法を整理してみましょう。

取得後に内容をMarkdown形式で出力するかjson形式で出力するかは、実際の開発状況によって異なります。

V. 展望

ここで議論しているのは、単一の Vue ファイルから直接情報を取得して出力することですが、elementUI のドキュメントなど多くのサードパーティ コンポーネント ライブラリと同様に、コンポーネント情報だけでなく表示例もあります。コンポーネントライブラリが比較的よくメンテナンスされている場合、コンポーネントには対応するテストケースがあるはずです。では、コンポーネントのテストケースも抽出し、コンポーネントファイル内のサンプル部分の自動抽出を実現することは可能でしょうか?これも研究する価値のある問題です。

上記は、vue コンポーネント ドキュメントを自動生成する方法を分析する詳細な内容です。vue コンポーネント ドキュメントを自動生成する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vueコンポーネントドキュメント生成ツールライブラリのメソッド

<<:  Tencent インタビュー: SQL ステートメントの実行が非常に遅くなる理由は何ですか? ---後悔シリーズは見ないで(推奨)

>>:  Centos7 で MySQL マスター スレーブ サーバーを構築する方法 (グラフィック チュートリアル)

推薦する

MySQL 5.7.23 バージョンのインストールチュートリアルと設定方法

MySQL を自分でインストールするのに 3 時間かかりました。チュートリアルはたくさんあるにもかか...

WeChatアプレットのスクロールビューが左右の連動を実現

この記事では、WeChatアプレットのスクロールビューの左右連動を実現するための具体的なコードを参考...

メンテナンスしやすい CSS コードを書くための 5 つのガイドライン

1. スタイルシートの先頭にコメント ブロックを追加して、スタイルシートの作成日、作成者、タグ、その...

Reactにおける制御されたコンポーネントと制御されていないコンポーネントの簡単な分析

目次制御されていないコンポーネント制御コンポーネント知らせ結論は制御されていないコンポーネントフォー...

MySQL 5.7.21 winx64 無料インストールバージョン設定方法グラフィックチュートリアル

MySQL 5.7.21 winx64無料インストールバージョンの設定方法、参考までに、具体的な内容...

MySQL での外部キーの作成、制約、削除

序文MySQL バージョン 3.23.44 以降では、InnoDB エンジン タイプのテーブルは外部...

Vue はインターフェースのスライド効果を実装します

この記事では、インターフェースのスライド効果を実現するためのVueの具体的なコードを例として紹介しま...

Vant+postcss-pxtoremはブラウザ適応機能を実装します

Remレイアウトの適応Vant のスタイルでは、デフォルトで px を単位として使用します。rem ...

Mac M1 での Nginx のマルチサイト構成の実装

注: nginxはbrew経由でインストールされますウェブサイトのルートディレクトリ: /opt/h...

Mysql varchar型の合計操作例

友人の中には、データベースについて学習しているときに、テーブル構造を作成するときに誤ってフィールドを...

Dockerに証明書を追加する方法

1. アップグレードプロセス: sudo apt-get updateパッケージが見つからない、パッ...

MySQL のジオメトリ型を使用して経度と緯度の距離の問題を処理する方法

テーブルを作成する テーブル `map` を作成します ( `id` int(11) NULLではな...

JavaScript Reduceの詳しい説明

目次地図フィルターいくつかの毎インデックスを検索パイプ参考回答1. パラメータを受け入れる関数を返す...

jsはシンプルな計算機を実装します

参考までに、ネイティブjsを使用して簡単な計算機(詳細なコメント付き)を実装します。具体的な内容は次...

Mysql SSHトンネル接続を使用するための基本的な手順

序文セキュリティ上の理由から、MySQL の root ユーザーはローカルにのみログインでき、外部ネ...