Anda mungkin pernah menggunakan modul ES dalam pembangunan JavaScript moden, tetapi adakah anda tahu sejarah di sebalik evolusinya? Memahami perjalanan daripada amalan JavaScript awal kepada sistem modul hari ini akan membantu anda menghargai sejauh mana kami telah melangkah dan sebab modul ES merupakan pengubah permainan.
Tahunnya ialah 1995, empat tahun selepas halaman web pertama dicipta. Kebanyakan tapak web adalah mudah — halaman statik dengan teks dan interaktiviti yang minimum. Walau bagaimanapun, pembangun dengan cepat mencari cara untuk menjadikan halaman web lebih dinamik.
Dalam persekitaran ini, Netscape (pelayar web yang dominan pada masa itu) mengupah Brendan Eich untuk mencipta bahasa skrip yang akan dijalankan terus dalam penyemak imbas. Ini membawa kepada kelahiran JavaScript, bahasa yang direka bentuk untuk menjadi mudah dan boleh diakses, terutamanya untuk bukan pengaturcara seperti pereka web. Begitu juga dia, melengkapkan versi pertama dalam 10 hari.
Pada asalnya, JavaScript bertujuan untuk menambahkan peningkatan kecil pada halaman web, seperti pengesahan borang, tanpa perlu menghantar data pergi balik ke pelayan. Walau bagaimanapun, apabila tapak web menjadi lebih interaktif, JavaScript dengan cepat berkembang melebihi tujuan asalnya.
Pada zaman awal, semua kod JavaScript hidup dalam skop global. Memandangkan lebih ramai pembangun menambahkan kod pada halaman yang sama, risiko perlanggaran nama meningkat. Jika berbilang skrip menggunakan pembolehubah atau nama fungsi yang sama, kod itu boleh pecah dengan cara yang tidak dijangka.
Untuk mengurus ini, pembangun menggunakan konvensyen penamaan untuk mengelakkan perlanggaran. Jika sekeping kod dimaksudkan untuk dijalankan sekali sahaja, pembangun sering membungkusnya dalam IIFE (Ungkapan Fungsi Segera Diminta). Ini mengekalkan fungsi dan pembolehubah dalam skop dalam fungsi, menghalangnya daripada mencemarkan ruang nama global.
(function init() { function getData(){ // ... } })()
Ini cukup bagus pada masa itu kerana kebanyakan tapak web adalah bahagian pelayan yang diberikan dengan logik sebelah pelanggan yang sangat sedikit.
Pada tahun 2008 Ryan Dahl mencipta Node.js, masa jalan JavaScript untuk membina aplikasi sisi pelayan. Ini membuka peluang dunia yang baharu, tetapi kekurangan sistem modul menyebabkan pembangun bergelut untuk menguruskan pangkalan kod yang besar.
Pada tahun 2009, CommonJS telah diperkenalkan untuk menyelesaikan masalah ini untuk bahagian pelayan. Sistem modul CommonJS membenarkan pembangun mentakrifkan modul, mendedahkan kefungsian dan mengimport modul lain. Berikut ialah contoh cara ia berfungsi:
const math = require("./math"); function subtract(a,b) { return math.add(a,-b); } module.exports = { subtract: subtract }
Dengan CommonJS, setiap fail dianggap sebagai modulnya sendiri dan modul diimport menggunakan fungsi memerlukan dan dieksport menggunakan module.exports.
Beberapa ciri utama CommonJS termasuk:
Sambungan fail adalah pilihan apabila memerlukan modul (cth., require('./math') mencari math.js secara automatik).
Pemuatan modul adalah segerak, bermakna program menunggu modul dimuatkan sebelum meneruskan pelaksanaan.
Kemudian dalam artikel kita akan melihat mengapa Ryan Dahl mengaku menyesali 2 keputusan reka bentuk ini.
Pada masa yang sama, sistem modul lain yang dipanggil AMD (Definisi Modul Asynchronous) telah dibangunkan. Walaupun CommonJS tertumpu terutamanya pada JavaScript sisi pelayan, AMD direka untuk mengendalikan JavaScript sisi klien dalam penyemak imbas.
Ciri utama AMD ialah keupayaannya untuk memuatkan modul secara tidak segerak. Ini membenarkan penyemak imbas memuatkan JavaScript sahaja yang diperlukan untuk halaman pada bila-bila masa, meningkatkan prestasi dengan mengurangkan masa muat halaman awal. Ia juga menyelesaikan isu yang berkaitan dengan resolusi kebergantungan, memastikan modul hanya akan dijalankan setelah kebergantungannya selesai dimuatkan.
Faedah AMD termasuk:
Dengan peningkatan npm pada tahun 2010 (pengurus pakej untuk JavaScript bahagian pelayan), keperluan untuk berkongsi kod merentas penyemak imbas dan pelayan menjadi jelas. Masukkan Browserify, alat yang membenarkan pembangun menggunakan modul CommonJS dalam penyemak imbas dengan mengubah kod agar serasi dengan persekitaran penyemak imbas.
Dengan 2 piawaian yang bersaing, CommonJS dan AMD. Terdapat keperluan untuk sistem modul tunggal yang boleh berfungsi di mana-mana tanpa memerlukan langkah binaan. Dan pada tahun 2011, definisi modul universal(UMD) telah diperkenalkan.
UMD menggabungkan yang terbaik dari kedua-dua dunia, membolehkan pembangun menulis modul yang boleh dijalankan dalam:
UMD menjadi sangat popular di kalangan pengarang perpustakaan dengan perpustakaan terkenal seperti Lodash, Underscore.js, Backbone.js dan Moment.js menggunakannya. Walau bagaimanapun, UMD mempunyai beberapa kelemahan yang ketara. Walaupun ia menyelesaikan masalah keserasian, ia datang dengan kerumitan mengurus kedua-dua sistem, dan ia mewarisi masalah kedua-dua AMD dan CommonJS.
Pada 2015, ES Modules (ESM) telah diperkenalkan sebagai sebahagian daripada standard ECMAScript, akhirnya menawarkan sistem modul asli untuk JavaScript. Menjelang 2017, semua penyemak imbas utama menyokong modul ES, dan pada 2020, Node.js turut menambah sokongan.
Jom lihat mengapa modul ES adalah yang terbaik:
Kod UMD berikut:
(function init() { function getData(){ // ... } })()
kini boleh dikurangkan kepada:
(function init() { function getData(){ // ... } })()
Untuk bersikap adil, tiada siapa yang menulis UMD seperti itu. Mereka menggunakan alat seperti umdify untuk menjana kod tersebut. Tetapi dengan modul ES dibina dalam kita boleh melangkau langkah binaan dan mempunyai saiz berkas yang lebih kecil.
Modul ES adalah statik, bermakna alat boleh menganalisis struktur kod pada masa penyusunan untuk menentukan kod yang sedang digunakan dan yang tidak. Ini membolehkan pokok digoncang, di mana kod yang tidak digunakan dialih keluar daripada berkas terakhir.
Oleh kerana modul CommonJS dan AMD adalah dinamik (dinilai pada masa jalan), gegaran pokok adalah kurang berkesan dengan sistem ini, selalunya menghasilkan berkas yang lebih besar.
Apabila mengimport modul dengan CommonJS, menentukan sambungan fail adalah pilihan.
const math = require("./math"); function subtract(a,b) { return math.add(a,-b); } module.exports = { subtract: subtract }
Tetapi apakah maksud matematik sebenarnya? Adakah ia fail JavaScript? Fail JSON? Fail index.js di dalam direktori matematik?
Apabila menggunakan alat analisis statik seperti ES Lint, skrip taip atau lebih cantik setiap keperluan menjadi permainan meneka.
adakah ia math.js?
adakah ia math.jsx?
adakah ia math.cjs?
adakah ia math.mjs?
adakah ia matematik.ts?
adakah ia matematik.tsx?
adakah ia matematik.mts?
adakah ia matematik.cts?
adakah ia matematik/index.js?
adakah ia matematik/index.jsx?
Anda mendapat idea itu.
Membaca fail adalah mahal. Ia adalah jauh kurang berprestasi daripada membaca dari ingatan. Mengimport math/index.js menghasilkan 9 operasi IO dan bukannya 1! Dan permainan meneka ini memperlahankan alatan kami dan menjejaskan pengalaman pembangun.
Dalam modul ES kami mengelakkan kekacauan ini dengan mewajibkan sambungan fail.
Tidak seperti CommonJS, yang memuatkan modul secara serentak (menyekat keseluruhan proses sehingga modul dimuatkan), modul ES tidak segerak. Ini membolehkan JavaScript untuk terus melaksanakan semasa modul dimuatkan di latar belakang, meningkatkan prestasi — terutamanya dalam persekitaran seperti Node.js.
Walaupun terdapat faedah yang jelas, penggunaan modul ES bukanlah tugas yang mudah. Inilah sebab peralihan mengambil masa yang lama:
Bertukar daripada modul CommonJS kepada ES bukanlah perubahan yang remeh, terutamanya untuk projek besar. Perbezaan sintaks, digabungkan dengan keperluan untuk sokongan perkakas, menjadikan penghijrahan sebagai usaha yang ketara.
Node.js mengambil masa 5 tahun untuk menyokong sepenuhnya modul ES. Pada masa ini, pembangun perlu mengekalkan keserasian dengan kedua-dua CommonJS (pada pelayan) dan modul ES (pada penyemak imbas). Sokongan dwi ini mencipta banyak geseran dalam ekosistem.
Walaupun selepas Node.js menambah sokongan untuk modul ES, modul CommonJS tidak dapat memuatkan modul ES. Walaupun modul ES boleh memuatkan modul CommonJS, kedua-dua sistem tidak boleh beroperasi sepenuhnya, mewujudkan pening kepala tambahan untuk pengarang pakej yang terpaksa menyokong kedua-dua sistem.
Masa depan modul JavaScript adalah cerah, dan berikut adalah beberapa perkembangan penting yang akan menjadikan modul ES sistem dominan yang bergerak ke hadapan:
Dalam Node.js 23 akhirnya kami mempunyai keupayaan untuk memuatkan modul ES daripada CommonJS.
Terdapat kaveat kecil: Modul ES yang menggunakan await peringkat atas tidak boleh diimport ke CommonJS, kerana await hanya boleh digunakan dalam fungsi tak segerak dan CommonJS adalah segerak.
Pendaftaran pakej javascript baharu yang bersaing dengan npm. Ia mempunyai banyak kelebihan berbanding npm yang saya tidak akan pergi ke sini. Tetapi perkara yang menarik ialah anda hanya dibenarkan memuat naik pakej modul ES. Tidak perlu menyokong piawaian lama.
Perjalanan daripada penggodaman skop global kepada modul ES moden telah mengubah cara kami menstruktur JavaScript. Selepas bertahun-tahun bereksperimen dengan CommonJS, AMD dan UMD, modul ES telah muncul sebagai standard yang jelas, menawarkan sintaks yang lebih mudah, pengoptimuman yang lebih baik dan prestasi yang lebih baik.
Walaupun berhijrah ke modul ES memang mencabar, terutamanya dengan sokongan Node.js dan keserasian ekosistem, faedahnya tidak dapat dinafikan. Dengan Node.js 23 meningkatkan kesalingoperasian dan alatan baharu seperti JSR yang mempromosikan sistem modul bersatu, modul ES ditetapkan untuk menjadi lalai untuk JavaScript.
Sambil kami terus menerima modul ES, kami boleh mengharapkan kod yang lebih bersih, lebih pantas dan lebih boleh diselenggara, menandakan era baharu modulariti dalam pembangunan JavaScript.
Atas ialah kandungan terperinci Sejarah ringkas modul ES. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!