Webpack: Hiểu Cơ Bản Về Cấu Trúc Của Webpack

    Ở bài viết tiếp đầu tiên trong một serie nhỏ về webpack này mình sẽ cùng các bạn đi vào chi tiết hơn với webpack và từng thành phần của nó. Phải nói là mình rất ấn tượng về cách làm việc và xử lý cũng như phân tách module của webpack. Bạn cũng có thể để ý các bộ cli rất nổi bật hiện nay và điển hình như create-react-app (React), Angular CLI (Angular >2), Vue CLI (Vue) đều sử dụng webpack là module bundle chính để phục vụ cho việc optimize, share chunk và rất nhiều tính năng khác. Ở bài viết này mình sẽ chỉ chia sẻ một cách cơ bản nhất về webpack mà mình đã làm việc với nó từ những ngày đầu tiên. 
    Chú ý: Bài viết được tác giả viết và lưu lại trong học ký từ hơn 1 năm trước và hiện tại đã có rất nhiều bài chia sẻ về webpack lên tác giả sẽ đi vào phần đã triển khai và làm việc. Rất mong các bạn thông cảm vì điều này nhé 😅.(Tác giả ở đây là mình nhé :]] ).
Ok bài viết của mình sẽ đi qua những phần chính như dưới đây:
  1. Thiết lập môi trường phát triển
  2. Cấu trúc cơ bản của 1 file webpack
  3. Một số chú ý về 2 môi trường phát triển develop và product

1. Thiết lập môi trường phát triển

- NodeJS thì lúc nào cũng cần rồi này 😀.
- Cài đặt các gói phụ thuộc global cho webpack: npm i webpack webpack-dev-server -g  (vơi webpack-dev-server là một web server nhỏ chạy với express nodejs)
- Có thể bạn đã quen với việc bundle và phân tách môi trường với việc sử dụng thông qua một file config có tên là webpack.config.js đặt ở thư mục root của project. Thời gian sau này mình đã cấu hình webpack theo cách phân tách ra làm 3 file nhỏ và đặt ở 3 file này ở thư mục root của dự án:
  • webpack.config.js: đây là file cấu hình cơ bản nhất của mình, file cấu hình này mình sẽ cấu hình các phụ thuộc sử dụng chung được ở cả 2 môi trường product và development
  • webpack.config.dev.js (triển khai trên môi trường develop). tại file này mình sẽ triển khai một số đặc chưng riêng cho môi trường development chẳng hạn như: không minify code không remove comment, console.log, thêm source map ánh xạ để tiện hơn cho việc phát triển, mình cũng thêm một số tính năng hot - reloader cho file cấu hình development này ...
  • webpack.config.prod.js (triển khai trên môi trương production): một số triển khai và tư tưởng viết mã cho file này mà mình hay sử dụng có thể kể đến như: minify (js, css ...), require nhiều hơn phụ thuộc, tạo task hủy bỏ các comment - console.log, ko tạo source map ...
- Vậy thi giờ mình làm thế nào để run webpack với các file cấu hình trên giờ? Bật cửa số command lên và cd tới root-project, mình sẽ thực hiện gõ trên cửa số terminal những lệnh dưới đây:
  • "webpack" => đòng nghĩa với việc bundle dựa trên file webpack.config.js   
  • "webpack --process --color --config webpack.config.prod.js": dòng này tương đương với việc bạn chạy config của file .prod.js
  • "webpack-dev-server --inline --process --color --config webpack.config.dev.js": tương tự với lệnh trên tuy nhiên bạn sẽ chạy với môi trường development. Có một chút khác biệt là bạn sẽ chạy lệnh trên với webpack-dev-server giúp tạo 1 server tự đọng watch các task khi thay đổi
- Tất nhiên mình sẽ không thảnh thơi mỗi lần lại phải gõ cả tá lệnh dài trên được. Mình viết script và đặt tên ngắn gọn cho các task này bằng cách cấu hình option script trong file package.json. File package.json ở root project của mình option script sẽ được custom trông giống thế này: 
- Sau này mỗi khi chạy bạn chỉ cần gõ như này: npm run build hoặc npm run dev cho từng môi trường mà bạn muốn chạy (có thể thay bằng yarn build, yarn dev nếu bạn cài gói quản lý package bằng yarn nhé :) )
- Oke hay vậy nhưng đâu ra cái đống tham số loằng ngoằng phía sau như kia vậy. Hề nó là như này:
  • webpack: triển khai trên môi trường production
  • webpack-dev-server: triển khai trên môi trường develop
  • --progress: Hiển thị phần trăm khi chạy
  • --color: Hiển thị màu khi complie webpack
  • --inline: để xóa thanh bar trong chế độ webpack-dev-server, khi đó ta có thể truy cập web bundle ko thấy thank bar nữa
  • Và còn rất nhiều option khác cho anh, chị, em chọn ở đây nhé
Rồi giờ mình sẽ đi tiếp sang xem một file thiết lập webpack cơ bản có những gì nhé

2. Cấu trúc cơ bản của 1 file webpack

- Dưới đây là cấu trúc cơ bản của một file webpack và đi kèm đó là giải thích cho từng phần sử dụng mà mình đã comment đính kèm.
Đoạn mã có chú thích ở file trên có thể đôi phần giúp bạn hình dung cấu trúc của đoạn mã tổ chức trên webpack như nào rồi nhỉ 😎. Giờ mình sẽ giải thích kỹ hơn một chút nhé:
- Qua tổ chức file ở trên mình sẽ liệt kê các thành phần như sau:
  • Entry: Chứa các file require đầu vào, chúng ta có thể liệt kê danh sách các file thực hiện bundle, optimize ... ở đây. Liệt kê từng file sẽ rất là dở vì vậy webpack đã hỗ trợ chung ta config theo pattern regex để nhận diện các file vd: /.*js/  để lấy toàn bộ các file js chẳng hạn.
  • Output: Đích xuất ra tập tin.
  • Plugin: Là các plugin bên thư viện thứ 3 nhúng vào để làm các công việc chẳng hạn như nén file js,css, html hay  1 công việc nào đó ...
  • Module: Trong module được phân ra làm 3 mục nhỏ
    • preLoaders: Các tiền xử lý,là các xử lý được nạp trước khi bắt đầu với các module loader. Thường thì trong preLoader các dev sẽ check syntax của nó với JSHint hay ESLint (chế độ này thường thiết lập bên môi trường webpack-dev-server), trên môi trường thực tế ko lên triển khai điều này vì sẽ làm mất thêm thời gian check cú pháp ko cần thiết, công việc này thường thiết lập trên môi trường dev-server.
    • loaders: là các xử lý complie các ngôn ngữ khác nhau. Chẳng hạn như đưa về less, scss về css có less-loader, scss-loader, hay chuyển đổi es6, type-script về es5 có ‘babel-loader’ ..vv và rất nhiều loader khác
    • postLoaders: Là hậu xử lý, Các xử lý sau cùng sẽ được thông qua thằng này. Ở đây mình chưa có điều kiện sử dụng thằng này ở thực tế nhiều lên mình xin phép không nói gì thêm.
  • Jshint hoặc Eslint: Đây là các thiết lập để check cú pháp theo một chuẩn được define theo jshint hoặc eslint (nhớ là dành chút thời gian để 'Google it' về nó nhé ).
  • Watch: có 2 giá trị là true hoặc false, true để kích hoạt theo dõi sự thay đổi của tập tin webpack sẽ tự động compile lại và false là ngược lại
- Vẫn còn khá nhiều option khác nằm bên ngoài tuy nhiên với cừng này option cũng là đủ để cấu hình 1 file webpack bundle cơ bản rồi. Để biết thêm chi các option khác thì bạn ghé zô trang chủ webpack để xem thêm nhé
Chú ý: Về việc tại sao phải tạo ra đến 3 loader này trong khi chỉ cần 1 loaders là cần thiết thì Juho Vepsäläinen tác giả của webpack và reactjs có nói, ông sẽ sử dụng nó để linting các đoạn mã của ông ấy (linting ở đây chính là check cú pháp javascript) và tránh việc compile tốn tài nguyên với trường hợp không cần thiết, tác giả sẽ thiết lập check cú pháp ở tiền xử lý preloader trước và nếu fail thì nó sẽ dừng lại thay vì phải chạy vào loaders phía sau, vì vậy tác giả sẽ thiết lập sử dụng lợi thế này trong một số trường hợp với preLoader và tương tự một số lợi thế có lợi với postLoader
- Thành phần loaders: là thành phần khá quan trọng lên mình sẽ giải thích kỹ hơn một chút về các loader, với preloader và postLoaders cũng sử dụng tương tự nhưng với mục đích khác, về cơ bản cấu trúc của nó khá giống nhau. Dưới đây là ví dụ về việc sử dụng loader với 2 thành phần loader: 

- Trong đó:
  • test: value là chuỗi regex so khớp với các định dạng file, khi trình phân tích đi qua test nó sẽ nạp các file này để chuẩn bị cho quá trình xử lý
  • exclude: value là chuỗi regex so khớp với các định dạng file, khi trình phân tích đi qua exclude tự động nó sẽ bỏ qua phân tích các file này (thường thì ta sẽ bỏ file node_module đi).
  • loader: đây là thành phần quan trọng nhất, nó chính là các loader module mà bạn cài từ các gói package npm. Ví dụ trên mình đã sử dụng các gói loader là style-loader, css-loader và babel-loader. Trình phân tích loader sẽ phân tích chuỗi bên trong của nó theo 1 mảng và đi sau là query-string. Đoạn mã với loader css ở trên mình có thể viết là loader: [‘style-loader’,’css-loader’], với loader babel-loader mình có thể viết là: loader: 'babel-loader?optional=runtime,cacheDirectory=true,presets[]=es2015'
  • query: như bạn thấy mình đã trình bày ở trên, thay vì ta sử dụng query-string để truyền cho các option cho nó, trình phân tích webpack cho phép ta nạp các query dưới dạng các option, dễ hình dung và trong sáng hơn hẳn.

3. Một số chú ý về hai môi trường develop và product

- Môi trường dev: webpack-dev-server (Được set up với npm run dev)
 Mô tả: mặc định khi bạn chạy webpack-dev-server với script npm run dev như trên thì nó sẽ chạy ở localhost với port:8080, để đổi cổng thì bạn thay bằng cờ p như mình đề cập ở trên.
Các chú ý:
  • Với môi trường này các file bundle không được ghi ra ổ đĩa mà sẽ lưu trên RAM (cái này mình đọc ở đâu ấy ko nhớ nguồn link) vậy lên bạn sẽ ko thấy tìm thấy các file optimize (gộp, nén các kiểu) ở đâu cả. Để xem được các file này thì các bạn debug trên cửa sổ devtool của các trình duyệt inspect ra để xem nhé.
  • Một chu ý quan trọng nữa là: Tại môi trường này bạn hạn chế tối thiểu optimize nhất, chỉ lên gộp file chứ ko lên remove source map vì như vậy rất khó cho việc gỡ lỗi (debug) sản phẩm của mình trước khi release.
-Môi trường product: webpack (Được setup với npm run build trong package.json).
  • Chế độ này cho phép triển khai budle file và chạy thật,,, file được bundle sẽ được ghi ra như trong đĩa cứng. Bạn sẽ nhìn thấy file này bằng file bằng dung lương (như bằng sương bằng thịt ấy :v). output file sẽ được thiết lập trong option output như mình đã đề cập ở trên đó.

    Rồi vậy là với bài viết này mình đã giới tổng quan các thiết lập cơ bản nhất của một file webpack cũng như cách phân tách các file môi trường rồi đó. Giờ thì bạn đã 'are you ready' chưa. Thử tự viết cho mình một build tool sử dụng webpack làm module bundle xem sao nhé. Còn chưa sẵn sàng thì bài viết tới mình sẽ giới thiệu thêm cho các bạn một số Loader + Plugin thông dụng mà mọi người hay sử dụng trong webpack nhé :D. Hẹn gặp lại các bạn trong bài viết tới nha. Thấy gì sai sai thì comment zô góp ý cùng mình với nhé 😚.

Tham Khảo

Previous
Next Post »