Mengumpulkan bundel impian dengan Webpack

Aplikasi JS, situs dan sumber daya lainnya menjadi lebih kompleks dan alat membangun adalah realitas pengembangan web. Bundlers membantu mengemas, mengompilasi, dan mengatur perpustakaan. Salah satu alat open source yang kuat dan fleksibel yang dapat dikustomisasi sempurna untuk membangun aplikasi klien adalah Webpack.

Maxim Sosnov ( crazymax11 ) - Frontend Lead di N1.RU memperkenalkan Webpack ke beberapa proyek besar yang sebelumnya memiliki custom build sendiri, dan menyumbangkan beberapa proyek untuk itu. Maxim tahu cara membangun bundel impian dengan Webpack, melakukannya dengan cepat, dan mengonfigurasinya sehingga konfigurasi tetap bersih, terpelihara, dan modular.


Interpretasinya berbeda dari laporan - ini adalah versi proflink yang sangat ditingkatkan. Sepanjang transkrip, telur Paskah tersebar di artikel, plugin, minifiers, opsi, transpiler dan bukti dari kata-kata pembicara, tautan yang tidak dapat dimasukkan ke dalam pidato. Jika Anda mengumpulkan semuanya, maka level bonus di Webpack terbuka :-)

Integrasi webpack dalam proyek tipikal


Biasanya, prosedur implementasi adalah sebagai berikut: pengembang di suatu tempat membaca artikel tentang Webpack, memutuskan untuk menghubungkannya, mulai membangunnya, entah bagaimana itu berfungsi, semuanya dimulai, dan untuk beberapa waktu webpack-config berfungsi - selama enam bulan, satu tahun, dua. Secara lokal, semuanya baik-baik saja - matahari, pelangi dan kupu-kupu. Dan kemudian pengguna nyata datang:

- Dari perangkat seluler, situs Anda tidak memuat.
- Semuanya bekerja untuk kita. Secara lokal, semuanya baik-baik saja!

Untuk berjaga-jaga, pengembang pergi ke profil segalanya dan melihat bahwa untuk perangkat seluler bundel memiliki berat 7 MB dan membutuhkan waktu 30 detik untuk memuat . Ini tidak cocok untuk siapa pun dan pengembang mulai mencari cara mengatasi masalah - ia dapat menghubungkan loader atau menemukan plug-in ajaib yang akan menyelesaikan semua masalah. Ajaibnya, plugin semacam itu berada. Pengembang kami pergi ke konfigurasi webpack, mencoba menginstal, tetapi baris kode mengganggu:

if (process.env.NODE_ENV === 'production') { config.module.rules[7].options.magic = true; } 

Baris diterjemahkan sebagai berikut: "Jika config sedang dirakit untuk produksi, maka ambil aturan ketujuh dan taruh opsi magic = true sana." Pengembang tidak tahu apa yang harus dilakukan dengan ini dan bagaimana menyelesaikannya. Ini adalah situasi di mana Anda membutuhkan seikat mimpi.

Bagaimana cara mengumpulkan seikat mimpi?


Pertama, mari kita tentukan apa itu. Pertama-tama, bundel mimpi memiliki dua karakteristik utama:

  • Beratnya sedikit . Semakin sedikit berat - semakin cepat pengguna akan mendapatkan aplikasi yang berfungsi. Anda tidak ingin situs Anda terbuka selama 15 detik.
  • Pengguna hanya mengunduh apa yang perlu diunduh untuk menampilkan halaman situs saat ini, dan tidak lebih dari satu byte!

Dan untuk mengurangi ukuran bundel, Anda harus terlebih dahulu mengevaluasi ukurannya.

Nilai ukuran bundel


Solusi paling populer adalah plugin WebpackBundleAnalyzer . Itu mengumpulkan statistik membangun aplikasi dan membuat halaman interaktif di mana Anda dapat melihat lokasi dan berat masing-masing modul.

gambar

Jika ini tidak cukup, Anda bisa membuat grafik ketergantungan menggunakan plugin lain .

gambar

Atau diagram lingkaran .

gambar

Jika ini tidak cukup, dan Anda ingin menjual Webpack ke pemasar, maka Anda dapat membangun seluruh alam semesta di mana setiap titik adalah modul, seperti bintang di Semesta.

gambar

Ada banyak alat yang mengevaluasi ukuran bundel dan memonitornya. Ada opsi dalam konfigurasi Webpack yang crash perakitan jika bundel terlalu berat, misalnya. Ada plugin duplikat-paket-pemeriksa-webpack-plugin yang akan mencegah Anda membangun bundel jika Anda memiliki paket 2 npm dari versi yang berbeda, misalnya, Lodash 4.15 dan Lodash 4.14.

Cara mengurangi bundel


  • Yang paling jelas adalah menyambungkan UglifyJS sehingga itu meminimalkan JavaScript.
  • Gunakan loader dan plugin khusus yang mengkompres dan mengoptimalkan sumber daya tertentu. Misalnya, css-nano untuk css, atau SVGO , yang mengoptimalkan SVG.
  • Kompres semua file secara langsung ke Webpack melalui plugins gzip / brotli .
  • Alat lainnya.

Sekarang kita akan mengerti cara membuang kelebihan dari bundel.

Buang kelebihannya


Pertimbangkan ini dalam contoh populer dengan moment.js : import moment from 'moment' . Jika Anda mengambil aplikasi kosong, impor moment.js dan ReactDOM ke dalamnya, dan kemudian kirimkan melalui WebpackBundleAnalyzer , Anda akan melihat gambar berikut.

gambar

Ternyata ketika Anda menambahkan satu hari, satu jam ke tanggal, atau hanya ingin meletakkan tautan "dalam 15 menit" menggunakan moment.js, Anda menghubungkan kode 230 Kbytes ! Mengapa ini terjadi dan bagaimana cara menyelesaikannya?

Pemuatan lokal saat ini


Ada fungsi di moment.js yang mengatur lokal:

 function setLocale(locale) { const localePath = 'locale/' + locale + '.js'; this._currentLocale = require(localePath); } 

Dapat dilihat dari kode bahwa lokal dimuat di sepanjang jalur dinamis, yaitu dihitung dalam runtime. Webpack bertindak dengan cerdas dan mencoba memastikan bahwa bundel Anda tidak macet selama eksekusi kode: ia menemukan semua kemungkinan lokal dalam proyek, dan bundel mereka. Oleh karena itu, aplikasi ini sangat berat.

gambar

Solusinya sangat sederhana - kami mengambil plugin standar dari Webpack dan mengatakan kepadanya: "Jika Anda melihat seseorang ingin mengunduh banyak lokal, karena mereka tidak dapat menentukan yang mana, ambil saja yang Rusia!"

gambar

Webpack hanya akan mengambil bahasa Rusia, dan WebpackBundleAnalyzer akan menampilkan 54 Kb, yang sudah 200 Kb lebih mudah.

Penghapusan kode mati


Optimasi berikutnya yang menarik bagi kami adalah penghapusan kode mati . Pertimbangkan kode berikut.

 const cond = true; if (!cond) { return false; } return true; someFunction(42); 

Sebagian besar baris dari kode ini tidak diperlukan dalam bundel akhir - blok dengan kondisi tidak akan dieksekusi, fungsi setelah kembali juga. Yang perlu Anda tinggalkan adalah return true . Inilah yang dimaksud dengan penghapusan kode Mati: alat build mendeteksi kode yang tidak dapat dieksekusi dan memotongnya. Ada fitur bagus yang dapat dilakukan UglifyJS ini.

Sekarang mari kita beralih ke penghapusan kode Mati yang lebih maju - Metode pengocokan pohon .

Pohon bergetar


Katakanlah kita memiliki aplikasi yang menggunakan Lodash . Saya sangat meragukan bahwa ada orang yang menggunakan seluruh Lodash. Kemungkinan besar, beberapa fungsi seperti get , IsEmpty, unionBy, atau sejenisnya dieksploitasi .

Ketika kita melakukan Tree gemetar, kita ingin Webpack untuk "mengguncang" modul yang tidak perlu dan membuangnya, dan kita hanya memiliki yang diperlukan. Ini Pohon bergetar.

Bagaimana Tree shaking bekerja di Webpack


Katakanlah Anda memiliki kode seperti ini:

 import { a } from './a.js'; console.log(a); 

Kode ini sangat sederhana: dari beberapa modul, impor variabel a dan output. Tetapi ada dua variabel dalam modul ini: a dan b . Kami tidak membutuhkan variabel b , dan kami ingin menghapusnya.

 export const a = 3 export const b = 4 

Ketika Webpack tiba, itu mengonversi kode impor menjadi ini:

 var d = require(0); console.log(d["a"]); 

import kami berubah menjadi require , tetapi console.log belum berubah.

Ketergantungan Webpack dikonversi ke kode berikut:

 var a = 3; module.exports["a«] = a; /* unused harmony export b */ var b = 4; 


Webpack meninggalkan ekspor variabel a , dan menghapus ekspor variabel b , tetapi meninggalkan variabel itu sendiri, menandainya dengan komentar khusus. Dalam kode yang dikonversi, variabel b tidak digunakan, dan UglifyJS dapat menghapusnya.

Goyang pohon webpack hanya berfungsi jika Anda memiliki semacam minifier kode, seperti UglifyJS atau babel-minify .

Mari kita pertimbangkan kasus-kasus yang lebih menarik - ketika Tree shaking tidak berfungsi.

Ketika Pohon Goyang Tidak Berfungsi


Kasus No. 1. Anda menulis kode:

 module.exports.a = 3; module.exports.b = 4; 

Jalankan kode melalui Webpack, dan tetap sama. Itu karena bundler mengatur Tree goyang hanya jika Anda menggunakan modul ES6. Jika Anda menggunakan modul CommonJS, maka Tree shaking tidak akan berfungsi.

Kasus No. 2. Anda menulis kode dengan modul ES6 dan bernama ekspor.

 export const a = 3 export const b = 4 

Jika kode Anda berjalan melalui Babel dan Anda tidak mengatur opsi modul ke false , maka Babel akan membawa modul Anda ke CommonJS, dan Webpack sekali lagi tidak dapat mengeksekusi Tree shaking, karena hanya bekerja dengan modul ES6.

 module.exports.a = 3; module.exports.b = 4; 

Karenanya, kita perlu memastikan bahwa tidak ada seorang pun dalam rencana perakitan kita yang akan mentranskripsi modul ES6.

Kasus No. 3. Misalkan kita memiliki kelas yang tidak berguna yang tidak melakukan apa-apa: export class ShakeMe {} . Apalagi kami masih belum menggunakannya. Ketika Webpack melewati impor dan ekspor, Babel akan mengubah kelas menjadi suatu fungsi, dan bundler akan mencatat bahwa fungsi tersebut tidak digunakan:

 /* unused harmony e[port b */ var ShakeMe = function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Tampaknya semuanya harus baik-baik saja, tetapi jika kita melihat lebih dekat, kita akan melihat bahwa di dalam fungsi ini ada variabel global babelHelpers , dari mana beberapa fungsi dipanggil. Ini adalah efek samping : UglifyJS melihat bahwa beberapa fungsi global sedang dipanggil dan tidak akan memotong kode, karena takut sesuatu akan rusak.

Ketika Anda menulis kelas dan menjalankannya melalui Babel, mereka tidak pernah terpotong. Bagaimana ini diperbaiki? Ada peretasan standar - tambahkan komentar /*#__PURE__*/ sebelum fungsi:

 /* unused harmony export b */ var ShakeMe = /*#__PURE__*/ function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }(); 

Kemudian UglifyJS akan percaya pada kata bahwa fungsi selanjutnya adalah murni. Untungnya, Babel 7 melakukan ini sekarang, dan dalam Babel 6, sejauh ini tidak ada yang dihapus.

Aturan: jika Anda memiliki efek samping di suatu tempat, maka UglifyJS tidak akan melakukan apa pun.

Untuk meringkas:

  • Mengguncang pohon tidak berfungsi untuk sebagian besar perpustakaan dari npm , karena mereka semua dari CommonJS dan dibangun oleh Babel lama.
  • Kemungkinan besar, Tree shaking akan berfungsi secara memadai untuk pustaka yang sudah disiapkan untuk ini , misalnya, Lodash-es, Date-fns dan kode atau pustaka Anda.
  • UglifyJS terlibat dalam perakitan.
  • Modul ES6 yang digunakan.
  • Tidak ada efek samping.

Kami menemukan cara untuk mengurangi berat bundel, dan sekarang mari kita ajarkan untuk memuat hanya fungsionalitas yang diperlukan.

Kami hanya memuat fungsionalitas yang diperlukan


Kami membagi bagian ini menjadi dua. Pada bagian pertama, hanya kode yang diperlukan pengguna dimuat : jika pengguna mengunjungi halaman utama situs Anda, ia tidak memuat halaman akun pribadi. Dalam yang kedua, perubahan kode menyebabkan reload sumber daya sekecil mungkin .

Kami hanya memuat kode yang diperlukan


Pertimbangkan struktur aplikasi imajiner. Itu memiliki:

  • Titik masuk - APP.
  • Tiga halaman: rumah, pencarian dan kartu.

gambar

Masalah pertama yang ingin kita pecahkan adalah mengeluarkan kode umum . Mari kita menunjukkan kode merah sebagai kode umum untuk semua halaman, lingkaran hijau untuk halaman utama dan halaman pencarian. Sisa angka tidak terlalu penting.

gambar

Ketika pengguna datang ke pencarian dari halaman utama, ia akan memuat ulang kotak dan lingkaran untuk kedua kalinya, meskipun ia sudah memilikinya. Idealnya, kami ingin melihat sesuatu seperti ini.

gambar

Ada baiknya bahwa Webpack 4 sudah memiliki plugin bawaan yang melakukan ini untuk kita - SplitChunksPlugin . Plugin mengeluarkan kode aplikasi atau modul modul simpul, yang digunakan oleh beberapa chunks dalam chunk yang terpisah, sambil memastikan bahwa chunk dengan kode yang umum akan lebih dari 30 Kb, dan untuk memuat halaman yang Anda perlu unduh tidak lebih dari 5 chunks. Strateginya optimal: memuat potongan terlalu kecil tidak menguntungkan, dan memuat terlalu banyak potongan panjang dan tidak seefisien mengunduh lebih sedikit potongan bahkan di http2. Untuk mengulangi perilaku ini pada 2 atau 3 versi Webpack, saya harus menulis 20-30 baris dengan fitur tidak berdokumen. Sekarang ini sedang diselesaikan dalam satu baris.

CSS Takeaway


Alangkah baiknya jika kita masih mengeluarkan CSS untuk setiap chunk di file terpisah. Ada solusi siap pakai untuk ini - Mini-Css-Extract-Plugin . Plugin hanya muncul di Webpack 4, dan sebelum itu tidak ada solusi yang memadai untuk tugas seperti itu - hanya peretasan, rasa sakit, dan tembakan kaki. Plugin menghapus CSS dari potongan asinkron dan dibuat khusus untuk tugas ini , yang berfungsi sempurna.

Muat ulang sumber daya seminimal mungkin


Kami akan mencari cara untuk memastikan bahwa saat merilis, misalnya, blok promo baru di halaman utama, pengguna akan memuat ulang bagian terkecil dari kode .

Jika kami memiliki versi, semuanya akan baik-baik saja. Di sini kita memiliki halaman utama versi N, dan setelah rilis blok promo - versi N + 1. Webpack menyediakan mekanisme serupa langsung dari kotak menggunakan hashing. Setelah Webpack mengumpulkan semua aset, dalam hal ini app.js, ia akan menghitung hash kontennya dan menambahkannya ke nama file untuk mendapatkan aplikasi. [Hash] .js. Ini adalah versi yang kita butuhkan.

gambar

Mari kita periksa cara kerjanya. Nyalakan hash, buat perubahan pada halaman utama, dan lihat apakah kode halaman utama benar-benar telah berubah. Kita akan melihat bahwa dua file telah berubah: main dan app.js.

gambar

Mengapa ini terjadi, karena itu tidak logis? Untuk memahami alasannya, mari kita lihat app.js. Ini terdiri dari tiga bagian:

  • kode aplikasi
  • runtime webpack;
  • tautan ke bongkahan asinkron.

Ketika kami mengubah kode di main, isinya dan hash berubah, yang berarti bahwa tautannya juga berubah di app. Aplikasi itu sendiri juga akan berubah dan harus di-boot ulang. Solusi untuk masalah ini adalah dengan membagi app.js menjadi dua potongan: kode aplikasi dan runtime webpack dan tautan ke potongan asinkron. Webpack 4 melakukan segalanya untuk kami dengan satu opsi runtimeChunk , yang beratnya sangat kecil - kurang dari 2 KB di gzip. Mem-boot ulang untuk pengguna praktis tidak ada artinya. RuntimeChunk diaktifkan hanya dengan satu opsi:

 optimization: { runtimeChunk: true } 

Di Webpack 3 dan 2, kami akan menulis 5-6 baris, bukan satu. Ini tidak lebih, tetapi masih merupakan ketidaknyamanan yang tidak perlu.

gambar

Semuanya bagus, kami belajar membuat tautan dan runtime! Mari kita menulis modul baru di main, lepaskan, dan - op! - Sekarang, secara umum, semuanya restart.

gambar

Kenapa begitu Mari kita lihat bagaimana modul bekerja di webpack.

Modul Webpack


Misalkan ada kode di mana Anda menambahkan modul a , b , d, dan e :

 import a from 'a'; import b from 'b'; import d from 'd'; import e from 'e'; 

Webpack mengonversi impor menjadi mengharuskan: a , b , d, dan e diganti dengan mengharuskan (0), mengharuskan (1), membutuhkan (2), dan membutuhkan (3).

 var a = require(0); var b = require(1); var d = require(2); var e = require(3); 

Bayangkan sebuah gambar yang sangat sering terjadi: Anda menulis modul baru c import c from 'c'; dan rekatkan di suatu tempat di tengah:

 import a from 'a'; import b from 'b'; import c from 'c'; import d from 'd'; import e from 'e'; 

Ketika Webpack memproses semuanya, itu mengubah impor modul baru menjadi memerlukan (2):

 var a = require(0); var b = require(1); var c = require(2); var d = require(3); var e = require(4); 

Modul d dan e , yang 2 dan 3, akan menerima angka 3 dan 4 - id baru. Kesimpulan sederhana berikut dari ini: menggunakan nomor seri karena id agak konyol, tetapi Webpack melakukannya.

Jangan gunakan nomor seri sebagai id unik

Untuk memperbaiki masalah, ada solusi Webpack bawaan - HashedModuleIdsPlugin :

 new webpack.HashedModuleIdsPlugin({ hashFunction: 'md4′, hashDigest:'base64′, hashDigestLength: 4, }), 

Plugin ini menggunakan 4 karakter hash md4 bukan id digital dari path absolut ke file. Dengan itu, kebutuhan kami akan berubah menjadi ini:

 var a = require('YmRl'); var b = require('N2Fl'); var c = require('OWE4′); var d = require('NWQz'); var e = require('YWVj'); 

Alih-alih angka, surat muncul. Tentu saja, ada masalah tersembunyi - ini adalah tabrakan hash . Kami menemukan sekali dan dapat menyarankan Anda untuk menggunakan 8 karakter, bukan 4. Setelah mengkonfigurasi hash dengan benar, semuanya akan bekerja seperti yang kami inginkan.

Kita sekarang tahu bagaimana cara mengumpulkan kumpulan mimpi.

  • Minify .
  • Gunakan pemisahan kode .
  • Siapkan hash .

Kami belajar mengumpulkan, dan sekarang kami akan bekerja dengan kecepatan.

Bagaimana cara merakit bundel impian dengan cepat ?


Di N1.RU kami, aplikasi terbesar terdiri dari 10.000 modul, dan tanpa optimasi, dibutuhkan 28 menit. Kami dapat mempercepat perakitan menjadi dua menit! Bagaimana kami melakukannya? Ada 3 cara untuk mempercepat perhitungan apa pun, dan ketiganya berlaku untuk Webpack.

Paralelisasi Majelis


Hal pertama yang kami lakukan adalah memparalelkan majelis . Untuk ini kami memiliki:

  • HappyPackPlugin , yang membungkus pemuat Anda dengan pemuat lainnya, dan mengambil semua perhitungan yang terbungkus dalam proses terpisah. Ini memungkinkan, misalnya, memparalelkan Babel dan node-sass.
  • thread-loader . Melakukan kira-kira sama dengan HappyPackPlugin, hanya menggunakan bukan proses, tetapi kumpulan thread. Beralih ke utas terpisah adalah operasi yang mahal, gunakan dengan hati-hati, dan hanya jika Anda ingin membungkus operasi yang intensif sumber daya dan berat, seperti babel atau node-sass. Untuk memuat json, misalnya, paralelisasi tidak diperlukan, karena memuat cepat.
  • Plugin dan pemuat yang Anda gunakan kemungkinan besar sudah memiliki alat paralelisasi bawaan - Anda hanya perlu melihatnya. Misalnya, opsi ini di UglifyJS .

Caching membangun hasil


Caching hasil perakitan adalah cara paling efisien untuk mempercepat perakitan Webpack.

Solusi pertama yang kami miliki adalah cache-loader . Ini adalah loader yang masuk ke rantai pemuat dan menyimpan ke sistem file hasil dari membangun file tertentu untuk rantai pemuat tertentu. Pada perakitan bundel berikutnya, jika file ini ada di sistem file dan telah diproses dengan rantai ini, cache-loader akan mengambil hasilnya dan tidak akan memanggil loader yang ada di belakangnya, misalnya, Babel-loader atau node-sass.

Grafik menunjukkan waktu perakitan. Bilah biru - 100% waktu pembuatan, tanpa cache-loader, dan bersamanya - 7% lebih lambat. Ini karena cache-loader menghabiskan waktu ekstra menyimpan cache ke sistem file. Sudah di majelis kedua, kami menerima keuntungan nyata - perakitan itu 2 kali lebih cepat.

gambar

Solusi kedua lebih canggih - HardSourcePlugin . Perbedaan utama: cache-loader hanyalah sebuah loader yang dapat beroperasi hanya dalam rantai loader dengan kode atau file, dan HardSourcePlugin memiliki akses hampir penuh ke ekosistem Webpack, dapat beroperasi dengan plugins dan loader lainnya, dan memperluas ekosistem untuk caching sedikit. Grafik di atas menunjukkan bahwa pada peluncuran pertama, waktu build meningkat sebesar 37%, tetapi pada peluncuran kedua dengan semua cache, kami mempercepat 5 kali.

gambar

Bagian terbaiknya adalah Anda dapat menggunakan kedua solusi secara bersamaan, yang kami lakukan di N1.RU. Hati-hati, karena ada masalah dengan cache, yang akan saya bahas nanti.

Plugin / loader yang sudah Anda gunakan mungkin memiliki mekanisme caching bawaan . Sebagai contoh, babel-loader memiliki sistem caching yang sangat efisien, tetapi karena alasan tertentu dimatikan secara default. Fungsionalitas yang sama ada di mengagumkan-typeScript-loader . Plugin UglifyJS juga memiliki caching, yang sangat bagus. Dia mempercepat kami beberapa menit.

Dan sekarang masalahnya.

Masalah caching


  • Cache mungkin tidak divalidasi dengan benar .
  • Solusi yang diterapkan mungkin tidak berfungsi dengan plugin, loader, kode Anda yang terhubung, atau satu sama lain . Dalam hal ini, cache-loader adalah solusi sederhana dan tidak repot. Tetapi dengan HardSourcePlugin Anda harus lebih berhati-hati.
  • Sulit untuk debut jika semuanya rusak . Ketika caching tidak berfungsi dengan benar dan terjadi kesalahan yang tidak dapat dipahami, akan sangat sulit untuk mencari tahu apa masalahnya.

Bagaimana cara menghemat produksi?


Cara terakhir untuk mempercepat suatu proses adalah tidak melakukan bagian apa pun dari proses tersebut. Mari kita pikirkan bagaimana Anda dapat menghemat produksi? Apa yang tidak bisa kita lakukan? Jawabannya pendek - kita tidak bisa melakukan apa-apa ! Kami tidak punya hak untuk menolak sesuatu dalam produksi, tetapi kami dapat menghemat banyak dalam dev .

Apa yang harus dihemat:

  • Jangan kumpulkan peta sumber sampai kami membutuhkannya.
  • Gunakan style-loader alih - alih skema keren dengan penghapusan dan pemrosesan css melalui loader css. Style-loader itu sendiri sangat cepat, karena mengambil garis css dan mendorongnya ke fungsi yang memasukkan garis itu ke dalam tag gaya.
  • Anda dapat meninggalkan dalam daftar browser hanya browser yang Anda gunakan secara khusus - kemungkinan besar ini adalah chrome terakhir . Ini akan sangat mempercepat .
  • Benar-benar meninggalkan segala optimasi sumber daya : dari UglifyJS, css-nano, gzip / brotli.

Akselerasi build adalah paralelisasi, caching dan penolakan perhitungan. Dengan mengikuti tiga langkah sederhana ini, Anda dapat mempercepat sangat banyak.

Bagaimana cara mengkonfigurasi webpack?


Kami menemukan cara merakit bundel mimpi dan cara merakitnya dengan cepat, dan sekarang kami akan mencari cara mengonfigurasi Webpack sehingga kami tidak menembak diri sendiri setiap kali Anda mengubah konfigurasi.

Konfigurasi evolusi dalam proyek


Jalur webpack-config pada proyek dimulai dengan konfigurasi sederhana . Pada awalnya Anda hanya memasukkan Webpack, Babel-loader, sass-loader dan semuanya baik-baik saja. Kemudian, tiba-tiba, beberapa kondisi muncul di process.env , dan Anda memasukkan persyaratan. Satu, kedua, ketiga, lebih dan lebih, sampai suatu kondisi dengan opsi "ajaib" ditambahkan. Anda mengerti bahwa semuanya sudah sangat buruk, dan lebih baik duplikat konfigurasi untuk dev dan produksi, dan lakukan koreksi dua kali. Semuanya akan lebih jelas. Jika Anda memiliki pemikiran: "Apakah ada yang salah di sini?", Maka satu-satunya saran yang bekerja adalah untuk menjaga konfigurasi . Saya akan memberi tahu Anda bagaimana kami melakukannya.

Pertahankan konfigurasi


Kami menggunakan paket webpack-merge . Ini adalah paket npm yang dibuat untuk menggabungkan beberapa konfigurasi menjadi satu. Jika Anda tidak nyaman dengan strategi penggabungan default, Anda dapat menyesuaikannya.


4 :

  • Loaders.
  • Plugins.
  • Presets.
  • Parts.

.

Plugin/Loader


, , API, , .

Itu terlihat seperti ini:

 /** *  JSdoc * @param {Object} options * @see    */ module.exports = function createPlugin(options) { return new Plugin(options); }; 

, , , . , url-loader :

 /** * url-loader    file-loader.        * * @example * -   some-image.png.     url-loader,  url-loader    * 1.    ,  url-loader    base64  * 2. , url-loader    outputPath + name     ,     . *    some-image.png,     outputPath/images/some-image.12345678hash.png,  url-loader  * publicPath/images/some-image.12345678hash.png * * @param {string} prefix    * @param {number} limit    ,    * @return {Object} loader   * @see https://www.npmjs.com/package/url-loader */ 

, , , , , , . , , , , url-loader. :

 function urlLoader(prefix = 'assets', limit = 100) { return { loader: 'url-loader', options: { limit, name: `${prefix}/[name].[hash].[ext]` } }; }; 

. , Loader .

Preset


webpack. , , , webpack, . — , , scss-:

 { test: /\.scss$/, use: [cssLoader, postCssLoader, scssLoader] } 

.

Part


— , . , , . , :

 entry: { app: './src/Frontend/app.js' }, output: { publicPath: '/static/cabinet/app/', path: path.resolve('www/static/app') }, 

:

  • , , , json, , , splitChunks.
  • dev , , js/css
  • Part , output, publicPath, entry-point , , source map.

gambar

Webpack-merge . , . webpack-merge 3-7 , Babel-loader, . , .


. , . , webpack — . , .

, !

Frontend Conf . , — , , Frontend Conf ++ .

- ? FrontenConf ++ , 27 28 . 27 , 15 . — !

Source: https://habr.com/ru/post/id433324/


All Articles