最近、私たちは名前付きエクスポート/インポートに移行し、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 つの段階にリファクタリングしました。
データ収集: 最初のフェーズでは、コードベース全体のデフォルトのインポートとエクスポートのすべてのインスタンスを収集します
変換: データが収集されると、第 2 フェーズでデフォルトのエクスポートが名前付きエクスポートに書き換えられます。 jscodeshift を使用して、ソース コードを並列かつ簡単に変換しました。
次の 2 つのステップに分割します:
ケースが蓄積し始めたので (動的インポート、再エクスポートされたデフォルト、エクスポートされたさまざまなエンティティ: 変数、関数、クラス、変数の問題の既に使用されている名前など)、テスト ケースのセットアップに追加の時間を費やしました。約 30 分でしっかりとしたテストのセットアップが完了し、テスト駆動開発 (TDD) に移行できるようになりました。信じてください。膨大な数のケースがあるこのようなツールの TDD に時間を費やす価値はあります。さらに進めば進むほど、テスト ケースからより多くの価値を感じることができます。テストがない場合にケースの半分をカバーした後、変更を追加する必要があるたびに他の多くのケースが壊れる可能性があるため、巨大なプロジェクトを実行してデバッグするのは悪夢になります。
AST:
次のタイプの AST ノードを使用しました:
技術的な考慮事項と既知の制限事項
このツールは機能しますが、まだ処理されていないいくつかの特殊なケースがあります:
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.
以上です。以下のコメントを歓迎します! ?
以上がデフォルトのエクスポートを書き換えるための Codemod ツールを構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。