优雅地使用TypeScript开发React Native应用

5,885 阅读5分钟

React Native 0.57 版本开始,我们终于可以直接使用 TypeScript 开发,不需要任何额外的配置。本文主要介绍如何使用 TypeScript 优雅地开发 React Native 应用。

一、初始化项目

初始化项目之前,请确保已经按照 React Native 中文网 的搭建开发环境文档完成了环境搭建

$ react-native init AwesomeProject

注意: 入口文件 index.js 需要保留,其他文件都可以使用 .ts.tsx 后缀。

二、TypeScript 编译器

$ yarn global add typescript
$ yarn add -D typescript @types/react @types/react-native

三、配置 tsconfig.json

$ tsc --init --pretty --target esnext --allowJs --checkJs --jsx react-native --allowSyntheticDefaultImports --experimentalDecorators --emitDecoratorMetadata

注意:注意多余的注释可能会不兼容,需要移除,详细文档可查阅 编译选项

配置文件

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "allowJs": true,
    "checkJs": true,
    "jsx": "react-native",
    "strict": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "exclude": ["node_modules", "**/*.js"],
  "compileOnSave": false
}

解释:

  • target: 指定 ECMAScript 目标版本 "ES3"(默认),"ES5","ES6"/"ES2015","ES2016","ES2017","ES2018", "ES2019" 或 "ESNext"。
  • mode: 指定生成哪个模块系统代码:"None","CommonJS","AMD","System","UMD","ES6", "ES2015" 或 "ESNext"。
  • allowJs: 允许编译 javascript 文件。
  • checkJs: 在 .js 文件中报告错误。与 --allowJs 配合使用。
  • jsx: 在 .tsx 文件里支持 JSX: "react"、"react-native"或 "preserve"。查看 JSX
  • strict: 启用所有严格类型检查选项。启用 --strict 相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict--strictNullChecks--strictFunctionTypes--strictPropertyInitialization
  • allowSyntheticDefaultImports: 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
  • esModuleInterop: TypeScript 与 Babel 采取了不同的方案,并且直到现在,还没出现真正地固定标准。 简单地说,如果你使用 Babel,Webpack 或 React Native,并期望与你以往使用地不同的导入行为,TypeScript 提供了该编译选项。
  • experimentalDecorators: 启用实验性的 ES 装饰器。
  • 给源码里的装饰器声明加上设计类型元数据。: 给源码里的装饰器声明加上设计类型元数据。

四、EsLint 代码检测

Lint 工具用于检查代码的语法是否正确、风格是否符合要求。最新的工具 ESLint 不仅允许你自定义语法规则,还允许用户创造插件,改变默认的 JavaScript 语法,比如支持 ES6 和 JSX 的语法。

VsCode 支持

安装 ESLint Plugin

配置 ESLint Plugin

{
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    {
      "language": "typescript",
      "autoFix": true
    },
    {
      "language": "typescriptreact",
      "autoFix": true
    },
    {
      "language": "vue",
      "autoFix": true
    },
    {
      "language": "html",
      "autoFix": true
    }
  ],
  "eslint.autoFixOnSave": true
}
  • eslint.validate:ESLint 插件默认只校验 javascript 和 javascriptreact,所以需要手动开启其他语言的校验支持
  • eslint.autoFixOnSave: 开启保存时自动修复错误

项目配置

注意:配置之前请确保根目录下存在 .eslintrc.js。如果要指定忽略某些文件,可以使用 .eslintignore 文件(node_modules、bower_compnents 文件夹已经默认被忽略)

$ yarn add -D eslint eslint-config-airbnb eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react eslint-plugin-react-native @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-typescript

配置文件

.eslintrc.js:

由于文件过长,这里不做展示,具体配置请戳

.eslintignore:

# /node_modules/* and /bower_components/* ignored by default

五、Prettier 代码格式化

ESLint 能够检测出代码中的潜在问题,提高代码质量,但是并不能完全统一代码风格。而 Prettier 在格式化代码方面具有更大优势。Prettier 扫描文件中的样式问题,并自动重新格式化代码,以确保缩进、间距、分号、单引号和双引号等遵循一致的规则。

VsCode 支持

如果你只是想要格式化你的 JS 或 TS 代码,你可以忽略这一部分

安装 Prettier Plugin

配置 Prettier Plugin

注意:除了以下配置,建议你把其他格式化插件,比如 beautify 直接卸载,并配置 prettier 为默认格式化程序。

  • prettier.requireConfig: 需要项目中存在一个 prettierconfig 文件才能运行 prettier
  • editor.formatOnSave: 开启保存时自动格式化
{
  "prettier.requireConfig": true,
  "editor.formatOnSave": true
}

配置规则:

Prettier 与 ESLint 配合使用

完成上一部分 VSCode 的支持,再配置一个 PrettierConfig 文件你就可以使用 Prettier 的功能了。但是当样式出问题时,编辑器并不会给你报错。更糟糕的是,ESLint 和 Prettier 在格式化规则方面存在一些冲突。幸运的是,Prettier 被设计为易于与 ESLint 集成,所以你可以轻松在项目中使两者,而无需担心冲突。

$ yarn add prettier eslint-config-prettier eslint-plugin-prettier -D

配置文件

.eslintrc.js:

module.exports = {
  extends: [
+   'plugin:prettier/recommended',
+   'prettier/react',
+   'prettier/@typescript-eslint',
+   'prettier',
  ],
}

.eslintignore:

# /node_modules/* and /bower_components/* ignored by default

.prettierrc.js

module.exports = {
  semi: false, // 行位是否使用分号,默认为true
  trailingComma: 'es5', // 是否使用尾逗号,有三个可选值"<none|es5|all>"
  singleQuote: true, // 字符串是否使用单引号,默认为false,使用双引号
  printWidth: 120, // 一行的字符数,如果超过会进行换行,默认为80
  tabWidth: 2, // 一个tab代表几个空格数
  bracketSpacing: true, // 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
}

.prettierinore

**/node_modules/*

六、EditorConfig 跨编辑器配置统一

当多人共同开发一个项目的时候,往往会出现大家用不同编辑器的情况。就前端开发者来说,有人喜欢 Sublime,有人喜欢 Webstorm , 也有人喜欢 Atom,还有人喜欢 Vim,HBuilder 等等。各种不同编程语言的开发者喜欢各种不同的编辑器。EditorConfig 这个项目就是为了解决跨编辑器开发项目的代码风格统一问题的。

VSCode Plugin

安装完后不需要配置,直接在项目中添加配置文件即可。

配置文件

.editorconfig:

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.gradle]
indent_size = 4

[BUCK]
indent_size = 4

七、Git pre-commit Hook

pre-commit钩子在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 如果该钩子以非零值退出,Git 将放弃此次提交,不过你可以用git commit --no-verify来绕过这个环节。 你可以利用该钩子,来检查代码风格是否一致(运行类似 lint 的程序)、尾随空白字符是否存在(自带的钩子就是这么做的),或新方法的文档是否适当。

husky: 轻松使用 Git hooks

Husky 能阻止坏的 git commit, git push 和更多的 💩

$ yarn add -D husky

配置文件

.huskyrc.js:

module.exports = {
  hooks: {
    'pre-commit': 'node node_modules/eslint/bin/eslint.js --fix src/**/*.js',
  },
}

注意:测试发现直接运行 eslint --fix 使用的是全局的模块。

只使用 husky 的问题

  • 性能问题:对整个项目运行一个 lint 进程很慢,而且 linting 结果可能无关紧要。
  • 效率问题:遗留代码仓库上工作的同学很快会遇到新的问题,开启 Lint 初期,你可能会面临成千上万的 Lint Error 需要修复。部分同学对下面这个图可能并不陌生:只改了文件 A,但是文件 B、C、D 中也有大量错误。

lint-staged: husky 的好帮手

针对暂存的 git 文件运行 linters 并且不要让 💩 滑入你的代码库!对暂存区概念不熟悉的同学可以看下git-简明指南

$ yarn add -D husky lint-staged
  • husky: 被用来添加一些 git 钩子,这里我们需要一个用 pre-commit 在每次 git commit 操作时执行 lint-staged 命令。
  • lint-staged: 可以对 git 暂存区文件(也就是你想要 commit 的文件)执行一些操作,这样做即提高了性能又提高了效率。

配置文件

.huskyrc.js:

module.exports = {
  hooks: {
    'pre-commit': 'lint-staged',
    '**/*.{md,json}': ['prettier --write', 'git add'],
  },
}

lint-staged.config.js:

module.exports = {
  'src/**/*.{js,jsx,ts,tsx}': ['eslint --fix', 'git add'],
}

八、相对于根目录引入组件

这部分不是必须的,配置也有些繁琐。这里我就只介绍下简单的配置,详细文档请请查阅 babel-plugin-root-import

$ yarn add -D babel-plugin-root-import eslint-import-resolver-babel-plugin-root-import

配置文件

babel.config.js:

module.exports = {
  ...
  plugins: [
    [
      'babel-plugin-root-import',
      {
        rootPathSuffix: 'src',
        rootPathPrefix: '~',
      },
    ],
  ],
  ...
}

.eslintrc.js

{
  settings: {
    'import/resolver': {
      'babel-plugin-root-import': {
        rootPathSuffix: 'src',
        rootPathPrefix: '~',
      },
    },
  },
}

tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "~/*": ["src/*"]
    }
  }
}

九、支持 .jsx

React Native 都已经内置支持 TypeScript 了,但是却不支持 .jsx 文件后缀。如果你想要使用 .jsx 开发,可以配置 metro.config.js:

module.exports = {
  resolver: {
    sourceExts: ['ts', 'tsx', 'js', 'jsx', 'json', 'mjs'],
  },
}

十、相关资料