TypeScript
好的,我会根据提供的英文源文档,创作一份专业、结构清晰的中文技术教程。以下是教程的正文部分。
TypeScript
本指南源自 起步指南。
TypeScript 是 JavaScript 的类型化超集,可编译为纯 JavaScript。在本指南中,我们将学习如何将 TypeScript 与 webpack 集成。
基本设置
首先,运行以下命令安装 TypeScript 编译器和加载器:
bash
npm install --save-dev typescript ts-loader
现在,我们修改目录结构和配置文件:
项目结构
diff
webpack-demo
├── package.json
├── package-lock.json
+ ├── tsconfig.json
- ├── webpack.config.js
+ ├── webpack.config.ts
├── /dist
│ ├── bundle.js
│ └── index.html
├── /src
- │ ├── index.js
+ │ └── index.ts
└── /node_modules
tsconfig.json
让我们设置一个配置文件,以支持 JSX 并将 TypeScript 编译为 ES5...
json
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "bundler",
"target": "esnext",
"jsx": "react-jsx",
"allowJs": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
欲了解 tsconfig.json 配置选项的更多信息,请参阅 TypeScript 文档。
欲了解 webpack 配置的更多信息,请参阅 配置概念。
现在,让我们配置 webpack 以处理 TypeScript:
首先,安装所需的依赖项:
bash
npm install --save-dev ts-node @types/node
webpack.config.ts
ts
import path from "node:path";
import { fileURLToPath } from "url";
import webpack from "webpack";
// 防止配置 `devServer` 时出现任何 TypeScript 错误
import "webpack-dev-server";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const config: webpack.Configuration = {
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"),
},
};
export default config;
有关如何在 TypeScript 文件 中编写配置的更多信息,请参阅相关文档。
这将指示 webpack 从 ./index.ts 文件_进入_,通过 ts-loader_加载_所有 .ts 和 .tsx 文件,并在当前目录下_输出_一个 bundle.js 文件。
接下来,我们需要调整在 ./index.ts 中导入 lodash 的方式。由于 lodash 的类型定义不包含默认导出,因此我们需要更新导入语句。
首先,确保已安装 TypeScript 定义:
bash
npm install --save-dev @types/lodash
然后,更新文件顶部的导入语句:
./index.ts
diff
- 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());
T> 若要让这些导入默认如此行为,并继续在 TypeScript 中使用 import _ from 'lodash'; 语法,请在 tsconfig.json 文件中设置 "allowSyntheticDefaultImports": true 和 "esModuleInterop": true。这涉及到 TypeScript 的配置,此处提及仅供您参考。
在 webpack.config.ts 中使用 TypeScript 的方法
在 webpack.config.ts 中使用 TypeScript 有三种方式:
-
使用 webpack 内置的 Node.js 类型剥离功能(推荐):
bashwebpack -c ./webpack.config.ts将尝试使用 Node.js 内置的 类型剥离 功能加载配置,然后尝试使用
interpret和rechoir加载配置文件(在这种情况下,您需要安装tsx或ts-node或其他工具)。 -
为 Node.js 使用自定义的
--import/--require:bashNODE_OPTIONS='--import=tsx --no-experimental-strip-types' webpack -c ./webpack.config.tsbashNODE_OPTIONS='--require=ts-node/register --no-experimental-strip-types' webpack -c ./webpack.config.ts从 Node.js 22.7.0 版本开始,需要使用
--no-experimental-strip-types标志。 -
为 Node.js ≥ v22.7.0 使用内置的 Node.js 转换类型功能:
启用需要生成 JavaScript 代码的不可擦除 TypeScript 语法(例如枚举声明、参数属性)的转换。
bashNODE_OPTIONS='--experimental-transform-types' webpack --disable-interpret -c ./webpack.config.ts
TypeScript 路径别名
如果您在 tsconfig.json 中使用 compilerOptions.paths 或 compilerOptions.baseUrl 来创建导入别名,从 webpack 5.105 开始,webpack 可以直接通过 resolve.tsconfig 读取这些别名。这取代了 tsconfig-paths-webpack-plugin,后者不应再被使用。
resolve.tsconfig 接受 boolean | string | object:
webpack.config.ts
js
export default {
resolve: {
tsconfig: true, // 自动查找 tsconfig.json
},
};
传递字符串以指向特定文件(在 monorepo 中很有用):
js
export default {
resolve: {
tsconfig: "./tsconfig.app.json",
},
};
传递一个对象以同时解析 TypeScript 项目引用:
js
export default {
resolve: {
tsconfig: {
configFile: "./tsconfig.json",
references: "auto", // 从 tsconfig 继承引用,或传递路径数组
},
},
};
tsconfig.json
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
通过上述配置,@/components/Button 将解析为 src/components/Button,无需任何额外插件或在 resolve.alias 中重复别名。
从 tsconfig-paths-webpack-plugin 迁移
如果您当前正在使用 tsconfig-paths-webpack-plugin,可以放弃它,转而使用内置的 resolve.tsconfig 选项:
diff
- import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
export default {
resolve: {
- plugins: [new TsconfigPathsPlugin()],
+ // 在项目根目录自动查找 tsconfig.json
+ tsconfig: true,
+
+ // 或显式指定一个
+ // tsconfig: './tsconfig.app.json'
},
};
然后,您可以从项目中移除该包:
bash
npm uninstall tsconfig-paths-webpack-plugin
W> resolve.tsconfig 仅处理模块解析 —— 它不转译 TypeScript。您仍然需要 ts-loader、带有 @babel/preset-typescript 的 babel-loader 或其他转译步骤。
加载器
我们在此指南中使用 ts-loader,因为它可以更容易地启用额外的 webpack 功能,例如导入其他 web 资源。
W> ts-loader 使用 tsc(TypeScript 编译器),并依赖于您的 tsconfig.json 配置。请确保避免将 module 设置为 "CommonJS",否则 webpack 将无法 tree-shake(摇树优化)您的代码。
请注意,如果您已经在使用 babel-loader 来转译代码,您可以使用 @babel/preset-typescript 让 Babel 同时处理您的 JavaScript 和 TypeScript 文件,而无需使用额外的加载器。请记住,与 ts-loader 不同,底层的 @babel/plugin-transform-typescript 插件不执行任何类型检查。
源码映射
要了解有关源码映射的更多信息,请参阅 开发指南。
要启用源码映射,我们必须配置 TypeScript 将内联源码映射输出到我们编译后的 JavaScript 文件中。必须在 TypeScript 配置中添加以下几行:
tsconfig.json
diff
{
"compilerOptions": {
"outDir": "./dist/",
+ "sourceMap": true,
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "bundler",
"target": "esnext",
"jsx": "react-jsx",
"allowJs": true,
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
现在,我们需要告诉 webpack 提取这些源码映射并将其包含在最终的 bundle 中:
webpack.config.ts
diff
import path from "node:path";
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
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 指令来声明它:
ts
/// <reference types="webpack/module" />
console.log(import.meta.webpack); // 如果没有上述引用声明,TypeScript 将抛出错误
要为整个项目启用这些类型,请在 tsconfig.json 的 compilerOptions.types 中添加 webpack/module:
diff
{
"compilerOptions": {
"types": [
+ "webpack/module"
]
}
}
使用第三方库
在从 npm 安装第三方库时,重要的是要记住安装该库的类型定义。
例如,如果我们想使用 lodash,应该运行以下命令来安装其类型定义:
bash
npm install --save-dev @types/lodash
如果 npm 包在其包中已经包含了声明类型,则无需下载相应的 @types 包。欲了解更多信息,请参阅 TypeScript 更新日志博客。
导入其他资源
要将非代码资源与 TypeScript 一起使用,我们需要延迟这些导入的类型。这需要一个 custom.d.ts 文件,它表示我们项目中 TypeScript 的自定义定义。让我们为 .svg 文件设置一个声明:
custom.d.ts
ts
declare module "*.svg" {
const content: any;
export default content;
}
这里我们通过指定任何以 .svg 结尾的导入并定义模块的 content 为 any 来声明一个 SVG 新模块。我们可以通过将类型定义为字符串来更明确地表明它是一个 URL。同样的概念也适用于其他资源,包括 CSS、SCSS、JSON 等。
构建性能
W> 这可能会降低构建性能。
有关构建工具的更多信息,请参阅 构建性能 指南。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
