Dalam sebuah proyek yang saya kolaborasi, kami memiliki dua pilihan sistem modul mana yang dapat kami gunakan:
- Mengimpor modul menggunakan
require
, dan mengekspor menggunakanmodule.exports
danexports.foo
. - Mengimpor modul menggunakan ES6
import
, dan mengekspor menggunakan ES6export
Apakah ada manfaat kinerja untuk menggunakan salah satunya? Apakah ada hal lain yang harus kita ketahui jika kita menggunakan modul ES6 di atas yang Node?
javascript
node.js
ecmascript-6
babeljs
kpimov
sumber
sumber
node --experimental-modules index.mjs
memungkinkan Anda menggunakanimport
tanpa Babel dan berfungsi di Node 8.5.0+. Anda dapat (dan harus) juga mempublikasikan paket npm Anda sebagai ESModule asli , dengan kompatibilitas ke belakang untukrequire
cara lama .Jawaban:
Perlu diingat bahwa belum ada mesin JavaScript yang secara bawaan mendukung modul ES6. Anda mengatakan sendiri bahwa Anda menggunakan Babel. Konversi Babel
import
danexport
deklarasi ke CommonJS (require
/module.exports
) secara default. Jadi, bahkan jika Anda menggunakan sintaks modul ES6, Anda akan menggunakan CommonJS di bawah tenda jika Anda menjalankan kode di Node.Ada perbedaan teknis antara modul CommonJS dan ES6, mis. CommonJS memungkinkan Anda memuat modul secara dinamis. ES6 tidak mengizinkan ini, tetapi ada API dalam pengembangan untuk itu .
Karena modul ES6 adalah bagian dari standar, saya akan menggunakannya.
sumber
ES6 import
denganrequire
tetapi mereka bekerja secara berbeda. CommonJS mengekspor kelas itu sendiri sementara hanya ada satu kelas. Ekspor ES6 seperti ada beberapa kelas sehingga Anda harus menggunakan.ClassName
untuk mendapatkan kelas yang diekspor. Apakah ada perbedaan lain yang sebenarnya mempengaruhi implementasimodule.exports = ...;
setara denganexport default ...
.exports.foo = ...
setara denganexport var foo = ...
;import
mentranspilasikan ke CommonJS di Node, yang digunakan bersama Webpack 2 / Rollup (dan bundler lain yang memungkinkan ES6 tree gemetar), dimungkinkan untuk menyelesaikan dengan file yang jauh lebih kecil daripada kode setara Node crunches melalui penggunaanrequire
tepat karena fakta ES6 memungkinkan analisis statis impor / ekspor. Meskipun ini tidak akan membuat perbedaan untuk Node (belum), tentu bisa jika kode akhirnya akan berakhir sebagai satu bundel browser.Ada beberapa penggunaan / kemampuan yang mungkin ingin Anda pertimbangkan:
Memerlukan:
require
s, mereka dimuat dan diproses satu per satu.Impor ES6:
Juga, sistem modul Require tidak berbasis standar. Sangat tidak mungkin menjadi standar sekarang karena modul ES6 ada. Di masa depan akan ada dukungan asli untuk Modul ES6 dalam berbagai implementasi yang akan menguntungkan dalam hal kinerja.
sumber
require
, jadi Anda tetap menggunakan sistem modul dan loader Node.Keuntungan utama adalah sintaksis:
Anda tidak mungkin melihat manfaat kinerja dengan modul ES6. Anda masih membutuhkan pustaka tambahan untuk menggabungkan modul-modul, bahkan ketika ada dukungan penuh untuk fitur ES6 di browser.
sumber
node --experimemntal-modules index.mjs
Anda dapat menggunakannyaimport
tanpa Babel. Anda dapat (dan harus) juga mempublikasikan paket npm Anda sebagai ESModule asli, dengan kompatibilitas ke belakang untukrequire
cara lama . Banyak browser juga mendukung impor dinamis secara asli.Jawaban saat ini adalah tidak, karena tidak ada mesin browser saat ini yang mengimplementasikan
import/export
dari standar ES6.Beberapa grafik perbandingan http://kangax.github.io/compat-table/es6/ tidak memperhitungkan ini, jadi ketika Anda melihat hampir semua hijau untuk Chrome, berhati-hatilah.
import
kata kunci dari ES6 belum diperhitungkan.Dengan kata lain, mesin browser saat ini termasuk V8 tidak dapat mengimpor file JavaScript baru dari file JavaScript utama melalui arahan JavaScript apa pun.
(Kami mungkin masih beberapa bug saja atau beberapa tahun lagi hingga V8 mengimplementasikannya sesuai dengan spesifikasi ES6.)
Dokumen ini adalah yang kita butuhkan, dan dokumen ini ini yang harus kita patuhi.
Dan standar ES6 mengatakan bahwa dependensi modul harus ada sebelum kita membaca modul seperti dalam bahasa pemrograman C, di mana kita memiliki
.h
file (header) .Ini adalah struktur yang baik dan teruji, dan saya yakin para ahli yang menciptakan standar ES6 memikirkan hal itu.
Inilah yang memungkinkan Webpack atau paket bundler lain untuk mengoptimalkan bundel dalam beberapa kasus khusus , dan mengurangi beberapa dependensi dari bundel yang tidak diperlukan. Tetapi dalam kasus kita memiliki dependensi sempurna ini tidak akan pernah terjadi.
Dibutuhkan waktu hingga
import/export
dukungan asli ditayangkan, danrequire
kata kunci tidak akan pergi ke mana pun untuk waktu yang lama.Apa
require
?Ini adalah
node.js
cara memuat modul. ( https://github.com/nodejs/node )Node menggunakan metode tingkat sistem untuk membaca file. Anda pada dasarnya mengandalkan itu ketika menggunakan
require
.require
akan berakhir pada beberapa panggilan sistem sepertiuv_fs_open
(tergantung pada sistem akhir, Linux, Mac, Windows) untuk memuat file / modul JavaScript.Untuk memeriksa apakah ini benar, coba gunakan Babel.js, dan Anda akan melihat bahwa
import
kata kunci akan dikonversi menjadirequire
.sumber
import
dalam proses membangun Webpack 2 / Rollup berpotensi mengurangi ukuran file yang dihasilkan oleh 'pohon gemetar' modul / kode yang tidak digunakan, yang mungkin berakhir di bundel akhir. Ukuran file yang lebih kecil = lebih cepat untuk mengunduh = lebih cepat untuk init / dieksekusi pada klien.import
kata kunci secara asli. Atau ini berarti Anda tidak dapat mengimpor file JavaScript lain dari file JavaScript. Inilah sebabnya mengapa Anda tidak dapat membandingkan manfaat kinerja keduanya. Tapi tentu saja, alat seperti Webpack1 / 2 atau Browserify dapat menangani kompresi. Mereka leher ke leher: gist.github.com/substack/68f8d502be42d5cd4942import
danexport
merupakan deklarasi statis yang mengimpor jalur kode tertentu, sedangkanrequire
bisa dinamis dan dengan demikian bundel dalam kode yang tidak digunakan. Manfaat kinerja tidak langsung - Webpack 2 dan / atau Rollup berpotensi menghasilkan ukuran bundel yang lebih kecil yang lebih cepat untuk diunduh, dan karenanya terlihat lebih tajam untuk pengguna akhir (peramban). Ini hanya berfungsi jika semua kode ditulis dalam modul ES6 dan karenanya impor dapat dianalisis secara statis.import/export
dikonversi menjadirequire
, diberikan. Tetapi apa yang terjadi sebelum langkah ini dapat dianggap sebagai peningkatan "kinerja". Contoh: Jikalodash
ditulis dalam ES6 dan Andaimport { omit } from lodash
, bundel utama HANYA akan berisi 'hilangkan' dan bukan utilitas lain, sedangkan yang sederhanarequire('lodash')
akan mengimpor semuanya. Ini akan meningkatkan ukuran bundel, membutuhkan waktu lebih lama untuk mengunduh, dan karenanya menurunkan kinerja. Ini hanya berlaku dalam konteks browser, tentu saja.Menggunakan modul ES6 dapat berguna untuk 'pengocokan pohon'; yaitu mengaktifkan Webpack 2, Rollup (atau bundler lain) untuk mengidentifikasi jalur kode yang tidak digunakan / diimpor, dan karenanya tidak membuatnya menjadi bundel yang dihasilkan. Ini secara signifikan dapat mengurangi ukuran file dengan menghilangkan kode yang tidak pernah Anda perlukan, tetapi dengan CommonJS dibundel secara default karena Webpack dkk tidak memiliki cara untuk mengetahui apakah itu diperlukan.
Ini dilakukan dengan menggunakan analisis statis dari jalur kode.
Misalnya, menggunakan:
... memberikan bundler petunjuk yang
package.anotherPart
tidak diperlukan (jika tidak diimpor, itu tidak dapat digunakan-kan?), sehingga tidak akan mengganggu bundling itu.Untuk mengaktifkan ini untuk Webpack 2, Anda perlu memastikan bahwa transpiler Anda tidak mengeluarkan modul CommonJS. Jika Anda menggunakan
es2015
plug-in dengan babel, Anda dapat menonaktifkannya.babelrc
seperti:Rollup dan lainnya dapat bekerja secara berbeda - lihat dokumen jika Anda tertarik.
sumber
Ketika datang ke async atau mungkin pemuatan malas, maka
import ()
jauh lebih kuat. Lihat ketika kita membutuhkan komponen dengan cara asinkron, maka kita menggunakannyaimport
dalam beberapa cara async seperti padaconst
variabel yang menggunakanawait
.Atau jika Anda ingin menggunakannya
require()
,Masalahnya
import()
sebenarnya async di alam. Seperti yang disebutkan oleh neehar venugopal di ReactConf , Anda dapat menggunakannya untuk memuat komponen reaksi secara dinamis untuk arsitektur sisi klien.Juga jauh lebih baik dalam hal Routing. Itu adalah satu hal khusus yang membuat log jaringan mengunduh bagian yang diperlukan ketika pengguna terhubung ke situs web tertentu ke komponen spesifiknya. mis. halaman login sebelum dasbor tidak akan mengunduh semua komponen dasbor. Karena yang dibutuhkan saat ini yaitu komponen login, yang hanya akan diunduh.
Hal yang sama berlaku untuk
export
: ES6export
persis sama dengan untuk CommonJSmodule.exports
.CATATAN - Jika Anda mengembangkan proyek node.js, maka Anda harus benar-benar menggunakan
require()
sebagai simpul akan membuang kesalahan pengecualian seolah-invalid token 'import'
olah Anda akan menggunakanimport
. Jadi simpul tidak mendukung pernyataan impor.UPDATE - Seperti yang disarankan oleh Dan Dascalescu : Sejak v8.5.0 (dirilis September 2017),
node --experimental-modules index.mjs
Anda dapat menggunakannyaimport
tanpa Babel. Anda dapat (dan harus) juga mempublikasikan paket npm Anda sebagai ESModule asli, dengan kompatibilitas ke belakang untukrequire
cara lama .Lihat ini untuk izin lebih lanjut tempat menggunakan impor async - https://www.youtube.com/watch?v=bb6RCrDaxhw
sumber
Yang paling penting untuk diketahui adalah bahwa modul ES6 memang merupakan standar resmi, sedangkan modul CommonJS (Node.js) tidak.
Pada tahun 2019, modul ES6 didukung oleh 84% browser. Sementara Node.js menempatkannya di belakang flag --experimental-modules , ada juga paket simpul yang disebut esm , yang membuat integrasi menjadi mulus.
Masalah lain yang mungkin Anda temui antara sistem modul ini adalah lokasi kode. Node.js mengasumsikan sumber disimpan dalam
node_modules
direktori, sementara sebagian besar modul ES6 digunakan dalam struktur direktori datar. Ini tidak mudah untuk direkonsiliasi, tetapi dapat dilakukan dengan meretaspackage.json
file Anda dengan skrip instalasi sebelum dan sesudah. Berikut ini adalah contoh modul isomorfik dan artikel yang menjelaskan cara kerjanya.sumber
Saya pribadi menggunakan impor karena, kita dapat mengimpor metode yang diperlukan, anggota dengan menggunakan impor.
Nama File : dep.js
Penghargaan untuk Paul Shan. Info lebih lanjut .
sumber
require
cara lama ?const {a,b} = require('module.js');
berfungsi juga ... jika Anda mengekspora
danb
module.exports = { a: ()={}, b: 22 }
- Bagian kedua dari respan @BananaAcidSampai sekarang impor ES6, ekspor selalu dikompilasi ke CommonJS , sehingga tidak ada manfaat menggunakan satu atau yang lain. Meskipun penggunaan ES6 direkomendasikan karena itu harus menguntungkan ketika dukungan asli dari browser dirilis. Alasannya, Anda dapat mengimpor sebagian dari satu file sementara dengan CommonJS Anda harus meminta semua file.
ES6 →
import, export default, export
CommonJS →
require, module.exports, exports.foo
Di bawah ini adalah penggunaan umum dari mereka.
ES6 standar ekspor
ES6 ekspor banyak dan impor banyak
Module.exports CommonJS
CommonJS module.exports multiple
sumber
Tidak yakin mengapa (mungkin optimasi - pemuatan malas?) Apakah berfungsi seperti itu, tetapi saya perhatikan bahwa
import
mungkin tidak menguraikan kode jika modul yang diimpor tidak digunakan.Perilaku yang mungkin tidak diharapkan dalam beberapa kasus.
Ambil kelas Foo yang dibenci sebagai ketergantungan sampel kami.
untuk
Sebagai contoh:
index.ts
index.ts
index.ts
Di samping itu:
index.ts
sumber