Ia adalah hari menampal biasa. Saya menampal dan menaik taraf kebergantungan npm saya tanpa membuat perubahan kod, dan tiba-tiba, beberapa ujian unit saya gagal.
Wtf!
Ujian saya gagal kerana Jest menemui token yang tidak dijangka; mereka gagal kerana Jest tidak dapat mengendalikan pakej ESM sahaja di luar kotak. Malah, Jest ditulis dalam CommonJS.
Tetapi apakah maksudnya? Untuk berbuat demikian, kita perlu memahami sebab CommonJS dan ESM wujud.
Pada hari-hari awal pembangunan web, JavaScript digunakan terutamanya untuk memanipulasi Model Objek Dokumen (DOM) dengan perpustakaan seperti jQuery. Walau bagaimanapun, pengenalan Node.js juga menyebabkan JavaScript digunakan untuk pengaturcaraan sebelah pelayan. Peralihan ini meningkatkan kerumitan dan saiz pangkalan kod JavaScript. Akibatnya, timbul keperluan untuk kaedah berstruktur untuk mengatur dan mengurus kod JavaScript. Sistem modul telah diperkenalkan untuk memenuhi keperluan ini, membolehkan pembangun membahagikan kod mereka kepada unit yang boleh diurus dan boleh digunakan semula1.
CommonJS ditubuhkan pada tahun 2009, asalnya bernama ServerJS2. Ia direka untuk JavaScript bahagian pelayan, menyediakan konvensyen untuk menentukan modul. Node.js menggunakan CommonJS sebagai sistem modul lalainya, menjadikannya lazim dalam kalangan pembangun JavaScript bahagian belakang. Penggunaan CommonJS memerlukan untuk mengimport dan module.exports untuk mengeksport modul. Semua operasi dalam CommonJS adalah segerak, bermakna setiap modul dimuatkan secara individu.
Pada 2015, ECMAScript memperkenalkan sistem modul baharu yang dipanggil ECMAScript Modules (ESM), terutamanya menyasarkan pembangunan sisi pelanggan. ESM menggunakan penyata import dan eksport, dan operasinya adalah tak segerak, membolehkan modul dimuatkan secara selari3. Pada mulanya, ESM bertujuan untuk pelayar, manakala CommonJS direka untuk pelayan. Ia menjadi semakin standard untuk ekosistem JS. Pada masa kini, masa jalan JavaScript moden menyokong kedua-dua sistem modul. Penyemak imbas mula menyokong ESM secara asli pada tahun 2017. Malah Typescript menyesuaikan sintaks ESM, dan setiap kali anda mempelajarinya, anda juga mempelajari ESM secara tidak sedar.
Sebenarnya terdapat lebih banyak pakej CommonJS (CJS)- sahaja daripada pakej ESM sahaja4.
Walau bagaimanapun, terdapat trend yang jelas. Bilangan pakej ESM sahaja atau dwi modul semakin meningkat, manakala lebih sedikit pakej CJS sahaja sedang dibuat. Aliran ini menekankan keutamaan yang semakin meningkat untuk ESM dan menimbulkan persoalan tentang berapa banyak pakej CJS sahaja yang diselenggara secara aktif.
Perbandingan menarik antara CommonJS dan ESM melibatkan penanda aras prestasi. Disebabkan sifat segeraknya, CommonJS lebih pantas apabila secara langsung menggunakan penyata memerlukan dan import. Mari kita pertimbangkan contoh berikut:
// CommonJS -> s3-get-files.cjs const s3 = require('@aws-sdk/client-s3'); new s3.S3Client({ region: 'eu-central-1' }); // ESM -> s3-get-files.mjs import { S3Client } from '@aws-sdk/client-s3'; new S3Client({ region: 'eu-central-1' });
Saya menggunakan aws-sdk S3-Client kerana ia mempunyai sokongan dwi modul. Di sini kami membuat instantiate pelanggan dan kemudian melaksanakannya dengan nod:
hyperfine --warmup 10 --style color 'node s3-get-files.cjs' 'node s3-get-files.mjs' Benchmark 1: node s3-get-files.cjs Time (mean ± σ): 82.6 ms ± 3.7 ms [User: 78.5 ms, System: 16.7 ms] Range (min … max): 78.0 ms … 93.6 ms 37 runs Benchmark 2: node s3-get-files.mjs Time (mean ± σ): 93.9 ms ± 4.0 ms [User: 98.3 ms, System: 18.1 ms] Range (min … max): 88.1 ms … 104.8 ms 32 runs Summary node s3-get-files.cjs ran 1.14 ± 0.07 times faster than node s3-get-files.mjs
Seperti yang anda lihat, s3-get-files.cjs dan, dengan itu, CommonJS berjalan lebih pantas.
Saya mendapat inspirasi dari Buns Blogpost.
Namun, apabila anda ingin menghasilkan perpustakaan JS anda, anda perlu menggabungkannya. Jika tidak, anda akan menghantar semua node_modules. Digunakan esbuild kerana ia dapat digabungkan ke CJS dan ESM. Sekarang, mari jalankan penanda aras yang sama dengan versi yang digabungkan.
hyperfine --warmup 10 --style color 'node s3-bundle.cjs' 'node s3-bundle.mjs' Benchmark 1: node s3-bundle.cjs Time (mean ± σ): 62.1 ms ± 2.5 ms [User: 53.8 ms, System: 6.7 ms] Range (min … max): 59.5 ms … 74.5 ms 45 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 2: node s3-bundle.mjs Time (mean ± σ): 45.3 ms ± 2.2 ms [User: 38.1 ms, System: 5.6 ms] Range (min … max): 43.0 ms … 59.2 ms 62 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Summary node s3-bundle.mjs ran 1.37 ± 0.09 times faster than node s3-bundle.cjs
Seperti yang anda lihat, s3-bundle.mjs kini lebih pantas daripada s3-bundle.cjs. Fail ESM kini lebih pantas daripada fail CommonJS yang tidak dihimpunkan kerana ia menghasilkan saiz fail yang lebih kecil dan masa pemuatan yang lebih cepat disebabkan penggoncangan pokok yang cekap—suatu proses yang mengalih keluar kod yang tidak digunakan.
Masa depan modul JavaScript sudah pasti cenderung kepada ESM. Ini bermula apabila mencipta projek NodeJS baharu atau malah projek React. Setiap tutorial dan artikel menggunakan pernyataan import, iaitu ESM. Walaupun terdapat banyak pakej CommonJS sedia ada, trend ini berubah apabila lebih ramai pembangun dan penyelenggara mengguna pakai ESM untuk faedah prestasi dan sintaks modennya. Soalan lain juga ialah berapa banyak projek CJS sahaja ini masih dikekalkan.
ESM ialah standard yang berfungsi dalam sebarang masa jalan, seperti NodeJS, Bun atau Deno, dan dalam penyemak imbas tanpa berjalan pada pelayan. Ia tidak perlu untuk menukar melalui Babel kepada CommonJS kerana pelayar memahami ESM. Anda masih boleh menggunakan Babel untuk menukar kepada versi ECMAScript yang berbeza, tetapi anda tidak sepatutnya menukar kepada CJS.
Anda harus membangun dalam ESM sahaja kerana setiap masa jalan sekarang dan penyemak imbas yang lebih baharu daripada 2017 memahami ESM.
Jika kod anda rosak, anda mungkin menghadapi masalah warisan. Pertimbangkan untuk menggunakan alatan atau pakej yang berbeza. Sebagai contoh, anda boleh berhijrah dari Jest ke vitest atau dari ExpressJS ke h3. Sintaks tetap sama; bezanya cuma penyata import.
Pengambilan Utama:
Untuk bermula, anda boleh mengikuti Gist ini atau dapatkan pembelajaran inspirasi di sini.
Untuk Masa Depan JavaScript yang lebih baik, Hayati ESM!
Pembentangan
https://www.freecodecamp.org/news/javascript-es-modules-and-module-bundlers/#why-use-modules ↩
https://deno.com/blog/commonjs-is-hurting-javascript ↩
https://tc39.es/ecma262/#sec-overview ↩
https://twitter.com/wooorm/status/1759918205928194443 ↩
Atas ialah kandungan terperinci Oh CommonJS! Kenapa awak mESMing dengan saya?! Sebab untuk membuang CommonJS. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!