Webpack là gì? Cách sử dụng webpack để build một project bất kì

Webpack là gì?. Nó dùng để làm gì???

Như tiêu đề thì web pack là gì, ngắn gọn thì Webpack là công cụ giúp gói gọn toàn bộ file js, css(bao gồm cả scss,sass,..). Việc gói gọn không phải là lộn xộn hết cả lên mà nó được gói theo cấu trúc project, từ phần modul này sang phần kia. Ngoài ra webpack còn rất nhiều chức năng hữu dụng nữa, vd như optimize hay  tuỳ chọn chạy trên môi trường khác nhau(dev hoặc production), watch file,… Mình đã xem qua webpack sử dụng plugin nén 1 file js từ 6mb xuống còn 76 kb. : )). Với sự contribute của một cộng đồng dev khổng lồ nên webpack là tool hỗ trợ rất tốt cho các dev js, việc sử dụng webpack để dùng cho các project lớn là đều hết sức tuyệt vời.

Vậy chúng ta sử dụng nó như thế nào, trong lập trình thì bất kì một bài toán nào cũng phải có input và output, vậy webpack cũng thế, ta tạo một file webpack.config.js với đoạn code sau

//webpack.config.js

module.exports = {

entry: './index.js',// entry sẽ là input

output: { filename: 'bundle.js' } // như cái tên của nó thì sẽ là ouput

Module trong webpack

Vậy có input và output rồi thì thiếu cái gì nữa. Đó là module, vậy hiểu đơn giản thì nó là nơi khai báo loaders, preLoaders, postLoaders, mình thấy trong thực tế chỉ dùng 2 cái đầu là chủ yếu, nên mình sẽ viết 2 cái đầu thôi (cái thứ 3 nói trắng ra là chưa dùng và không biết :v )

preLoaders: Là các tiền xử lý được nạp khi chạy các modul loader. Nó sẽ load các ESLint(check cú pháp) JSHint. Thường mình sẽ config cái này khi code trên môi trường dev. Còn môi trường product sẽ xoá đi đỡ mất công phải check các kiểu mất thời gian

loaders:Ở đây sẽ khai báo một mảng chứ các compile các ngôn ngữ khác nhau. Đây là chỗ khai báo rất quan trọng của webpack, chẳng hạn như chuyển less, scss về css, es6 về es5 thì sử dụng babel.

module : {
   loaders : [
     {
       test : /\.jsx?/,//  complier những file có đuôi jsx
       include : APP_DIR,
       loader : 'babel-loader'
     },
     {
     test: /\.js$/, // là value chuỗi regex , khi phân tích modul thì webpack sẽ chỉ tìm những file 
     //khớp với định dạng này
     exclude: /node_module/, // bỏ qua các thư mục hoặc file khi khai bảo ở đây
     loader: 'babel-loader', // load .Ở đây là vì mình chuyển đổi code es6 =>es5 nên dung babel
     query: {
        optional: 'runtime',
        cacheDirectory: true,
        presets: ['es2015']
        }
     }
  ]
}

Code splitting trong webpack

Đã nói đến webpack thì không thể không nhắc đến code splitting, đây là tính năng mình thích nhất ở webpack, mình sẽ đưa ra một vd đơn giản thế này, trong một dự án thì việc import rất nhiều thư viện vào cùng một lúc là điều hết sức bình thường, nếu ta có file A.js import thư viên C chẳng hạn và cũng có một file B.js import thư viên C, vậy khi webpack build thì sẽ thành 1 file mà chứa code 2 lần cái thư viện C, vậy việc này có thể gây giảm performance

Có 3 cách tiếp cận để split code hiện tại:

  • Entry point: Phân chia thủ công bằng cách cấu hình file entry, file để bắt đầu chạy ứng dụng và từ đó webpack hoạt động
  • Prevent duplication : Sử dụng splitChunks để xóa những bundle trùng lắp và split ra các chunks, hiểu đơn giản là webpack nó sẽ tự động tìm các thư viện import để ra các file riêng khác nhau, khi code logic của mình cần đến thì sẽ lấy những file riêng ấy để dùng
  • Dynamic Imports: Chia code thông qua các function được gọi trong các modules.

Entry Point: cách này khá thủ công và thường là sẽ không dùng đến, nếu như trường hợp ở dưới cả hai 2 index.js và lib.js đều cùng add một thư viện C thì thành như kiểu mình đã sử dụng thư viên C 2 lần

const path = require('path');

const webpack = require('webpack');

const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {

  entry: {

    index: './src/index.js',

    lib: './src/lib.js'

  },

  plugins: [

    new HTMLWebpackPlugin({

      title: 'bla bla'

    }),
   output: {

    filename: '[name].bundle.js',

    path: path.resolve(__dirname, 'dist')

  }

};

Prevent duplication:

Ở prevent duplication thì chúng ta sẽ cho vào một plugin splitChunks, nhiệm vụ của nó sẽ lấy tất cả các thư viện được import trong project, nó sẽ được tách ra thành các file riêng biệt, đến khi nào code logic của ta cần những thư viện đó thì nó sẽ tự động import

const path = require('path');

const webpack = require('webpack');

const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {

  entry: {

    index: './src/index.js',

    lib: './src/lib.js'

  },

  plugins: [

    new HTMLWebpackPlugin({

      title: 'bla bla'

    }),

   optimization: {
    splitChunks: {
      chunks: 'all'
     }
   }
   ],
   output: {

    filename: '[name].bundle.js',

    path: path.resolve(__dirname, 'dist')

  }

};

Dynamic imports

Ở trong hàm này, hàm getCompoment sẽ return dynamic imports và trả về lodash, tại sao ta lại làm phức tạp thêm thế này, đơn giản là vì dynamic imports nó import lodash khi cần và nó giúp tăng performance.

function getComponent() {
   return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {
   var element = document.createElement('div');
  var _ = _.default;
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    return element;
  }).catch(error => 'An error occurred while loading the component');
  }
   getComponent().then(component => {
   document.body.appendChild(component);
 })

Run webpack theo code dưới đây:

const path = require('path');
    module.exports = {
    mode: 'development',
    entry: { 
       index: './src/index.js' // chỉ cần file index ,không như 2 TH kia
             
           },
    output: {
      filename: '[name].bundle.js',
      chunkFilename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }

  };

Plugin trong webpack

Tiếp theo là plugin, hiện nay với sử đóng góp rất nhiều từ cộng đồng nên số lượng plugin là rất lớn, mình không kể hết đc nhưng phải kể đến các plugin không thế thiếu khi run project như UglifyJSPlugin  webpackDashboard, webpackbundleanalyzer,… Vì trong giới hạn bài viết nên mình sẽ không đi giải thích và liệt kê ra từng cái một, các bạn có thể tham khảo nhiều hơn ở Link này.

Cách sử dụng:

const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
     index: './src/index.js',
     lib: './src/lib.js'
 }, 
plugins:
   [ 
    new HTMLWebpackPlugin({ title: 'Code Splitting' }),
    new webpack.optimize.CommonsChunkPlugin({ name: 'common' }) 
   ],
output: {
   filename: '[name].bundle.js',
   path: path.resolve(__dirname, 'dist')
 }
};

Môi trường chạy

Hồi xưa khi mình mới học react, lúc đó chỉ biết xài create-react-app của bọn facebook, thấy react học thật là dễ. Sau đó để nâng cao khả năng code thì mình đã kiếm vài project về react trên github đọc thử và vào đã bị choáng vì có quá nhiều file lạ, trong đó chính là webpack. Cơ chế chạy của nó khác hoàn toàn với create react-app, về sau mình mới nhận ra thằng create-react-app nó đã tích hợp sẵn rất nhiều thứ kinh khủng trong đó mới tạo ra chương trình chạy ngon lành thế và điều ngạc nhiên trong project, mình thấy nó có tận 3 file webpack. Giải đáp ra thì hiểu đơn giản một bản để dev phát triển còn một bản product để build server cho user sử dụng, với bản dev thì ta muốn giữ lại comment code cho thằng khác đọc chẳng hạn, bản product thì muốn minify để tối ưu chẳng hạn. Vì vậy họ mới sinh ra chuyện tách bạch các môi trường ra như thế. Vậy 3 file ấy là 3 file gì ??

webpack.config.js: File này là file chạy chung cho cả 2 môi trường

– webpack.config.dev.js: Chỉ chạy cho môi trường dev, ở đây bạn có thể thêm các plugin auto log data. Để thuận tiện code việc phát triển sản phẩm

webpack.config.prod.js: Chỉ triển khai trên môi trường production, ở đây thường mọi người sẽ config minify, xoá comment,…

Tiếp  theo, nhiều người chạy webpack và tò mò hỏi tại sao đôi khi trong file html nhúng script một cái folder không tồn tại trong khi app của chúng ta vẫn chạy ngon. Thì đó là chính là tính năng của webpack, môi trường production thì cho phép triển khai bundle file và chạy thật, bạn sẽ thấy file nó được sinh ra thật và tất nhiên nó sẽ được lưu trên ổ cứng còn với môi trường dev thì khá nhiều người thắc mắc tại sao nhiều người tải project về nghịch, rõ là nó được compiler nhưng không thấy. Khi mở source trong chrome thì lại thấy, thì mình giải thích ở đây là vì nó chạy trên môi trường dev, file nó sinh ra sẽ được lưu trên ram, không có trong ổ cứng

Tổng kết:

Webpack là một công cụ có thể nói là quá hữu ích, thông thạo webpack là một lợi thế rất lớn khi code, nó giúp chúng ta dễ thở hơn trong công việc và tối ưu project và quản lý dự án một cách tuyệt vời. Mình nhận ra thực sự của điều này khi xem qua webpack Page builder của bravebits, từ việc tối ưu đến clone project, watch file, run project một cách dễ dàng. Bài viết trên đây mình chỉ giới thiệu qua các phần basic nhưng khá là core của webpack. Bạn có thể tham khảo một số link giới đây để tìm hiểu kĩ hơn về webpack 

Document: webpack

Bài viết hay trên medium: react and webpack, react combine webpack

Comments

Let’s make a great impact together

Be a part of BraveBits to unlock your full potential and be proud of the impact you make.