+13

Hãy bỏ túi một vài plugin siêu hữu ích cho Webpack

Chào anh em, lại là mình đây 😄. Hôm nay chúng ta lại tiếp tục đi đến 1 chủ đề tuy mới mà lại cũ 😎, đó là Webpack, hẳng ai đã làm việc với React, Vue chắn chắn đều sẽ biết về module bundler siêu mạnh mẽ và thông dụng này và bài viết này sẽ nói về Plugin webpack một phần được ví như là backbone của webpack. Nào hãy cùng theo dõi nhé 💯

1. Chuẩn bị

Yêu cầu:

  • Đã có kiến thức cơ bản về Webpack.
  • Môi trường mình sẽ sử dụng:
    • Window 10
    • node v12.14.0
    • yarn v1.22.4
    • editor: VSCode

Mục đích:

  • Điểm qua một số plugin siêu hữu ích để anh em có thể dùng cho các dự án sắp tới.

Những phần bỏ qua:

  • Phần cấu hình mình sẽ không mô tả chi tiết trong bài viết, các bạn có thể theo dõi thông qua repo.
  • Giải thích các thuật ngữ, khái niệm cơ bản mà các bạn hoàn toàn có thể đọc thông qua trang chính thức của thư viện đó.

2. Nội dung

Vậy webpack plugin là gì ?

Plugins are the backbone of webpack. webpack itself is built on the same plugin system that you use in your webpack configuration!

Có bao nhiêu loại webpack plugin ?

Cơ bản sẽ gồm 2 loại:

  • Các plugin được tích hợp sẵn bên trong webpack. Ví dụ: DefinePlugin, ProgressPlugin, EnvironmentPlugin, etc.
  • Các plugin được xây dựng từ cộng đồng. Ví dụ: html-webpack-plugin, webpack-bundle-analyzer, copy-webpack-plugin, etc.

Hôm nay, mình sẽ chia sẽ về một số plugin được xây dựng từ cộng đồng mà mình rất rất thường xuyên sử dụng.

Một số plugin

copy-webpack-plugin

Mục đích của plugin này để copy các file hay thư mục được chỉ định đến thư mục nào đó (thông thường là thư mục build)

Demo

// webpack.config.js
const path = require('path')
const CopyPlugin = require('copy-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve('src/assets'),
          to: path.resolve('build/assets'),
          toType: 'dir',
        },
      ],
    }),
  ],
}

Chúng ta sẽ chỉ định copy thư mục từ src/assets sang build/assets khi tiến hành build

Thư mục trước khi build

Chạy lệnh sau để build

yarn webpack

Thư mục sau khi build

Bạn sẽ thấy plugin đã copy 1 bản assets sang thư mục build do ta chỉ định ở cấu hình phía trên.

case-sensitive-paths-webpack-plugin

Mục đích của plugin này để bắt buộc phân biệt chữ hoa thường khi các bạn import file

Demo

Cấu trúc thư mục

Khi bạn không sử dụng case-sensitive-paths-webpack-plugin

// webpack.config.js
const path = require('path')
// const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  // plugins: [new CaseSensitivePathsPlugin()],
}

Kết quả

Mọi thứ vẫn diễn ra và như không có chuyện gì

Khi bạn sử dụng case-sensitive-paths-webpack-plugin

// webpack.config.js
const path = require('path')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  plugins: [new CaseSensitivePathsPlugin()],
}

Kết quả

Lập tức có mỗi lỗi không tìm thấy module, để giải quyết bạn cần phải import chính xác module name có phân biệt hoa thường.

circular-dependency-plugin

Mục đích của plugin này để đảm bảo không xảy ra quá trình import chéo giữa 2 hay nhiều file

Demo

// index.js
import a from './a'
import b from './b'

a()
b()


// a.js
import b from './b'

export default function a() {
  console.log('function a')
  b()
}


// b.js
import a from './a'

export default function b() {
  console.log('function b')
  a()
}

Chúng ta sẽ import a vào b và b vào a

Khi bạn không sử dụng circular-dependency-plugin

// webpack.config.js
const path = require('path')
// const CircularDependencyPlugin = require('circular-dependency-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  plugins: [
    // new CircularDependencyPlugin({
    //   exclude: /node_modules/,
    // }),
  ],
}

Kết quả

Sẽ không có bất kì warning nào để cảnh báo chúng ta về việc phụ thuộc chéo giữa 2 file

Khi bạn sử dụng circular-dependency-plugin

// webpack.config.js
const path = require('path')
const CircularDependencyPlugin = require('circular-dependency-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  plugins: [
    new CircularDependencyPlugin({
      exclude: /node_modules/,
    }),
  ],
}

Kết quả

Lập tức warning để chúng ta có thể cân nhắc điều chỉnh

html-webpack-plugin

Mục đích của plugin này để giúp webpack tự động tạo 1 hay nhiều file html (nâng cao) và liên kết các module sau khi build, ngoài ra có thể tối ưu và sử dụng các biến môi trường trong file html đầu ra.

Demo

Cấu hình webpack và tệp html mẫu cho plugin

Sau khi build

Tệp bundle đã được link tới tệp html tự động và kích hoạt tối ưu file html đầu ra

mini-css-extract-plugin

Mục đích của plugin này để gom rất cả các module css vào 1 file duy nhất

Demo

Mình sẽ phải sử dụng với css-loader để giúp resolve các tệp css như module Các tệp ban đầu

Sau khi build

Một file main.css duy nhất chứa tất cả css từ các tệp.

Để có thể minify css bạn nên kết hợp với plugin optimize-css-assets-webpack-plugin

webpack-bundle-analyzer

Mục đích của plugin này để tạo ra một biểu đồ để bạn có thể hình dung thông tin của các tệp đầu ra, từ đó có thể biết file nào, library nào kích thước quá lớn mà có thể tiến hành tối ưu

Demo

Mình sẽ thêm module lodash để bạn có thể nhìn thấy rõ hơn trong bản build vì lodash có kích thước khá lớn

Sau khi build, webpack-bundle-analyzer sẽ kích hoạt một server và mở 1 trang như sau

Bạn có thể nhìn thấy rõ các thông tin của mỗi tệp đầu ra.

terser-webpack-plugin

Mục đích của plugin này để minify các file js

Demo

Theo mặc định thì terser-webpack-plugin đã kích hoạt gần như hầu hết các tính năng minify cần thiết, chúng ta chỉ nên điều chỉnh một vài option nếu thực sự cần. Ở đây mình sẽ thử kích hoạt xóa các dòng console khi build bằng việc enable terserOptions.compress.drop_console

Kết quả

Tất nhiên là file js đầu ra đã được inline nên không thể đọc. bạn cần dùng prettier hay một công cụ nào đó format lại để kiểm tra

Thực sự các dòng console.log mình sử dụng đã bị xóa trong file js này.

clean-webpack-plugin

Mục đích của plugin này rất đơn giản, nó sẽ kích hoạt xóa thư mục được chỉnh định trong output.path để tiến hành bản build mới mà không ghi đè lên thư mục cũ

Cấu hình rất đơn giản

// webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve('build'),
    publicPath: '/',
  },
  plugins: [new CleanWebpackPlugin()],
}

3. Kết luận

Qua bài viết này hi vọng sẽ giúp anh em hiểu và có thể dùng các webpack plugin này cho các dự án sắp tới.

Ngoài ra còn rất nhiều plugin khác, anh em có thể tìm hiểu thêm, nó chắn chắn sẽ giúp ích.

Nếu bạn cảm thấy bài viết này hữu ích, hãy chia sẽ cho bạn bè để cùng nhau khám phá những điều mới mẽ trong thế giới JavaScript này nhé 😄

Cảm ơn anh em đã đọc bài viết này.

Toàn bộ ví dụ trên tại repo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí