デフォルトのエクスポートを書き換えるための Codemod ツールを構築する
最近、私たちは名前付きエクスポート/インポートに移行し、eslint ルール no-default-export を追加することにしました。
動機は次のようなものでした。
デフォルトのエクスポートでは、特に大規模なコードベースでは、コードの保守が困難になる可能性があります。インポートされた名前は同じエンティティでも異なる場合があり、コードの読み取りプロセスや静的アナライザーの作成に影響を及ぼし、作業がより困難になります。逆に、名前付きエクスポートに切り替えると、デフォルトのエクスポートの欠点がすべて解消されます。
もちろん、私たちは巨大なコードベースを持っており、~1500 のデフォルトのエクスポートと~12000 のデフォルトのインポートを手動で置き換えるのは興味深い仕事ではありません?
主な問題は、名前付きエクスポート用に作成された、リンクされたすべてのファイルを同じ新しい識別子で更新することでした。
例を挙げます:
// Button/Button.tsx const Button = () => {}; export default Button; // Button/index.ts export { default } from './Button.tsx'; // SomePage1.tsx import OldButton from './component/Button'; // SomePage2.tsx import TestButton from './component/Button';
そして私が想定した目標結果は次のようになります:
// Button/Button.tsx export const Button = () => {}; // Button/index.ts export { Button } from './Button.tsx'; // SomePage1.tsx import { Button as OldButton } from './component/Button'; // SomePage2.tsx import { Button as TestButton } from './component/Button';
私がインターネットで見つけた各解決策は、そのファイルの外部には何も知ることなく、各ファイルを個別に変換する単なる codemod でした。
私は次のようなパーサーを夢見始めました。
- プロジェクト内のすべてのインポートを解決し、ファイル間の関係を保存します
- デフォルトのインポート/エクスポートに関する情報を収集します
- 名前付きエクスポートの新しい識別名を作成します
- リポジトリ全体のすべてのエントリを置き換えますか?
そこで私は、デフォルトのエクスポート/インポートを名前付きエクスポート/インポートに自動的に書き換える codemod ツールを開発するという新たな挑戦をしました。
もう開発しました! ? ? ネタバレ
開発プロセス
最初の考え
これは、前回の実験「反応コンポーネント ツリーの視覚化」の直後に起こりました。最初のアイデアは、babel プラグインと webpack プラグインを再利用して、すべてのモジュールを反復処理して AST を解析することでした。しかし、jscodeshift にすでにパーサーがあり、jscodeshift の代わりとなるパーサーが見つかったとしたら、なぜでしょうか。 webpack プラグインを使用すると、バンドラーに依存しないツールを作成できるようになります。
ツール
OK、パーサーとして jscodeshift を使用しました。しかし、エントリポイントから始まるすべてのファイル間の関係を見つけるために、ネイティブのnodejs require.resolveなどのパスを解決するのに役立つresolveパッケージを見つけましたが、バンドラーのようなパスを解決することに似ており、拡張子、同期をより詳細に制御できます。 /async 動作など
2 段階プロセスのエンジニアリング
私のツールの初期バージョンは、すべてが 1 つのスクリプトにまとめられているようなものでした。ただし、柔軟性とパフォーマンスを向上させ、デバッグを伴う開発プロセスを簡素化するために、ツールを 2 つの段階にリファクタリングしました。
-
データ収集: 最初のフェーズでは、コードベース全体のデフォルトのインポートとエクスポートのすべてのインスタンスを収集します
- このフェーズを制御するために、環境変数 IS_GATHER_INFO を導入しました。スクリプトは、resolve を使用して、デフォルトのエクスポート / インポート のすべての使用法を検索します。
- 別の環境変数 ENTRY には、コードベースのエントリ ポイントへの相対パスが含まれており、そのファイルから開始して、すべてのインポートが解決および分析されます
-
変換: データが収集されると、第 2 フェーズでデフォルトのエクスポートが名前付きエクスポートに書き換えられます。 jscodeshift を使用して、ソース コードを並列かつ簡単に変換しました。
- このフェーズを制御するために、環境変数 IS_TRANSFORM を導入しました
次の 2 つのステップに分割します:
- データ収集を変換から切り離すことができ、実行されるコードの量と、開発とデバッグに費やす時間を削減できました。
- gatherInfo 関数の結果を確認し、分析し、コードを再実行するのに非常に便利な方法です
- 収集したデータを使用してパイプライン全体を繰り返し実行せずに変換をテストします
- データ ダンプの収集は、さまざまなエントリ ポイントに対してこのツールを実行する必要があるが、収集されたデータを再利用する必要がある場合に役立ちます
ケースが蓄積し始めたので (動的インポート、再エクスポートされたデフォルト、エクスポートされたさまざまなエンティティ: 変数、関数、クラス、変数の問題の既に使用されている名前など)、テスト ケースのセットアップに追加の時間を費やしました。約 30 分でしっかりとしたテストのセットアップが完了し、テスト駆動開発 (TDD) に移行できるようになりました。信じてください。膨大な数のケースがあるこのようなツールの TDD に時間を費やす価値はあります。さらに進めば進むほど、テスト ケースからより多くの価値を感じることができます。テストがない場合にケースの半分をカバーした後、変更を追加する必要があるたびに他の多くのケースが壊れる可能性があるため、巨大なプロジェクトを実行してデバッグするのは悪夢になります。
AST:
次のタイプの AST ノードを使用しました:
-
デフォルトのインポートステートメントのみを検索する ImportDefaultSpecifier
- 「...」から何かをインポートします
-
ExportDefaultDeclaration を使用して、デフォルトのエクスポート ステートメントのみを検索します。
- デフォルトのものをエクスポートします;
-
ExportNamedDeclaration を使用してインポート デフォルト ステートメントとエクスポート デフォルト ステートメントを検索します。
- 「...」から { デフォルトとして何か } をエクスポートします - デフォルトのエクスポート
- import { デフォルトを何かとして } from '...' - デフォルトのインポート
- export {default} from '...' - デフォルトのインポートとデフォルトのエクスポートを同時に実行します
-
ImportExpression を使用して動的インポートを検索し、そのファイルを必要に応じてマークし、デフォルトのエクスポートを保持します。 React.lazy などの一部のツールは、デフォルトのエクスポートでのみ機能します。
- インポート('...')
- また、プロキシ ファイルに関する情報を保存しました。これは、デフォルトの何かをインポートし、その何かをデフォルトとしてエクスポートするファイルです。
- これを使用して、任意のファイル内の名前付きエクスポートの新しい名前を検索します: file a ->ファイルb ->ファイルc
技術的な考慮事項と既知の制限事項
このツールは機能しますが、まだ処理されていないいくつかの特殊なケースがあります:
namespace.default の使用法
次のコードはまだ変換されません:
// Button/Button.tsx const Button = () => {}; export default Button; // Button/index.ts export { default } from './Button.tsx'; // SomePage1.tsx import OldButton from './component/Button'; // SomePage2.tsx import TestButton from './component/Button';
プロキシ ファイルの競合
出典:
// Button/Button.tsx export const Button = () => {}; // Button/index.ts export { Button } from './Button.tsx'; // SomePage1.tsx import { Button as OldButton } from './component/Button'; // SomePage2.tsx import { Button as TestButton } from './component/Button';
結果:
import * as allConst from './const'; console.log(allConst.default);
のようなめちゃくちゃなエクスポート
出典:
export { Modals as default } from './Modals'; export { Modals } from './Modals';
実装が異なる 2 つの同じエクスポートがあるため、ロジックが壊れます:
export { Modals } from './Modals'; export { Modals } from './Modals';
前のエンティティのインポートも手動で修正する必要があります
出典:
export class GhostDataProvider {} export default hoc()(GhostDataProvider);
結果:
export class GhostDataProvider {} const GhostDataProviderAlias = hoc()(GhostDataProvider); export { GhostDataProviderAlias as GhostDataProvider };
これらの制限にもかかわらず、残りのエラーを 15 ~ 20 分で手動で修正し、実際のプロジェクトを正常に起動しました。 rewrite-default-exports.
リンク
- jscodeshift
- アストエクスプローラー
以上です。以下のコメントを歓迎します! ?
以上がデフォルトのエクスポートを書き換えるための Codemod ツールを構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。
