使用 Webpack 构建 TypeScript 开发环境
对应代码:https://github.com/EsunR/webpack-playground/tree/main/templates/html-ts
准备 TypeScript 环境
首先安装 TypeScript:
1
| pnpm install typescript -D
|
然后生成 tsconfig.json 配置文件:
1 2 3 4
| pnpm exec tsc --init
npx tsc --init
|
这时候根目录就会生成 tsconfig.json
文件,这个文件是 TypeScript 的配置文件,我们可以在这个文件中配置 TypeScript 的编译选项,我们调整如下几个选项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { "compilerOptions": { "target": "ES5", "module": "CommonJS", "moduleResolution": "node10", "baseUrl": "./", "paths": { "@/*": ["src/*"] }, "allowJs": true, "outDir": "./dist" } }
|
之后我们将 webpack.config.js
修改为 webpack.config.ts
,并将代码规范修改为 ESM,这样就可以编写有 TypeScript 提示的 webpack 配置了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import path from 'path';
import type { Configuration as WebpackConfiguration } from 'webpack';
import 'webpack-dev-server';
const isDev = process.env.NODE_ENV !== 'production';
const config: WebpackConfiguration = { mode: isDev ? 'development' : 'production', devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map', entry: path.resolve(__dirname, './src/main.ts'), output: { path: path.resolve(__dirname, './dist'), clean: true, }, };
export default config;
|
然后修改启动脚本:
1 2 3 4 5 6 7 8
| { "scripts": { - "dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.js", + "dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.ts", - "build": "cross-env NODE_ENV=production webpack --config webpack.config.js" + "build": "cross-env NODE_ENV=production webpack --config webpack.config.ts" } }
|
执行构建指令后会报错,这是因为我们只安装了 typescript 环境,但是如果想让 webpack 执行 TypeScript 的配置文件还需要 TypeScript 的运行执行指令,因此我们需要安装 ts-node,ts-node 可以让我们在直接运行 ts 代码而不需要编译成 js:
之后,webpack 就可以成功执行 TypeScript 编写的 webpack 配置文件了。
添加 ts-loader
准备完环境后,我们将 js 代码修改为 ts 代码后,webpack 会报错,这是因为 webpack 默认只能处理 js 代码,如果要处理 ts 代码,需要添加对应的 loader,这里我们使用 ts-loader 来处理 ts 代码:
1
| pnpm install ts-loader -D
|
向 webpack.config.ts
中添加对应的 loader,同时要让 webpack 支持 ts 模块的解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const config: WebpackConfiguration = { module: { rules: [ { test: /\.tsx?$/i, use: [ { loader: 'ts-loader', options: { configFile: path.resolve(__dirname, './tsconfig.json'), }, }, ], exclude: /node_modules/, }, ], }, resolve: { alias: { }, extensions: ['.js', '.ts', '.tsx'], }, };
|
除了 ts—loader,因为项目中使用了 babel,还可以使用 babel-loader 结合 @babel/preset-typescript 来处理 ts,但是这样不支持类型检查,这里不再做演示。
另外,如果追求编译速度,可以使用 esbuild 或者使用 swc 替换 babel。
处理静态资源模块
当引用静态资源时,ts 会报类型错误。
这是因为 ts 无法识别我们导入的静态资源模块,通过编写类型声明文件可以解决这个问题。在 src
目录下创建 types
文件夹,并新建 static.d.ts
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| declare module '*.css' { const classes: { readonly [key: string]: string }; export default classes; }
declare module '*.png' { const url: string; export default url; }
declare module '*.jpg' { const url: string; export default url; }
declare module '*.jpeg' { const url: string; export default url; }
declare module '*.gif' { const url: string; export default url; }
declare module '*.svg' { const url: string; export default url; }
declare module '*.webp' { const url: string; export default url; }
|
这样,引入静态资源模块时,ts 就不会报类型错误的问题了。
ts-loader 结合 babel-loader
参考:《在 Webpack 中同时使用 ts-loader 和 babel-loader》