Rumah > hujung hadapan web > tutorial js > Membina Alat Codemod untuk Menulis Semula Eksport Lalai

Membina Alat Codemod untuk Menulis Semula Eksport Lalai

DDD
Lepaskan: 2024-11-03 02:36:02
asal
1008 orang telah melayarinya

Building a Codemod Tool for Rewriting Default Exports

Baru-baru ini di tempat kerja, kami memutuskan untuk berhijrah ke eksport/import yang dinamakan dan menambah peraturan eslint no-default-export.

Motivasi berbunyi seperti:

Eksport lalai boleh menjadikan kod lebih sukar untuk dikekalkan, terutamanya dalam pangkalan kod yang besar. Nama yang diimport mungkin berbeza untuk entiti yang sama, menjejaskan proses membaca kod dan menulis penganalisis statik, menjadikannya lebih sukar. Sebaliknya, beralih kepada eksport dinamakan akan mengalih keluar semua kelemahan eksport lalai.

Sudah tentu, kami mempunyai pangkalan kod yang besar dan bukan tugas yang menarik untuk menggantikan ~1500 eksport lalai dan ~12000 import lalai secara manual ?

Kesukaran utama adalah mengemas kini semua fail yang dipautkan dengan pengecam baharu yang sama, dibuat untuk eksport yang dinamakan.

Saya berikan anda contoh:

// 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';
Salin selepas log masuk
Salin selepas log masuk

Dan hasil sasaran yang saya kira akan kelihatan seperti ini:

// 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';
Salin selepas log masuk
Salin selepas log masuk

Setiap penyelesaian yang saya temui di internet hanyalah codemod untuk mengubah setiap fail secara bebas tanpa mengetahui perkara lain di luar fail itu.

Saya mula bermimpi tentang penghurai yang akan:

  1. selesaikan semua import dalam projek dan simpan hubungan antara fail
  2. kumpul maklumat tentang import/eksport lalai
  3. buat nama pengecam baharu untuk eksport bernama
  4. ganti semua entri merentas repo ?

Jadi saya mengambil cabaran baharu untuk membangunkan alat codemod yang secara automatik menulis semula eksport/import lalai kepada yang dinamakan.

spoiler

Saya sudah membangunkannya! ? ?

Proses pembangunan

Fikiran pertama
Ia berlaku sejurus selepas percubaan saya sebelum ini Visualize react component tree dan idea pertama adalah untuk menggunakan semula pemalam babel dan webpack untuk lelaran melalui semua modul dan menghuraikan AST, tetapi mengapa, jika jscodeshift sudah mempunyai parser, dan jika saya menemui pengganti untuk pemalam webpack saya akan dapat menulis alat pengikat-agnostik, bagus ?

Alat
Ok, saya mempunyai jscodeshift sebagai penghurai. Tetapi untuk mencari hubungan antara semua fail bermula dari titik masuk, saya menemui pakej penyelesaian, yang membantu menyelesaikan laluan seperti nodejs asli require.resolve, tetapi ia lebih serupa dengan menyelesaikan laluan seperti bundler, anda mempunyai lebih kawalan ke atas sambungan, penyegerakan tingkah laku /async, dsb.

Kejuruteraan Proses Dua Langkah
Versi awal alat saya adalah seperti segala-galanya dalam satu skrip. Walau bagaimanapun, untuk meningkatkan fleksibiliti dan prestasi serta memudahkan proses pembangunan dengan penyahpepijatan, saya memfaktorkan semula alat kepada dua peringkat:

  1. Pengumpulan Data: Fasa pertama mengumpulkan semua contoh import dan eksport lalai merentas pangkalan kod

    • Saya memperkenalkan pembolehubah persekitaran, IS_GATHER_INFO, untuk mengawal fasa ini. Skrip menggunakan tekad untuk mencari setiap penggunaan eksport / import lalai
    • Entri env var lain mengandungi laluan relatif ke titik masuk asas kod anda, bermula dari fail itu, semua import akan diselesaikan dan dianalisis
  2. Transformasi: Setelah data dikumpul, fasa kedua menulis semula eksport lalai ke dalam eksport bernama. Menggunakan jscodeshift, saya menukar kod sumber secara selari dan mudah.

    • Saya memperkenalkan pembolehubah persekitaran, IS_TRANSFORM, untuk mengawal fasa ini

Dengan membahagikan kepada dua langkah ini:

  • Saya dapat mengasingkan pengumpulan data daripada transformasi, mengurangkan jumlah kod yang dilaksanakan dan menghabiskan masa semasa pembangunan dan penyahpepijatan
    • Ini adalah cara yang sangat mudah untuk melihat hasil fungsi gatherInfo, menganalisisnya, menjalankan semula kod anda
    • Uji transformasi tanpa berulang kali menjalankan keseluruhan saluran paip dengan data pengumpulan
  • Mengumpul pembuangan data berguna jika anda perlu menjalankan alat ini untuk titik masuk yang berbeza tetapi menggunakan semula data yang dikumpul

Apabila kes mula terkumpul (seperti import dinamik, lalai dieksport semula, entiti eksport yang berbeza: pembolehubah, fungsi dan kelas serta nama isu pembolehubah yang sudah digunakan) masa itu saya meluangkan masa tambahan untuk menyediakan kes ujian. Dalam masa kira-kira 30 minit saya mempunyai persediaan ujian yang kukuh, membolehkan saya beralih kepada pembangunan dipacu ujian (TDD). Percayalah, anda berbaloi untuk meluangkan masa menggunakan TDD untuk alatan sedemikian, yang mempunyai bilangan kes yang sangat besar. Lebih jauh anda pergi, lebih banyak nilai yang anda rasa daripada kes ujian anda. Saya akan mengatakan bahawa selepas menutup separuh daripada kes jika anda tidak mempunyai ujian, ia menjadi mimpi ngeri untuk menjalankan dan nyahpepijat pada projek besar kerana setiap kali anda perlu menambah beberapa perubahan, ia mungkin memecahkan banyak kes lain.

AST:
Saya menggunakan jenis nod AST berikut:

  • ImportDefaultSpecifier untuk mencari hanya import pernyataan lalai
    • import sesuatu daripada '...'
  • ExportDefaultDeclaration untuk mencari hanya eksport pernyataan lalai
    • eksport sesuatu lalai;
  • ExportNamedDeclaration untuk mencari pernyataan lalai import dan eksport lalai
    • eksport { sesuatu sebagai lalai } daripada '...' - eksport lalai
    • eksport { lalai sebagai sesuatu } daripada '...' - import lalai
    • eksport { lalai } daripada '...' - import lalai dan eksport lalai serentak
  • ImportExpression untuk mencari import dinamik dan tandakan fail itu sebagai diperlukan untuk mengekalkan eksport lalai. Sesetengah alatan seperti React.lazy berfungsi dengan eksport lalai sahaja.
    • import('...')
  • Selain itu, saya menyimpan maklumat tentang fail proksi, ia ialah fail yang mengimport sesuatu lalai dan mengeksport sesuatu itu sebagai lalai
    • Menggunakannya untuk mencari nama baharu eksport yang dinamakan dalam mana-mana fail: fail a -> fail b -> fail c

Pertimbangan Teknikal dan Had yang Diketahui
Walaupun alat ini berfungsi, terdapat beberapa kes tepi yang masih belum dikendalikan:

ruang nama.penggunaan lalai
kod berikut tidak akan ditukar lagi:

// 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';
Salin selepas log masuk
Salin selepas log masuk

Konflik dalam fail proksi
sumber:

// 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';
Salin selepas log masuk
Salin selepas log masuk

hasil:

import * as allConst from './const';
console.log(allConst.default);
Salin selepas log masuk

Eksport berantakan seperti
sumber:

export { Modals as default } from './Modals';
export { Modals } from './Modals';
Salin selepas log masuk

akan mengakibatkan logik rosak, kerana kini ia mempunyai dua eksport yang sama dengan pelaksanaan yang berbeza:

export { Modals } from './Modals';
export { Modals } from './Modals';
Salin selepas log masuk

Dan import untuk entiti sebelumnya juga harus dibetulkan secara manual
sumber:

export class GhostDataProvider {}
export default hoc()(GhostDataProvider);
Salin selepas log masuk

hasil:

export class GhostDataProvider {}
const GhostDataProviderAlias = hoc()(GhostDataProvider);
export { GhostDataProviderAlias as GhostDataProvider };
Salin selepas log masuk

Walaupun pengehadan ini, saya membetulkan baki ralat secara manual dalam 15-20 minit dan berjaya membuat projek sebenar kami. Eksport-lalai-tulis semula.

Pautan

  • jscodeshift
  • astexplorer

Itu sahaja, selamat datang ke komen di bawah! ?

Atas ialah kandungan terperinci Membina Alat Codemod untuk Menulis Semula Eksport Lalai. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan