TypeScript与webpack

项目中的 TypeScript 源代码不会全部放在一个文件中,我们会根据组件、模块和功能等将源代码划分到不同的文件。在发布一个项目时,尤其 Web 前端应用,通常需要使用打包工具对源文件进行打包合并。使用打包工具至少有以下几个原因:

  • 由于运行环境(浏览器)中不支持 TypeScript 代码中使用的模块格式(ES 模块),因此会导致无法加载代码。打包工具能够解析模块间的依赖关系并将多个模块文件合并为运行环境能够直接加载的单一文件。

  • 在浏览器环境中减少加载的资源文件数量能够显著提升 Web 应用的性能。如果使用打包工具将多文件合并为一个文件,那么浏览器只需加载一个文件即可。

在本节中,将通过一个示例来演示如何使用 webpack 工具来打包合并 TypeScript 代码。

webpack

webpack 是一个流行的 JavaScript 应用打包器。webpack 的主要用途是将多个 JavaScript 文件打包成一个或多个 JavaScript 文件。除此之外,webpack 还能够打包其他类型的资源文件,如图片和 CSS 等。

实例演示

本节将通过一个简单的例子来演示如何将 TypeScript 与 webpack 结合使用。此例中,web-pack 负责将多个 TypeScript 源文件打包合并为一个单独的 JavaScript 文件,具体如图9-4所示。

image 2024 02 07 23 26 22 389
Figure 1. 图9-4 TypeScript与webpack

与配置 Babel 的前四步相同,我们需要安装 Node.js 和 TypeScript 并且初始化工程。

假设当前工程的目录结构如下:

C:\ts-webpack
|-- node_modules
|   |-- <省略了一部分代码包>
|   `-- typescript
|-- package.json
|-- package-lock.json
`-- tsconfig.json

package.json 文件的内容如下:

{
    "name": "ts-webpack",
    "version": "1.0.0",
    "devDependencies": {
        "typescript": "^3.8.2"
    }
}

tsconfig.json 文件的内容如下:

{
    "compilerOptions": {
        "target": "ES6",
        "strict": true,
        "outDir": "dist"
    }
}

添加TypeScript文件

为了演示 webpack 的打包功能,我们新建两个模块文件。在 C:\ts-webpack 目录下创建一个 src 文件夹并添加 index.tsutils.ts 文件。

当前工程的目录结构如下:

C:\ts-webpack
|-- node_modules
|   |-- <省略了一部分代码包>
|   `-- typescript
|-- src
|   |-- index.ts
|   `-- utils.ts
|-- package.json
|-- package-lock.json
`-- tsconfig.json

utils.ts 文件的内容如下:

export function add(x: number, y: number) {
    return x + y;
}

index.ts 使用了 utils.ts 中导出的 add 函数,index.ts 文件的内容如下:

import { add } from './utils';

const total = add(1, 2);

console.log(total);

安装webpack

在 C:\ts-webpack 目录下,运行如下命令来安装 webpack 及相关工具:

npm install --save-dev webpack webpack-cli ts-loader

此时,C:\ts-webpack 目录的结构如下:

C:\ts-webpack
|-- node_modules
|   |-- <省略了一部分代码包>
|   |-- ts-loader
|   |-- typescript
|   |-- webpack
|   `-- webpack-cli
|-- src
|   |-- index.ts
|   `-- utils.ts
|-- package.json
|-- package-lock.json
`-- tsconfig.json

配置webpack

在默认情况下,webpack 会使用 webpack.config.js 作为配置文件。在 C:\ts-webpack 目录下创建一个 webpack.config.js 文件,它的内容如下:

const path = require('path');

module.exports = {
    entry: './src/index.ts',
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js']
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
};

在该配置文件中,entry 属性用来配置入口的模块文件,webpack 将搜索该模块文件直接或间接依赖的其他模块文件,并将此依赖关系保存在一种称作 依赖图 的数据结构中。

module.rules 属性用来配置文件加载器,文件加载器定义了如何解析一个文件以及如何打包该文件。webpack 从 依赖图 中读取要加载的文件,然后根据文件的类型选择对应的文件加载器。webpack 内置了 JavaScript 文件和 JSON 文件的加载器,若想要打包其他类型的文件,则必须安装和配置使用的加载器。此例中,我们想要让 webpack 能够打包 TypeScript 文件,因此必须安装能够处理 TypeScript 文件加载器。其中:

  • test 属性定义了在哪些文件上使用 ts-loader 文件加载器。此例中,使用正则表达式匹配了以 .ts.tsx 结尾的文件。

  • use 属性定义了文件加载器的名字。此例中,使用的是前面安装的 ts-loader 文件加载器。

resolve.extensions 属性定义了在文件名相同但文件扩展名不同时选择文件的优先级,第一个数组元素的优先级最高。例如,若同时存在 utils.tsutils.js 文件,将优先使用 index.ts 文件。

output 属性定义了打包生成的文件名及存放的位置。此例中,将打包生成的 bundle.js 存放在 C:\ts-webpack\dist 目录下。

现在,C:\ts-webpack 目录的结构如下:

C:\ts-webpack
|-- node_modules
|   |-- <省略了一部分代码包>
|   |-- ts-loader
|   |-- typescript
|   |-- webpack
|   `-- webpack-cli
|-- src
|   |-- index.ts
|   `-- utils.ts
|-- package.json
|-- package-lock.json
|-- tsconfig.json
`-- webpack.config.js

运行webpack

在 C:\ts-webpack 目录下运行 webpack 命令来打包文件,示例如下:

npx webpack

运行 webpack 命令会在 C:\ts-webpack\dist 目录下生成打包后的文件,示例如下:

C:\ts-webpack
|-- dist
|   `-- bundle.js
|-- node_modules
|   |-- <省略了一部分代码包>
|   |-- ts-loader
|   |-- typescript
|   |-- webpack
|   `-- webpack-cli
|-- package.json
|-- package-lock.json
|-- src
|   |-- index.ts
|   `-- utils.ts
|-- tsconfig.json
`-- webpack.config.js

运行打包后的 bundle.js 文件能够输出数字 3,因为我们在 index.ts 中使用了 utils.ts 提供的 add 函数来计算并打印 1+2 的值。示例如下:

node dist/bundle.js

最后,我们将 webpack 命令添加为 npm 脚本。在 package.json 文件的 scripts 属性中定义一个 bundle 脚本,示例如下:

{
    "name": "ts-webpack",
    "version": "1.0.0",
    "scripts": {
        "bundle": "webpack"
    },
    "devDependencies": {
        "ts-loader": "^6.2.1",
        "typescript": "^3.8.2",
        "webpack": "^4.41.6",
        "webpack-cli": "^3.3.11"
    }
}

现在可以通过 npm run 命令来运行该脚本,示例如下:

npm run bundle

小结

webpack 是一个十分流行且功能强大的 JavaScript 应用打包器,它支持自定义的文件加载器和插件来实现复杂场景下的打包工作。除了本节演示的基本功能外,webpack 还能够进行代码优化等工作。在实际项目中,像 webpack 这类的打包工具是必不可少的。