We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
目前 TypeScript 基本上是前端项目的标配了,所以这一篇介绍如何在项目内集成 TypeScript。
要在项目内使用 TypeScript,肯定得选择编译器和编译方式。
TypeScript
鉴于我们已经在项目内使用了 Babel,并且 TypeScript 官方也推荐使用 Babel,所以我们直接选用 @babel/preset-typescript 进行编译。同时,只使用一个编译工具也使项目配置更加容易,不用维护多个工具的配置文件。
Babel
@babel/preset-typescript
关于 @babel/preset-typescript 的由来,可以参见 [译] TypeScript 牵手 Babel:一场美丽的婚姻。
A. 安装编译所需依赖:
yarn add @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread -D
@babel/preset-typescript 是 Babel 编译 TypeScript 所需的预设,@babel/plugin-proposal-class-properties 和 @babel/plugin-proposal-object-rest-spread 是用于编译尚在提议阶段的语法,具体介绍可点击下面的链接查看。
@babel/plugin-proposal-class-properties
@babel/plugin-proposal-object-rest-spread
B. 安装类型检查所需依赖:
yarn add @types/react @types/react-dom
这两个包是对于 react 和 react-dom 的类型声明,如果不安装,编辑器会有相应的类型缺失的提示,类似的如果我们使用其他的库,比如说 lodash,可以查看是否有对应的 @types/loadsh 包,如果没有就需要自己写类型声明文件。
react
react-dom
lodash
@types/loadsh
C.修改 webpack.config.js
webpack.config.js
const path = require('path'); module.exports = { mode: 'development', entry: './src/index.tsx', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, devServer: { contentBase: './dist', }, resolve: { extensions: ['.tsx', '.ts', '.js'], }, module: { rules: [ { test: /\.(ts|js)x?$/, exclude: /node_modules/, loader: 'babel-loader', }, ], }, };
相对于之前的配置文件,entry 字段做了修改,添加了 extensions 字段,用于 import 的时候不用写文件的扩展名称。
entry
extensions
import
test 字段做了修改,目前表示匹配 .ts、.tsx、.js 和 .jsx 文件。
test
.ts
.tsx
.js
.jsx
删除了 use 字段,使用了 loader 字段,将 loader 的配置移到了专门的配置文件。
use
loader
D. 配置 babel-loader
babel-loader
新增 .babelrc 文件
.babelrc
{ "presets": [ "@babel/preset-env", "@babel/preset-typescript" "@babel/preset-react", ], "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread" ] }
.babelrc 文件是 babel 的配置文件,用于配置其所使用的插件和预设。
babel
E. 配置 TypeScript 的编译选项
新增 tsconfig.json 文件
tsconfig.json
{ "compilerOptions": { "allowSyntheticDefaultImports": true, "noFallthroughCasesInSwitch": true, "noUnusedParameters": true, "noImplicitReturns": true, "moduleResolution": "node", "esModuleInterop": true, "noUnusedLocals": true, "noImplicitAny": true, "target": "ESNext", "module": "ESNext", "strict": true, "jsx": "react-jsx", "noEmit": true, "allowJs": true }, "include": [ "src/**/*" ], "exclude": [ "node_modules", "dist" ] }
tsconfig.json 的配置项特别多,全部配置的解释可以查看这个文档。
allowJs
默认为 false,表示是否允许使用 .js 文件,设置为 true 可以让 .js 和 .ts 共存,方便对旧项目进行逐步迁移。
false
F. 修改代码
将 index.js 重命名为 index.tsx,内容不变
index.js
index.tsx
import React from 'react'; import ReactDOM from 'react-dom'; import App from './app'; ReactDOM.render( <App />, document.getElementById('root') );
将 app.js 重命名为 app.tsx,修改内容为如下
app.js
app.tsx
import React from 'react'; const App = () => { const title: string = 'A beautiful page!'; return ( <h2>{title}</h2> ) } export default App;
G. 查看效果
执行 yarn dev,效果如下
yarn dev
写过 React 项目的都知道,只要在文件内使用了 jsx,那文件必须得引入 React, 也就是 import React from 'react'。
jsx
React
import React from 'react'
每个文件都要导入一遍,就显得非常啰嗦和繁琐。
A. 为什么只要使用了 jsx,就要导入 React 呢?
因为浏览器并不能直接理解 jsx 代码,在编译打包的时候,jsx 代码实际上编译成了函数调用的代码,比如
import React from 'react'; function App() { return <h1>Hello World</h1>; }
|| 编 || 译 v 成
import React from 'react'; function App() { return React.createElement('h1', null, 'Hello world'); }
所以,React 必须导入到当前作用域。
B. React 17 之后,可以不用再导入 React 了。
React 17
注意:TypeScript 从 4.1 开始支持。
修改 .babelrc,给 @babel/preset-react 添加配置
@babel/preset-react
{ "presets": [ "@babel/preset-env", [ "@babel/preset-react", { "runtime": "automatic" } ], "@babel/preset-typescript" ], "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread" ] }
修改 tsconfig.js,将 jsx 的值从 react 修改为 react-jsx。
tsconfig.js
react-jsx
最后删除代码中的 import React from 'react',会发现 vscode 自身的 TypeScript 语法检查没有报错,项目也照常运行。
开启这个特性后,上面同样的源代码会被编译成:
// 这行代码由 babel 等编译器自动插入,不要手动改添加!!! import {jsx as _jsx} from 'react/jsx-runtime'; function App() { return _jsx('h1', { children: 'Hello world' }); }
实际上,同样是被编译成函数调用,只是编译器默认帮我们做了这件事,并且新增了运行时函数 jsx 提供给编译器使用。
对于这个特性,具体介绍参见 介绍全新的 JSX 转换。
目前为止,项目已经可以编译运行 TypeScript 代码了,但是还没有类型检查的功能。
因为 Babel 只负责对代码进行编译,并不会进行类型检查,参考 Using Babel with TypeScript。
虽然现在的编辑器比如 vscode 自带有类型检查功能,但是有一定局限性,只能在代码编写阶段给我们提示,如果想要在代码提交前以及持续集成的时候进行检查,那必须得添加专门的工具和检查配置。
vscode
A. 使用 TypeScript 进行代码检查
首先,安装 TypeScript。 yarn add typescript -D
yarn add typescript -D
然后添加检查命令到 package.json 的 scripts 字段下。
package.json
scripts
"scripts": { "type-check": "tsc", "build": "webpack", "dev": "webpack serve" },
然后,手动在 app.tsx 文件添加一个错误,测试代码检查是否生效。
const App = () => { const title: string = 'A beautiful page!'; // 声明 desc,但不使用 const desc = 'Beautiful'; return ( <h2>{title}</h2> ) } export default App;
因为我们在 tsconfig.json 中设置了 noUnusedLocals 为 true,所以理论上,上面添加的代码不能通过代码检查。
noUnusedLocals
true
运行 yarn type-check,结果如下
yarn type-check
可以看到,代码检查命令生效了。
yarn type-check 命令同样使用的是根目录下的 tsconfig.js 配置文件。
B. git commit 前自动检查修改的代码文件
git commit
上面添加的命令需要我们手动运行,在团队协作的时候,一般都会在代码提交前自动运行代码检查,强制对每个修改的文件进行检查,检查通过后 git commit 命令才会真正开始执行,否则代码将会一直处于暂存区,不会进入代码库。
为了达到这个效果,我们需要安装两个工具:husky 和 lint-staged。
husky
lint-staged
husky:用于操作 git hook,我们可以使用这个工具非常方便地编写自定义命令和脚本,husky 会在我们指定的时机执行。目前,husky 的最新版本是 5,但是这里我们使用 4,github 地址。
git hook
lint-staged:用于对处于暂存区的代码执行各种操作,github 地址。
首先安装依赖
yarn add [email protected] lint-staged -D
修改 package.json
{ // ... "scripts": { "type-check": "tsc", "type-check-pre-commit": "bash -c tsc", "build": "webpack", "dev": "webpack serve" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{ts,tsx}": [ "yarn type-check-pre-commit" ] }, // ... }
我们新增了命令 type-check-pre-commit
type-check-pre-commit
所以,假如我们修改了代码,通过 git add . 将代码添加到暂存区
git add .
然后执行 git commit -m "fix bugs" 的时候,就会触发上面添加的 pre-commit 钩子
git commit -m "fix bugs"
pre-commit
从而会执行 lint-staged 命令
然后 lint-staged 会将本次修改的 .ts 和 .tsx 文件筛选出来作为参数传递给 type-check-pre-commit 命令执行
最后就会使用 tsc 对其进行检查,如果检查失败就会终止 commit 命令
tsc
commit
修改代码再次 commit 直至检查通过后,commit 才会成功,代码才会真正进入代码库
至于上面为什么会写成 bash -c tsc,可以参考这个 issue,主要是为了在自动执行 type-check-pre-commit 命令的时候,能够让 ts 编译器使用项目根目录下的 tsconfig.json 文件。
bash -c tsc
ts
webpack-react-spa-template-project
The text was updated successfully, but these errors were encountered:
lint-staged bash -c tsc 好像不太好使,依然会检查所有的代码,并不是 staged 的
lint-staged bash -c tsc
Sorry, something went wrong.
我这里可以,估计是环境差异,看看 lint-staged/lint-staged#468 这个有答案不
不知道,后来我用这个包来做的 https://github.com/gustavopch/tsc-files
No branches or pull requests
选择编译器
要在项目内使用
TypeScript
,肯定得选择编译器和编译方式。鉴于我们已经在项目内使用了
Babel
,并且TypeScript
官方也推荐使用Babel
,所以我们直接选用@babel/preset-typescript
进行编译。同时,只使用一个编译工具也使项目配置更加容易,不用维护多个工具的配置文件。关于
@babel/preset-typescript
的由来,可以参见 [译] TypeScript 牵手 Babel:一场美丽的婚姻。安装
A. 安装编译所需依赖:
yarn add @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread -D
@babel/preset-typescript
是Babel
编译TypeScript
所需的预设,@babel/plugin-proposal-class-properties
和@babel/plugin-proposal-object-rest-spread
是用于编译尚在提议阶段的语法,具体介绍可点击下面的链接查看。B. 安装类型检查所需依赖:
yarn add @types/react @types/react-dom
这两个包是对于
react
和react-dom
的类型声明,如果不安装,编辑器会有相应的类型缺失的提示,类似的如果我们使用其他的库,比如说lodash
,可以查看是否有对应的@types/loadsh
包,如果没有就需要自己写类型声明文件。C.修改
webpack.config.js
相对于之前的配置文件,
entry
字段做了修改,添加了extensions
字段,用于import
的时候不用写文件的扩展名称。test
字段做了修改,目前表示匹配.ts
、.tsx
、.js
和.jsx
文件。删除了
use
字段,使用了loader
字段,将loader
的配置移到了专门的配置文件。D. 配置
babel-loader
新增
.babelrc
文件.babelrc
文件是babel
的配置文件,用于配置其所使用的插件和预设。E. 配置
TypeScript
的编译选项新增
tsconfig.json
文件tsconfig.json
的配置项特别多,全部配置的解释可以查看这个文档。allowJs
默认为
false
,表示是否允许使用.js
文件,设置为 true 可以让.js
和.ts
共存,方便对旧项目进行逐步迁移。F. 修改代码
将
index.js
重命名为index.tsx
,内容不变将
app.js
重命名为app.tsx
,修改内容为如下G. 查看效果
执行
yarn dev
,效果如下删除
写过 React 项目的都知道,只要在文件内使用了
jsx
,那文件必须得引入React
, 也就是import React from 'react'
。每个文件都要导入一遍,就显得非常啰嗦和繁琐。
A. 为什么只要使用了
jsx
,就要导入React
呢?因为浏览器并不能直接理解
jsx
代码,在编译打包的时候,jsx
代码实际上编译成了函数调用的代码,比如|| 编
|| 译
v 成
所以,
React
必须导入到当前作用域。B.
React 17
之后,可以不用再导入React
了。注意:
TypeScript
从 4.1 开始支持。修改
.babelrc
,给@babel/preset-react
添加配置修改
tsconfig.js
,将jsx
的值从react
修改为react-jsx
。最后删除代码中的
import React from 'react'
,会发现 vscode 自身的TypeScript
语法检查没有报错,项目也照常运行。开启这个特性后,上面同样的源代码会被编译成:
实际上,同样是被编译成函数调用,只是编译器默认帮我们做了这件事,并且新增了运行时函数
jsx
提供给编译器使用。对于这个特性,具体介绍参见 介绍全新的 JSX 转换。
添加类型检查
目前为止,项目已经可以编译运行
TypeScript
代码了,但是还没有类型检查的功能。因为
Babel
只负责对代码进行编译,并不会进行类型检查,参考 Using Babel with TypeScript。虽然现在的编辑器比如
vscode
自带有类型检查功能,但是有一定局限性,只能在代码编写阶段给我们提示,如果想要在代码提交前以及持续集成的时候进行检查,那必须得添加专门的工具和检查配置。A. 使用
TypeScript
进行代码检查首先,安装
TypeScript
。yarn add typescript -D
然后添加检查命令到
package.json
的scripts
字段下。然后,手动在
app.tsx
文件添加一个错误,测试代码检查是否生效。因为我们在
tsconfig.json
中设置了noUnusedLocals
为true
,所以理论上,上面添加的代码不能通过代码检查。运行
yarn type-check
,结果如下可以看到,代码检查命令生效了。
yarn type-check
命令同样使用的是根目录下的tsconfig.js
配置文件。B.
git commit
前自动检查修改的代码文件上面添加的命令需要我们手动运行,在团队协作的时候,一般都会在代码提交前自动运行代码检查,强制对每个修改的文件进行检查,检查通过后
git commit
命令才会真正开始执行,否则代码将会一直处于暂存区,不会进入代码库。为了达到这个效果,我们需要安装两个工具:
husky
和lint-staged
。husky
:用于操作git hook
,我们可以使用这个工具非常方便地编写自定义命令和脚本,husky
会在我们指定的时机执行。目前,husky
的最新版本是 5,但是这里我们使用 4,github 地址。lint-staged
:用于对处于暂存区的代码执行各种操作,github 地址。首先安装依赖
修改
package.json
我们新增了命令
type-check-pre-commit
所以,假如我们修改了代码,通过
git add .
将代码添加到暂存区然后执行
git commit -m "fix bugs"
的时候,就会触发上面添加的pre-commit
钩子从而会执行
lint-staged
命令然后
lint-staged
会将本次修改的.ts
和.tsx
文件筛选出来作为参数传递给type-check-pre-commit
命令执行最后就会使用
tsc
对其进行检查,如果检查失败就会终止commit
命令修改代码再次
commit
直至检查通过后,commit
才会成功,代码才会真正进入代码库至于上面为什么会写成
bash -c tsc
,可以参考这个 issue,主要是为了在自动执行type-check-pre-commit
命令的时候,能够让ts
编译器使用项目根目录下的tsconfig.json
文件。代码地址
webpack-react-spa-template-project
参考资料
The text was updated successfully, but these errors were encountered: