[WEBPACK] Webpack siêu tốc 1: Cấu hình Dev Server, Babel Loader, Style Loader, File Loader
https://xdevclass.com/webpack-sieu-toc-cau-hinh-dev-server-babel-loader-style-loader-file-loader/
Last updated
Was this helpful?
https://xdevclass.com/webpack-sieu-toc-cau-hinh-dev-server-babel-loader-style-loader-file-loader/
Last updated
Was this helpful?
C:\Users\Administrator\Desktop\practice\webpack.config.js
C:\Users\Administrator\Desktop\practice\package.json
C:\Users\Administrator\Desktop\practice\index.html
C:\Users\Administrator\Desktop\practice\src\add.js
C:\Users\Administrator\Desktop\practice\src\index.css
C:\Users\Administrator\Desktop\practice\src\index.js
C:\Users\Administrator\Desktop\practice\src\index.scss
C:\Users\Administrator\Desktop\practice\src\loadImage.js
C:\Users\Administrator\Desktop\practice\src\subtract.js
Nội dung bài viết
Mình tin rằng nhiều anh em đã từng nghe qua Webpack, nhưng đôi khi vẫn chưa hiểu nó là gì, dùng nó như thế nào. Đừng lo, trong chuỗi bài Webpack siêu tốc này, mình sẽ giải thích và hướng dẫn anh em một cách siêu dễ hiểu luôn, đọc phát làm được ngay. Không nói nhiều nữa, đi vào thực hành nhé.
Để hiểu được webpack thì bạn phải biết lý do mà nó sinh ra.
Ngày xưa thuở mới học lập trình web thì chúng ta thường tạo 1 project với 3 file đơn giản là: index.html
,style.css
, app.js
. Nhưng càng ngày thì css cũng như javascript càng phát triển, chúng ta SASS, LESS để biên dịch sang CSS, rồi các phiên bản Javascript mới hơn như ES6, ES2018, ES2019… Lúc này mới nảy sinh các vấn đề như sau:
Nếu anh em dùng cú pháp ES6 hay ES2018 thì các trình duyệt cũ chỉ hỗ trợ đến ES5 không thể hoạt động được
Viết code SASS, LESS thì trình duyệt không đọc được. Phải dùng một số công cụ chuyển đổi sang CSS như node-sass, Gulp, Koala,…
Viết code xong rồi còn phải nén code lại để giảm dung lượng code nhằm tăng tốc độ load trang
Khi thao tác ở môi trường dev, mỗi khi có thay đổi trên code, ta thường tự tay F5 để reload lại trình duyệt. Nếu muốn tự động thì ta có thể dùng một số tool ngoài kia như Live Server trên VSCode,…
Bên trên là một số trong rất nhiều vấn đề mà anh em sẽ gặp phải và nếu mỗi vấn đề dùng mỗi công cụ thì không phải là lựa chọn tối ưu. Vì thế Webpack sinh ra để giải quyết tất cả vấn đề trên.
Webpack là một công cụ chạy trên môi trường NodeJs, giúp bạn đóng gói js, css, image, font… thành một hay nhiều file một cách dễ dàng.
Oke, Bây giờ chúng ta cùng cấu hình một project đơn giản với Webpack.
Tạo một project mới và khởi tạo file package.json
với câu lệnh npmnpm init
Tạo một thư mục public và 1 file index.html
trong đó. File này sẽ load một file JS sau khi webpack thực hiện xong.
Tạo file .gitignore
để tránh đẩy thư mục node_modules
và dist
lên git nhé
Babel là trình biên dịch Javascript thành các version thấp cấp hơn để phù hợp cho các trình duyệt khác nhau.
Nếu các bạn dùng npm thì
Còn mình dùng yarn nên sẽ dùng cú pháp dưới đây. Hơi khác 1 xíu thôi, nhưng yarn cho tốc độ cài nhanh hơn npm
Giải thích:
Ở đây mình dùng yarn thay vì npm, các bạn có thể dùng npm tùy thích nhé. -D tương đương –save-dev, ám chỉ đây là các devDependencies
@babel/core là phần lõi của babel, nơi chứa các thuật toán của nó
@babel/preset-env là một bộ cài đặt giúp bạn biên dịch code Javascript về cú pháp cũ hơn (nếu không setting gì thì mặc định target là ES5 và modules là auto). Xem thêm tại đây
babel-loader giúp bạn tích hợp babel vào trong webpack
Nếu không dùng babel thì có chạy được webpack không?
Câu trả lời là vẫn oke nhé.
Chúng ta cùng làm rõ vấn đề sau. Nếu không dùng các transpiler như Babel thì khi webpack build 1 project, file build sẽ có 2 thành phần
Phần code của bạn sẽ được giữ nguyên. Nếu bạn dùng ES2016, ES2020 thì nó vẫn sẽ không bị thay đổi
Phần code của webpack thêm vào để nối các file của bạn thành 1 thể thống nhất. Phần code này thì mặc định webpack dùng cú pháp của ES6.
Vậy nên khi bạn dùng các trình biên dịch Javascript thì nó chỉ biên dịch phần 1 (tức code của bạn), còn phần 2 (code webpack thêm vào) thì bạn phải cấu hình bằng output.environment . Nhiều anh em không để ý đoạn này, build xong nhưng trong file bundle vẫn thấy dùng arrow function
yarn add css-loader file-loader sass sass-loader style-loader -D
Giải thích luôn
style-loader, css-loader giúp bạn có thể import được css vào file js
sass, sass-loader giúp bạn biên dịch scss sang css
file-loader giúp bạn import được các file ví dụ như ảnh, video vào file js
Đầu tiên ta phải cài yarn add webpack webpack-cli webpack-dev-server -D
Giải thích
webpack là phần lõi của webpack
webpack-cli giúp ta gõ được lệnh của webpack trên terminal
webpack-dev-server hỗ trợ tạo một server localhost cho môi trường dev
Tạo 1 file webpack.config.js
Copy các dòng lệnh này vào mục script
trong package.json
Tạo thư mục src
Copy 1 file ảnh logo.jpg bất kì vào thư mục src
Và giờ ta có một cây thư mục đầy đủ như thế này
Bây giờ mới giải thích từng cái nha
webpack.config.js
Chúng ta đặt tên là webpack.config.js
như vậy thì khi chạy lệnh webpack trong package.json
webpack sẽ tự hiểu là dùng config từ file này. Nếu bạn muốn dùng tên file khác thì bạn phải chỉ rõ ra trong package.json
. Tìm hiểu thêm tại đây
Trong file config, chúng ta có thể export một object, một function, một promise, hay một array. Trong bài này mình thích export function hơn, vì nó cho phép ta dùng được các biến từ bên ngoài truyền vào. Tìm hiểu thêm tại đây
Chúng ta phải cung cấp mode khi cấu hình webpack, mỗi mode sẽ có một bộ setting được cài sẵn. Công việc của chúng ta là cấu hình lại theo ý muốn của mình. Tìm hiểu thêm tại đây
Nếu các bạn để ý thì ở file package.json
mình có dòng --mode development
, nghĩa là webpack sẽ chạy ở mode development. Và ở trong file webpack.config.js
mình có thể xác định được đang ở mode nào bằng cách dùng agrv.mode
entry: nơi chứa một hay nhiều các file đầu vào. Ở đây mình dùng fileindex.js
. Vì ở trong file này mình import mọi file khác vào mà. Tìm hiểu thêm tại đây
module.rules: Nhận vào một array. Đây là nơi chứa các loader
test: Nhận vào một Regex để xác định kiểu file. Nếu là true thì nó sẽ chạy loader. Với babel-loader thì sẽ chạy với các file js, jsx. style-loader sẽ chạy với sass, scss, css. file-loader sẽ chạy với các file png, svg, jpg, gif.
exclude: Nhận vào một regex để loader loại trừ ra những file này
use: Nhận vào một object hoặc một array chứa thông tin loader
Để ý đoạn babel-loader mình dùng presets là @babel/preset-env không cấu hình gì thêm nghĩa là dùng bộ mặc định của @babel/preset-env. Nó sẽ biên dịch sang cú pháp ES5
Có source map, dễ dàng debug css
Để ý đoạn file-loader mình có option là name: '[path][name].[ext]'
nghĩa là các file bạn ở thư mục nào thì khi build ra nó cũng sẽ tạo một thư mục tương tự như vậy. Ví dụ bạn có file src/logo.png
thì khi build ra bạn sẽ có dist/src/logo.png
resolve: { extensions: [‘.js’, ‘.jsx’] }: Nơi chứa thứ tự ưu tiên khi import các file. Ví dụ các có 2 file name.js
và name.jsx
trong cùng 1 folder. Ở một file khác bạn import * from 'name'
thì nó sẽ ưu tiên chọn file .js
output.path: Nhận vào một string là đường dẫn tuyệt đối đến thư mục sau khi build. Những option mà nhận vào đường dẫn tuyệt đối thì ta hay dùng path.resovle()
hoặc path.join()
kết hợp với biến global là __dirname
. Anh em có thể xem sự khác biệt của 3 thằng đó như thế này. Tùy sở thích và mục đích mà anh em chọn cách dùng cho phù hợp nhé.
__dirname: D:\Projects\Training-Webpack\Bai1path.join(): .path.join("abc"): abcpath.join(__dirname, "abc"): D:\Projects\Training-Webpack\Bai1\abcpath.resolve(): D:\Projects\Training-Webpack\Bai1path.resolve"abc"): D:\Projects\Training-Webpack\Bai1\abcpath.resolve(__dirname, "abc"): D:\Projects\Training-Webpack\
Bai1\abc
output.publicPath: Chứa đường dẫn tương đối mà từ file index.html
trỏ đến các file trong thư mục dist sau khi build. Ví dụ ở file loadImage.js
phía trên, ta import logo
thì biến logo
sẽ bằng output.publicPath + 'src/logo.jpg'
. Nếu sau khi build, chúng ta chạy file index.html
ở một vị trí khác không phải nằm trong thư mục public thì sẽ vô tình làm biến logo
bị sai.
publicPath hoạt động vô chỗ này đây
output.filename: Tên file sau khi build
output.environment: Như mình đã giải thích ở trên thì vì mặc định webpack generate ra code dùng 1 số cú pháp của ES6, nhưng target mình mong muốn là ES5 nên mình cần chỉnh một số thông số như sau.
arrowFunction: Hỗ trợ arrow function.
bigIntLiteral: Hỗ trợ BigInt
const: Hỗ trợ khai báo const và let
destructuring: Hỗ trợ destructuring
dynamicImport: Hỗ trợ async import
forOf: Hỗ trợ vòng lặp forOf cho các array
module: Hỗ trợ moudle ES6 (import … from ‘…’)
devtool: chứa cấu hình file sau khi dev hoặc sau khi build. Ở đây thì khi dev mình để source-map
cho dễ debug js, còn khi build thì mình xóa source map đi cho nhẹ file build. Tìm hiểu thêm tại đây
Đến dev server nhé. Ở dev server bạn tưởng tượng nó sẽ tạo một server localhost ngay tại thư mục root
devServer.contentBase: Chứa đường dẫn tương đối đến file index.html
devServer.port: port khi chạy localhost
devServer.hot: Chế độ hot reload. Mặc định thì ở dev server thì webpack sẽ refresh lại trang mỗi khi có thay đổi nhỏ trong code. Hot Reload kiểu như nó không cần reload lại trang nhưng vẫn giúp chúng ta nhận biết được sự thay đổi.
devServer.publicPath: Chứa đường dẫn tương đối từ thư mục root trỏ đến thư mục build (ở đây là dist). Chú ý phải thêm /
ở trước và sau
devServer.watchContentBase: Nếu bạn có thay đổi gì trong file index.html thì trình duyệt cũng tự động reload.
Oke. Vậy là xong rồi đó. Khi bạn muốn chạy ở môi trường dev thì chỉ cầnyarn start
Thành quả xứng đáng :v
Thư mục dist sau khi build
Sau khi build xong bạn có thể sử dụng file public/index.html để chạy.
Các bạn để ý file add.js có function treeShaking
được export nhưng không được dùng ở bất kỳ đâu. Vậy nên webpack sẽ không dùng function này, vì thế nó sẽ không có trong code ở file build. Đây được gọi là tính năng tree shaking của webpack nhằm giúp giảm bớt code dư thừa (unused module export detection).
Điển hình là thư viện lodash . Nếu bạn import { get } from 'lodash'
thì nó sẽ không tree-shake, webpack vẫn sẽ import cả 1 thư viện lodash khổng lồ vào file bundle của bạn. Chẳng khác gì so với việc import _ from 'lodash'
Để fix vấn đề trên thì ta có thể dùng cú pháp import get from 'lodash/get'
, hoặc đơn giản hơn là dùng thư viện lodash es , vì thư viện này được build bằng es module.
Bài này khá nhiều kiến thức, nhưng mình đã giải thích rất kĩ rồi. Việc của mọi người là tải project về và tự tay thay đổi các thông số option thử là quen tay ngay.
Hẹn anh em ở bài sau với nhiều cấu hình chuyên sâu hơn nha
Github: link github project, folder bài 1 nhé
Bạn có thể chạy Babel mà không cần Webpack, nhưng trong bài này mình kết hợp babel với webpack để tạo ra bộ đôi “trai tài gái sắc”
Để ý đoạn style-loader mình có dùng options sourceMap, nếu là đang dev thì mình sẽ để sourceMap, còn không thì sẽ không để. Cho bạn nào chưa biết thì khi import css vào file js, webpack sẽ chuyển nó lên thẻ <style>
trong thẻ head
. Vì thế bạn cần phải có source map để thuận tiện cho việc dev
Webpack đưa css vào tag <style> trong <head>
Không có source map thì không biết style này từ đâu ra
Điều đặc biệt là những nơi cho phép để đường dẫn tương đối thì bạn có thể để đường dẫn tuyệt đối, nhưng ngược lại thì không được, đường dẫn tương đối không thể dùng trong những option yêu cầu đường dẫn tuyệt đối.
Mở trình duyệt lên tại địa chỉ http://localhost:3000, bạn sẽ thấy giao diện project
Muốn build webpack thì yarn build
Tính năng này chỉ hoạt động với code dùng cú pháp ES Module (import export đó ), còn lại thì sẽ không hoạt động nhé.