Giới thiệu Webpack, khái niệm và sử dụng cơ bản

Webpack là một module bundler cho JS (bundler - có nghĩa nó có tính năng gộp nhiều file nguồn JS thành một file, trong quá trình gộp nó đưa vào đầy đủ các dependency - thư viện - cũng như thực hiện một số chuyển đổi - ví dụ tối ưu minify ...), nó là một package của NodeJS - quản lý bởi npm (phải tải + cài đặt NodeJS trước)

Phần này sử dụng Webpack để giúp gộp JS, CSS (gồm cả dịch SCSS thành CSS). Hãy bắt đầu sử dụng Webpack một cách đơn giản như sau:

Tạo một thư mục lưu code đặt tên là webpack-example, trong thư mục đó gõ lệnh sau, để nó sinh ra file package.json nếu chưa có:

npm init -y

Webpack là package NodeJS, cài đặt nó chỉ việc thực hiện lệnh sau trong thự mục dự án:

npm i -D webpack webpack-cli

Sau lệnh này thì đã có webpack mà các dependency để webpack chạy.

Giờ hãy tạo ra 3 file nguồn js làm ví dụ như sau:

src/js/a.js
"use strict";
function Pop1() {
    alert("Thông báo  1");

}
export {Pop1}   //xuất hàm Pop1
src/js/b.js
"use strict";
function Pop2() {
    alert("Thông báo 2");

}
export {Pop2}
src/js/app.js
import { Pop1 } from './a.js';
import { Pop2 } from './b.js';

function Abc() {
    alert("Abc");
}

export {Pop1, Pop2, Abc}

Trong đó, file app.js nạp thành phần từ a.jsb.js. Giờ cần thiết để Webpack build file app.js với các dependency (a.js, b.js) thành 1 file duy nhất lưu ở dist/app.min.js

Thực hiện tạo ra file cấu hình của Webpack có tên là webpack.config.js, cập nhật cho nó nội dung như sau:

const path = require('path');

const devMode = true;

module.exports = {
  mode: devMode ? 'development' : 'production',
  entry: [
      './src/js/app.js', // file nguồn Webpack làm việc
    ],

  output: {
    filename: 'app.min.js',                 // tên file xuất ra
    path: path.resolve(__dirname, 'dist'),  // thư mục lưu
    library: 'mylib',                       // tên thư viện (tự đặt)
    libraryTarget: 'var',
  },

  optimization: {
    // We no not want to minimize our code.
    //minimize: false
  },
};

Sau khi có file cấu hình webpack.config.js, mở file package.json - tại mục scripts sửa thành như sau:

/..
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
/..

Thực hiện gõ lệnh sau để webpack tiến hành gộp file và sinh ra app.min.js:

nmp run build

File app.min.js đã có, bạn có thể mở ra kiểm kết quả. Hoặc tạo ra 1 file test.html với nội dung sau để kiểm tra.

<!DOCTYPE html>
<html>
<head>
    <script src="dist/app.min.js"></script>
</head>
<body>
    <script>
        mylib.Pop1();  mylib.Pop2();  mylib.Abc();
    </script>
</body>
</html>

Tự động chạy Webpack khi file nguồn cập nhật

Muốn mỗi khi file nguồn sửa đổi, cập nhật thì Webpack build lại, trước tiên cài đặt vào nmp-watch

npm install npm-watch

Sau đó mở file package.json thêm vào scrips đoạn script: "watch": "npm-watch", và thêm vào cấu hình như sau

  /..
    
  "watch": {                            //Thêm vào
    "build": "{src,othersrc}/js/*.js"   // loại file thay đổi dẫn đến scrip watch chạy
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "npm-watch"    //thêm vào
  },
/..

Để kích hoạt watch, gõ lệnh

nmp run watch

Build và gộp SCSS, CSS với Webpack

Để làm việc với CSS, SCSS cài thêm một số package sau:

npm i node-sass postcss-loader postcss-preset-env sass-loader css-loader cssnano mini-css-extract-plugin cross-env file-loader

Giả sử có file nguồn src/scss/site.scss muốn biên dịch thành CSS lưu tại dist/css/site.min

Hãy mở file webpack.config.js cập nhật thêm phần hỗ trợ chuyển đổi SCSS như sau:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const postcssPresetEnv = require('postcss-preset-env');

const devMode = false;

module.exports = {
  mode: devMode ? 'development' : 'production',
  entry: [
      './src/js/app.js',
      './src/scss/site.scss'      // file nguồn  CSS
    ],

  output: {
    filename: 'app.min.js',
    path: path.resolve(__dirname, 'dist'),
    library: 'mylib',
    libraryTarget: 'var',
  },


  module: {
    rules: [
        {
          // Thiết lập build scss
          test: /\.(sa|sc)ss$/,
          use: [
              {
                  loader: MiniCssExtractPlugin.loader
              },
              {
                  // Interprets CSS
                  loader: 'css-loader',
                  options: {
                      importLoaders: 2
                  }
              },
              {
                  // minify CSS và thêm autoprefix
                  loader: 'postcss-loader',
                  options: {
                      ident: 'postcss',

                      // Đặt chế độ tối ưu
                      plugins: devMode
                          ? () => []
                          : () => [
                              postcssPresetEnv({
                                  browsers: ['>1%']
                              }),
                              require('cssnano')()
                          ]
                  }
              },
              {
                  loader: 'sass-loader'
              }
          ]
        },
        {
            // Thiết lập lưu các ảnh sử dụng bởi CSS
            // lưu dưới đường dẫn images cùng file site.css
            test: /\.(png|jpe?g|gif)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]',
                        // Image sử dụng bởi CSS lưu tại
                        publicPath: '../images',
                        emitFile: false
                    }
                }
            ]
        }
    ]
  },

plugins: [
  // Xuất kết quả với CSS - sau khi qua loader MiniCssExtractPlugin.loader
  new MiniCssExtractPlugin({
      filename: devMode ? 'css/site.css' : 'css/site.min.css'
  })
]
};

Giờ thì khi build bằng Webpack nó sẽ biên dịch SCSS cho bạn. Thử kiểm tra bằng cách soạn mã nguồn site.scss - giả sử có biên dịch cả bootstrap.

Cài đặt bootstrap

npm install bootstrap

Mở file site.scss cập nhật

//Gộp Bootstrap
// Có thể thiết lập các biến biến như màu $warning ...
@import '../../node_modules/bootstrap/scss/bootstrap.scss';

.bigsize {
    font-size: 60px;
    font-weight: normal;
    line-height: 65px;
  }

Giờ hãy chạy lệnh để xem kết quả: nmp run webpack

Loader với Webpack

Loader là cách chỉ ra cho Webpack xử lý loại file củ thể, cấu hình cần tối thiểu chỉ ra

  • test chỉ ra loại file cần chuyển đổi
  • use các loader sử dụng cho file đó
const path = require('path');

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/,
        use: [
                {loader: "loader1"},
                {loader: "loader2"}
             ]
      }
    ]
  }
};

Các loader thực hiện từ dưới lên trên, như ở ví dụ trên đối với file CSS nó sẽ chuyển đổi dần qua các loader: sass-loader -> postcss-loader -> css-loader -> MiniCssExtractPlugin.loader

Copy file với copy-webpack-plugin

Nếu muốn copy khi chạy Webpack, hãy cài đặt copy-webpack-plugin

npm install copy-webpack-plugin

Sau đó ở file webpack.config.js nạp plugin này vào và cấu hình copy, ví dụ (những đoạn mã thêm vào):

/..
const CopyPlugin = require('copy-webpack-plugin');
/..
module.exports = {
   /..
plugins: [
  /..
  new CopyPlugin([
    { from: 'node_modules/bootstrap/dist/js/bootstrap.js', to: 'js/bootstrap.js' },
    { from: 'node_modules/bootstrap/dist/js/bootstrap.min.js', to: 'js/bootstrap.min.js' },
  ]),
]
};

Đăng ký nhận bài viết mới