Webpack是JavaScript的模組建置工具,運行在Node.js上,它可以將零散的JavaScript檔案用各式工具優化並打包起來,加快網頁的載入時間。Webpack也並不限於用在JavaScript上,它除了還能打包網頁有用到的靜態資源(如JS、CSS、圖片檔等)外,也還能透過TypeScript的載入器(loader)來編譯並打包TypeScript程式碼。



背景知識

在開始閱讀這篇文章之前,您應該要先對TypeScript程式語言和Webpack打包檔案的方式有所了解。可以先閱讀以下幾篇文章:

TypeScript 學習之路系列文章:

用Webpack來打包JavaScript、SCSS/CSS、HTML網頁和任意檔案:

用了TypeScript還需要用Webpack嗎?

TypeScript是一種能用來編譯出JavaScript程式碼的程式語言,它「本身」並沒有將多個TypeScript模組編譯為一個JavaScript的功能,必須要依靠System(SystemJS)或是AMD(Asynchronous Module Definition)模組系統來整合到同一個JavaScript檔案上。

例如以下的TypeScript程式:

console.log("A");
export default function print() {
    console.log("B");
}
import "./a";
import print from "./b";

print();

我們可以在tsconfig.json設定檔中的compilerOptions欄位內加上outFile欄位來讓TypeScript在編譯TypeScript時將JavaScript程式碼輸出到同一個JavaScript檔案中。此時compilerOptions欄位內的module欄位要設定為System或是AMD,也就是說,編譯出來的JavaScript檔案必須要運作在System和AMD的Runtime上(如果是要把該JavaScript檔案放在網頁瀏覽器上執行,就需要引用額外的JavaScript套件)。但如果我們是在Webpack下用TypeScript撰寫相同的程式,就不用受到模組系統的限制,自在地使用ES6的模組系統。

另外還有一點就是,TypeScript的編譯器並無法幫我們最小化並混淆編譯出來的JavaScript程式,但Webpack可以做到這件事。

所以,如果您的TypeScript程式所編譯出來的JavaScript程式也要用於網頁瀏覽器上,最好還是用Webpack來打包。

建立TypeScript的Webpack專案

加入Webpack

Webpack可以被加進現有的TypeScript的Node.js專案中,在終端機執行以下指令來安裝webpackwebpack-cli這兩個套件。

npm i -D webpack webpack-cli

然後編輯package.json中的腳本指令,如下:

{
  ...

  "scripts": {
    ...

    "ts-build": "tsc",
    "ts-build:watch": "tsc -w",
    "build": "webpack --mode production",
    "build:dev": "webpack --mode development",
    "build:watch": "webpack --mode development --watch"

    ...
  }
  
  ...
}

在撰寫TypeScript程式時,可以執行npm run ts-build:watch來持續監看並即時編譯TypeScript的程式碼。如果需要同時進行打包的話,可以改為執行npm build:watch,讓TypeScript的程式碼一有更動就自動重新打包。

再來就是在Node.js專案根目錄中,新增Webpack的設定檔webpack.config.js,內容可以初始如下:

module.exports = {
    plugins: [],
    module: { rules: [] },
    resolve: { extensions: [".ts", ".js"] },
};

resolve: { extensions: [".ts", ".js"] }可以讓Webpack看到無副檔名的檔案路徑時,先以.ts作為副檔名來嘗試,如果不存在,再以.js來嘗試。Webpack預設的輸出目錄為專案根目錄下的dist目錄,如果您的Typescript原先也是輸出到這個目錄的話,要換成別的。

加入TypeScript載入器

TypeScript的官方載入器為ts-loader,可以在終端機執行以下指令來安裝:

npm i -D ts-loader

webpack.config.js設定檔中,於module欄位的rules陣列內,加入TypeScript的載入器規則,如下:

module.exports = {
    ...

    module: {
        rules: [
            ...

            {
                test: /\.ts$/i,
                loader: "ts-loader"
            }

            ...
        ]
    }

    ...
};

設定Webpack的進入點(Entry Point)

直接使用TypeScript檔案作為Webpack的進入點。例如:

module.exports = {
    ...

    entry: "./src/index.ts"

    ...
};

與Babel一同使用

在終端機執行以下指令來安裝Babel:

npm i -D babel-loader @babel/core @babel/preset-env @babel/register

webpack.config.js設定檔中,於module欄位的rules陣列內,加入Babel的載入器規則,如下:

module.exports = {
    ...

    module: {
        rules: [
            ...

            {
                test: /\.ts$/i,
                use: [
                    {
                        loader: "babel-loader",
                        options: { presets: ["@babel/preset-env"] },
                    },
                    "ts-loader",
                ],
            },
            {
                test: /\.js$/i,
                use: {
                    loader: "babel-loader",
                    options: { presets: ["@babel/preset-env"] },
                },
            }

            ...
        ]
    }

    ...
};