informasi kontak saya
Surat[email protected]
2024-07-08
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Selain proses utama, kami juga akan menjelaskan beberapa konsep samar secara detail:
di depan Inisiasi, Pembuatan, Penyegelan"Dalam", kami telah memperkenalkan bahwa logika konstruksi yang mendasari Webpack secara kasar dapat dibagi menjadi: "Inisialisasi, konstruksi, pengemasan"tiga fase:
di dalam,"Membangun"Fase ini bertanggung jawab untuk menganalisis ketergantungan antar modul dan menetapkan Grafik ketergantungan(ModuleGraph); lalu, di "Enkapsulasi” tahap, berdasarkan grafik ketergantungan, modul dienkapsulasi secara terpisah ke dalam beberapa objek Chunk, dan hubungan ketergantungan induk-anak antara Chunk diurutkan ke dalam ChunkGraph dan beberapa objek ChunkGroup.
Tujuan terpenting dari fase "enkapsulasi" adalah membuat grafik hubungan ChunkGraph berdasarkan grafik hubungan ModuleGraph yang dikumpulkan dalam fase "pembangunan".
Mari kita analisa secara singkat logika implementasi dari beberapa langkah penting di sini.
Langkah pertama sangat penting: transferseal()
Setelah fungsinya, lintasientry
Konfigurasi, buat yang kosong untuk setiap entriChunk
DanTitik masuk objek (khususChunkGroup
), dan awalnya menyiapkan dasar ChunkGraph
Hubungan struktural, bersiap untuk langkah selanjutnya, kode kunci:
class Compilation {
seal(callback) {
// ...
const chunkGraphInit = new Map();
// 遍历入口模块列表
for (const [name, { dependencies, includeDependencies, options }] of this
.entries) {
// 为每一个 entry 创建对应的 Chunk 对象
const chunk = this.addChunk(name);
// 为每一个 entry 创建对应的 ChunkGroup 对象
const entrypoint = new Entrypoint(options);
// 关联 Chunk 与 ChunkGroup
connectChunkGroupAndChunk(entrypoint, chunk);
// 遍历 entry Dependency 列表
for (const dep of [...this.globalEntry.dependencies, ...dependencies]) {
// 为每一个 EntryPoint 关联入口依赖对象,以便下一步从入口依赖开始遍历其它模块
entrypoint.addOrigin(null, { name }, /** @type {any} */ (dep).request);
const module = this.moduleGraph.getModule(dep);
if (module) {
// 在 ChunkGraph 中记录入口模块与 Chunk 关系
chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
// ...
}
}
}
// 调用 buildChunkGraph 方法,开始构建 ChunkGraph
buildChunkGraph(this, chunkGraphInit);
// 触发各种优化钩子
// ...
}
}
Setelah eksekusi selesai maka terbentuklah struktur data sebagai berikut:
Kedua, jika dikonfigurasi saat ini entry.runtime
, Webpack juga akan memberikan kode runtime pada tahap ini membuat Potongan yang sesuai dan secara langsungmendistribusikan Memberientry
sesuaiChunkGroup
obyek.Dipanggil ketika semuanya sudah siapmembangunChunkGraph berfungsi, lanjutkan ke langkah berikutnya.
Langkah kedua: adabuildChunkGraph
dalam fungsitransfer visitModules
Fungsinya, jelajahi ModuleGraph dan tetapkan semua Modul ke modul yang berbeda sesuai dengan ketergantungannya.Chunk
Keberatan; jika ditemui selama proses inimodul asinkron, lalu modul membuatbaru ChunkGroup
DanChunk
Objek, pada akhirnya membentuk struktur data berikut:
langkah ketiga: adabuildChunkGraph
dalam fungsitransfer connectChunkGroups
metode, menetapkanChunkGroup
di antara,Chunk
ketergantungan antara satu sama lain untuk menghasilkan yang lengkapChunkGraph
Objek, pada akhirnya membentuk struktur data berikut:
langkah keempat: adabuildChunkGraph
dalam fungsitransfer cleanupUnconnectedGroups
Metode, pembersihan tidak validChunkGroup
, terutama berperan dalam pengoptimalan kinerja.
Setelah melalui empat langkah ini dari atas ke bawah,ModuleGraph
Modul yang disimpan di dalamnya akan ditetapkan ke tiga objek Chunk yang berbeda: Entry, Async, dan Runtime sesuai dengan sifat modul itu sendiri, dan ketergantungan antara Chunk akan disimpan di koleksi ChunkGraph dan ChunkGroup. Anda dapat melanjutkan berdasarkan objek ini Ubah kebijakan subkontrak (mis.SplitChunksPlugin
), mewujudkan optimalisasi subkontrak dengan mengatur ulang dan mengalokasikan kepemilikan objek Modul dan Potongan.
Proses konstruksi di atas melibatkan tiga objek utama: Chunk, ChunkGroup, dan ChunkGraph. Pertama, mari kita rangkum konsep dan fungsinya untuk memperdalam pemahaman kita:
Chunk
: Modul digunakan untuk membaca konten modul, mencatat ketergantungan antar modul, dll.; sementara Chunk menggabungkan beberapa Modul berdasarkan ketergantungan modul dan mengeluarkannya ke dalam file aset (logika penggabungan dan keluaran produk akan dijelaskan di bab berikutnya):ChunkGroup
:satu ChunkGroup
berisi satu atau lebihChunk
obyek;ChunkGroup
DanChunkGroup
Hubungan ketergantungan orangtua-anak terbentuk antara:ChunkGraph
: Terakhir, Webpack akan menyimpan dependensi antara Chunks dan ChunkGroup di dalamnya compilation.chunkGraph
Di dalam objek, tipe hubungan berikut terbentuk:Di atas ChunkGraph
Proses pembangunan pada akhirnya akan mengatur Modul menjadi tiga jenis Potongan yang berbeda:
entry
Modul yang dicapai dengan sentuhan bawah disusun menjadi sebuah Potongan;entry.runtime
Jika tidak kosong, modul runtime akan disusun menjadi sebuah Potongan.Ini sudah ada di dalam Webpack, jika tidak digunakan splitChunks
Dalam kasus plug-in lain, aturan default untuk memetakan input modul ke output adalah salah satu prinsip dasar utama Webpack, sehingga aturan spesifik dari setiap Chunk perlu diperkenalkan.
Potongan Entri:
Dimulai dengan Entry Chunk, Webpack akan melakukannya terlebih dahulu entry
membuatChunk
Objeknya, misalnya, konfigurasinya sebagai berikut:
module.exports = {
entry: {
main: "./src/main",
home: "./src/home",
}
};
Melintasi entry
properti objek dan buatchunk[main]
、chunk[home]
Dua objek, saat ini masing-masing berisi dua Potonganmain
、home
Modul:
Setelah inisialisasi selesai, Webpack akan melakukannya ModuleGraph
data ketergantungan, akanentry
Semua modul yang disentuh oleh yang berikut ini dimasukkan ke dalam Chunk (terjadi dikunjungiModul metode), misalnya, untuk dependensi file berikut:
main.js
Jika keempat file a/b/c/d direferensikan secara langsung atau tidak langsung secara sinkron, Webpack akan terlebih dahulumain.js
Modul ini membuat objek Chunk dan EntryPoint, lalu secara bertahap menambahkan modul a/b/c/d ke dalamnyachunk[main]
, akhirnya terbentuk:
Chunk Asinkron:
Kedua, Webpack akan mengkompilasi setiap pernyataan impor asinkron (import(xxx)
Danrequire.ensure
) diproses sebagai objek Chunk terpisah, dan semua submodulnya ditambahkan ke Chunk ini - kami menyebutnya Async Chunk. Misalnya saja untuk contoh berikut ini:
// index.js
import './sync-a.js'
import './sync-b.js'
import('./async-a.js')
// async-a.js
import './sync-c.js'
Dalam modul entri index.js
Dalam, sync-a dan sync-b diperkenalkan secara sinkron; modul async-a diperkenalkan secara asinkron; pada saat yang sama, dalam async-a, modul async-a diperkenalkan secara sinkron.sync-c
modul, membentuk diagram ketergantungan modul berikut:
Pada titik ini, Webpack akan menjadi titik masuknya index.js
, modul asinkron async-a.js
Buat subpaket secara terpisah untuk membentuk struktur Potongan berikut:
Dan chunk[index]
Danchunk[async-a]
Ketergantungan satu arah terbentuk di antara keduanya, dan Webpack akan menyimpan ketergantungan iniChunkGroup._parents
、ChunkGroup._children
di properti.
Potongan Waktu Proses:
Akhirnya, kecuali entry
, Selain modul asinkron, Webpack5 juga mendukung ekstraksi kode runtime secara terpisah ke dalam Potongan. Kode runtime yang disebutkan di sini mengacu pada serangkaian kode kerangka dasar yang dimasukkan oleh Webpack untuk memastikan bahwa produk yang dikemas dapat berjalan secara normal. Misalnya, struktur produk paket Webpack yang umum adalah sebagai berikut:
Bagian besar kode yang dilingkari kotak merah pada gambar di atas adalah kode runtime yang dihasilkan secara dinamis oleh Webpack. Saat kompilasi, Webpack akan memutuskan kode runtime mana yang akan dikeluarkan berdasarkan kode bisnis (berdasarkanDependency
subkelas), misalnya:
__webpack_require__.f
、__webpack_require__.r
dan fungsi lainnya untuk mencapai dukungan modular minimum;__webpack_require__.e
fungsi;__webpack_require__.o
fungsi;Meskipun setiap bagian kode runtime mungkin kecil, seiring bertambahnya fitur, hasil akhirnya akan menjadi lebih besar dan lebih besar. Khusus untuk aplikasi multi-entri, agak boros untuk berulang kali mengemas runtime serupa di setiap entri yang disediakan Webpack5 entry.runtime
Item konfigurasi digunakan untuk mendeklarasikan bagaimana kode runtime dikemas.Untuk pemakaiannya tinggal pakai sajaentry
Tambahkan formulir string ke itemruntime
nilai, misalnya:
module.exports = {
entry: {
index: { import: "./src/index", runtime: "solid-runtime" },
}
};
ada compilation.seal
Secara fungsinya, Webpack yang pertama adalahentry
membuatEntryPoint
, lalu menilai entry
Apakah konfigurasinya berisiruntime
properti, jika ada, buatlah denganruntime
Nilainya adalah nama Chunk. Oleh karena itu, contoh konfigurasi di atas akan menghasilkan dua Chunk:chunk[index.js]
、chunk[solid-runtime]
, dan berdasarkan ini, dua file akhirnya dihasilkan:
index.js
dokumen;solid-runtime.js
dokumen.dalam berbagai entry
Dalam skenarionya, hanya untuk semua orangentry
Semua diatur samaruntime
nilai, kode runtime Webpack akan digabungkan dan ditulis ke dalam Runtime Chunk yang sama, yang pada akhirnya mencapai pengoptimalan kinerja produk. Misalnya untuk konfigurasi berikut:
module.exports = {
entry: {
index: { import: "./src/index", runtime: "solid-runtime" },
home: { import: "./src/home", runtime: "solid-runtime" },
}
};
Pintu masuk index
、home
berbagi hal yang samaruntime
nilai, dan akhirnya menghasilkan tiga Potongan, masing-masing:
Pintu masuk saat ini chunk[index]
、chunk[home]
dengan waktu proseschunk[solid-runtime]
Hubungan ketergantungan orangtua-anak juga akan terbentuk.
Masalah terbesar dengan aturan sub-pengemasan default adalah bahwa ia tidak dapat menyelesaikan duplikasi modul. Jika beberapa Potongan berisi Modul yang sama pada saat yang sama, maka Modul ini akan berulang kali dikemas ke dalam Potongan ini tanpa batasan. Misalnya, kita mempunyai dua entri main/index yang keduanya bergantung pada modul yang sama:
Secara default, Webpack tidak akan melakukan pemrosesan tambahan dalam hal ini, tetapi hanya mengemas modul c ke dalam dua Chunk utama/indeks secara bersamaan, yang pada akhirnya membentuk:
dapat dilihat chunk
diisolasi satu sama lain, modul c dikemas berulang kali, yang dapat menyebabkan hilangnya kinerja yang tidak perlu pada produk akhir!
Untuk mengatasi masalah ini, Webpack 3 diperkenalkan CommonChunkPlugin
Plugin ini mencoba mengekstraksi ketergantungan umum antar entri menjadi terpisahchunk
,Tetapi CommonChunkPlugin
Ini pada dasarnya diimplementasikan berdasarkan rantai hubungan orangtua-anak yang sederhana antara Potongan. Sulit untuk menyimpulkan bahwa paket ketiga yang diekstraksi harus digunakan sebagaientry
ayahchunk
Masih anak-anakchunk
,CommonChunkPlugin
pemrosesan terpadu sebagai indukchunk
, dalam beberapa kasus hal ini mempunyai dampak negatif yang cukup besar terhadap kinerja.
Karena alasan ini, struktur data yang lebih kompleks diperkenalkan secara khusus setelah Webpack 4—— ChunkGroup
Mengkhususkan diri dalam mewujudkan manajemen rantai hubungan dan kerjasamaSplitChunksPlugin
dapat diimplementasikan dengan lebih efisien dan cerdasSubkontrak heuristik.
Singkatnya, fase "Bangun" bertanggung jawab untuk membangun ModuleGraph berdasarkan hubungan referensi modul; fase "Enkapsulasi" bertanggung jawab untuk membangun serangkaian objek Chunk berdasarkan ModuleGraph dan mengatur ketergantungan antar Chunk (referensi asinkron, waktu proses ) ke dalam ChunkGraph - objek grafik Ketergantungan Potongan. Mirip dengan ModuleGraph, pengenalan struktur ChunkGraph juga dapat memisahkan logika manajemen ketergantungan antar Chunk, menjadikan logika arsitektur keseluruhan lebih masuk akal dan lebih mudah untuk diperluas.
Namun, meskipun terlihat sangat rumit, tujuan terpenting dari tahap "pengemasan" tetap untuk menentukan berapa banyak Chunk yang ada dan Modul apa saja yang disertakan dalam setiap Chunk - inilah faktor kunci yang sangat mempengaruhi hasil akhir pengemasan.
Untuk poin ini, kita perlu memahami tiga aturan subkontrak bawaan Webpack5: Entry Chunk, Async Chunk, dan Runtime Chunk. Ini adalah logika subkontrak paling orisinal Plugin bongkahan terpisah) semuanya didasarkan pada ini, dengan bantuan buildChunkGraph
Berbagai kait yang dipicu kemudian memisahkan, menggabungkan, dan mengoptimalkan struktur Potongan lebih lanjut untuk mencapai efek subkontrak yang diperluas.
memikirkan Chunk
Apakah dan hanya satu file produk yang akan diproduksi? Mengapa?mini-css-extract-plugin
、file-loader
Bagaimana komponen jenis ini yang dapat menulis file tambahan diimplementasikan di bagian bawah?