Hiện tại các website đang có xu hướng trở thành những web app với các đặc tính như:

  • Càng ngày càng sử dụng JS nhiều hơn
  • Những browser ngày càng hỗ trợ những công nghệ mới
  • Những trang full-page-reload ít đi, single page app lên ngôi Dẫn đến phần code client-side ngày càng nhiều. Điều đó có nghĩa chúng ta cần phải có một công cụ để quản lí chúng một cách hiệu quả. Webpack là một trong những công cụ đó, vậy webpack là gì trong bài này chúng ta tìm hiểu về nó nhé

Webpack là gì?

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.

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

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

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

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,…

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

– 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,…

Viết câu trả lời

Drop Images