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 文件。

现在,由于 lodash 定义中没有默认导出,让我们更改 ./index.tslodash 的导入。

./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());

加载器

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 结尾的任何导入并定义模块的 contentany 来声明一个新的 SVG 模块。我们可以通过将类型定义为字符串来更明确地说明它是 URL。同样的概念也适用于其他资产,包括 CSS、SCSS、JSON 等等。

构建性能

请参阅 构建性能 指南了解构建工具。

7 位贡献者

morsdycekkamalimtriverabyzykEugeneHlushkochenxsansnitin315