Baru-baru ini di tempat kerja, kami memutuskan untuk berhijrah ke eksport/import yang dinamakan dan menambah peraturan eslint no-default-export.
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';
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';
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:
Jadi saya mengambil cabaran baharu untuk membangunkan alat codemod yang secara automatik menulis semula eksport/import lalai kepada yang dinamakan.
Saya sudah membangunkannya! ? ? spoiler
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:
Pengumpulan Data: Fasa pertama mengumpulkan semua contoh import dan eksport lalai merentas pangkalan kod
Transformasi: Setelah data dikumpul, fasa kedua menulis semula eksport lalai ke dalam eksport bernama. Menggunakan jscodeshift, saya menukar kod sumber secara selari dan mudah.
Dengan membahagikan kepada dua langkah ini:
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:
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';
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';
hasil:
import * as allConst from './const'; console.log(allConst.default);
Eksport berantakan seperti
sumber:
export { Modals as default } from './Modals'; export { Modals } from './Modals';
akan mengakibatkan logik rosak, kerana kini ia mempunyai dua eksport yang sama dengan pelaksanaan yang berbeza:
export { Modals } from './Modals'; export { Modals } from './Modals';
Dan import untuk entiti sebelumnya juga harus dibetulkan secara manual
sumber:
export class GhostDataProvider {} export default hoc()(GhostDataProvider);
hasil:
export class GhostDataProvider {} const GhostDataProviderAlias = hoc()(GhostDataProvider); export { GhostDataProviderAlias as GhostDataProvider };
Walaupun pengehadan ini, saya membetulkan baki ralat secara manual dalam 15-20 minit dan berjaya membuat projek sebenar kami. Eksport-lalai-tulis semula.
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!