TypeScript

TypeScript 是 JavaScript 的一个类型化超集,可以编译为纯 JavaScript。在本指南中,我们将学习如何将 TypeScript 与 webpack 集成。

基础设置

首先,通过运行以下命令安装 TypeScript 编译器和加载器:

npm install --save-dev typescript ts-loader

现在,我们将修改目录结构 & 配置文件

项目

  webpack-demo
  |- package.json
  |- package-lock.json
+ |- tsconfig.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
    |- index.js
+   |- index.ts
  |- /node_modules

tsconfig.json

让我们设置一个配置来支持 JSX 并将 TypeScript 编译为 ES5...

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node"
  }
}

请参阅 TypeScript 文档 以了解更多关于 tsconfig.json 配置选项的信息。

要了解更多关于 webpack 配置的信息,请参阅 配置概念

现在,让我们配置 webpack 来处理 TypeScript

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'),
  },
};

这将指示 webpack 通过 ./index.ts 进入,通过 ts-loader 加载所有 .ts.tsx 文件,并在当前目录中输出一个 bundle.js 文件。

现在,我们来修改 ./index.tslodash 的导入方式,因为 lodash 定义中没有默认导出。

./index.ts

- import _ from 'lodash';
+ import * as _ from 'lodash';

  function component() {
    const element = document.createElement('div');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    return element;
  }

  document.body.appendChild(component());

webpack.config.ts 中使用 TypeScript 的方法

webpack.config.ts 中有 5 种使用 TypeScript 的方法

  1. 将 webpack 与 TypeScript 配置一起使用

    webpack -c ./webpack.config.ts

    (由于 rechoirinterpret 的限制,并非所有功能都受支持。)

  2. 为 Node.js 使用自定义 --import

    NODE_OPTIONS='--import tsx'  webpack --disable-interpret -c ./webpack.config.ts
  3. 在 Node.js v22.7.0 及更高版本(但低于 v23.6.0)中使用内置 TypeScript 模块

    NODE_OPTIONS='--experimental-strip-types' webpack --disable-interpret -c ./webpack.config.ts
  4. 在 Node.js v22.6.0 及更高版本中使用内置 TypeScript 模块

    webpack --disable-interpret -c ./webpack.config.ts
  5. 在 Node.js v22.6.0 及更高版本中使用 tsx

    NODE_OPTIONS='--no-experimental-strip-types --import tsx' webpack --disable-interpret -c ./webpack.config.ts

加载器

ts-loader

本指南使用 ts-loader,因为它使得启用额外的 webpack 功能(例如导入其他 web 资源)变得更容易。

请注意,如果您已经在使用 babel-loader 来转译您的代码,则可以使用 @babel/preset-typescript 并让 Babel 处理您的 JavaScript 和 TypeScript 文件,而不是使用额外的加载器。请记住,与 ts-loader 不同,底层的 @babel/plugin-transform-typescript 插件不执行任何类型检查。

源码映射

要了解更多关于源码映射的信息,请参阅 开发指南

要启用源码映射,我们必须配置 TypeScript 将内联源码映射输出到我们编译后的 JavaScript 文件中。以下行必须添加到我们的 TypeScript 配置中:

tsconfig.json

  {
    "compilerOptions": {
      "outDir": "./dist/",
+     "sourceMap": true,
      "noImplicitAny": true,
      "module": "commonjs",
      "target": "es5",
      "jsx": "react",
      "allowJs": true,
      "moduleResolution": "node",
    }
  }

现在我们需要告诉 webpack 提取这些源码映射并将其包含在我们的最终打包中

webpack.config.js

  const path = require('path');

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

有关更多信息,请参阅 devtool 文档

客户端类型

您可以在 TypeScript 代码中使用 webpack 特有的功能,例如 import.meta.webpack。webpack 也为其提供了类型定义,添加一个 TypeScript reference 指令来声明它

/// <reference types="webpack/module" />
console.log(import.meta.webpack); // without reference declared above, TypeScript will throw an error

使用第三方库

从 npm 安装第三方库时,请务必安装该库的类型定义。

例如,如果我们要安装 lodash,可以运行以下命令来获取其类型定义:

npm install --save-dev @types/lodash

如果 npm 包已在其打包中包含其声明类型定义,则无需下载相应的 @types 包。有关更多信息,请参阅 TypeScript 更新日志博客

导入其他资源

要将非代码资源与 TypeScript 一起使用,我们需要为这些导入推迟类型。这需要一个 custom.d.ts 文件,它表示我们项目中 TypeScript 的自定义定义。让我们为 .svg 文件设置一个声明:

custom.d.ts

declare module '*.svg' {
  const content: any;
  export default content;
}

在这里,我们通过指定任何以 .svg 结尾的导入,并将模块的 content 定义为 any,来声明一个用于 SVG 的新模块。我们可以通过将类型定义为字符串来更明确地表示它是一个 URL。相同的概念适用于其他资源,包括 CSS、SCSS、JSON 等。

构建性能

请参阅关于构建工具的 构建性能 指南。

7 贡献者

morsdycekkamalimtriverabyzykEugeneHlushkochenxsansnitin315