優雅地使用TypeScript開發React Native應用
從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 複製程式碼
配置 tsconfig.json
$ tsc --init --pretty --target esnext --allowJs --checkJs --jsx react-native --allowSyntheticDefaultImports --experimentalDecorators --emitDecoratorMetadata 複製程式碼
注意:注意多餘的註釋可能會不相容,需要移除,詳細文件可查閱編譯選項。
配置檔案
{ "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"] } 複製程式碼
解釋:
-
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裝飾器。 -
給原始碼裡的裝飾器宣告加上設計型別元資料。
: 給原始碼裡的裝飾器宣告加上設計型別元資料。
@types/react、@types/react-native
為了提高開發效率和避免 typescript 型別檢查報錯,你需要新增這兩個型別宣告庫。
$ yarn add @types/react @types/react-native -D 複製程式碼
EsLint 程式碼檢測
Lint工具用於檢查程式碼的語法是否正確、風格是否符合要求。最新的工具ESLint不僅允許你自定義語法規則,還允許使用者創造外掛,改變預設的JavaScript語法,比如支援ES6和JSX的語法。
VsCode 支援
安裝 ESLint Plugin
配置 ESLint Plugin
eslint.validate eslint.autoFixOnSave
{ "eslint.validate": [ "javascript", "javascriptreact", { "language": "typescript", "autoFix": true }, { "language": "typescriptreact", "autoFix": true }, { "language": "vue", "autoFix": true }, { "language": "html", "autoFix": true } ], "eslint.autoFixOnSave": true, } 複製程式碼
專案配置
注意:配置之前請確保根目錄下存在.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 複製程式碼
- eslint: 可組裝的JavaScript和JSX檢查工具
-
eslint-config-airbnb: 該軟體包提供Airbnb的
.eslintrc
作為可擴充套件的共享配置 - eslint-plugin-jsx-a11y : 用於JSX元素的可訪問性規則的靜態AST檢查器。
- eslint-plugin-import: 此外掛旨在支援ES2015 +(ES6 +)匯入/匯出語法的linting。
- eslint-plugin-react: ESLint React 校驗規則外掛
- eslint-plugin-react-native : 針對ESLint的React Native特定linting規則
- @typescript-eslint/parser : 將 TypeScript 轉換為 ESTree,使 eslint 可以識別
- @typescript-eslint/eslint-plugin : 一個包含一堆特定於TypeScript的ESLint規則的外掛
- eslint-import-resolver-typescript : 給 eslint-plugin-import 新增 typescript 支援的外掛
配置檔案
module.exports = { env: { es6: true, node: true, jest: true, 'react-native/react-native': true, }, extends: [ 'airbnb', 'plugin:react-native/all', 'plugin:@typescript-eslint/recommended', ], parser: '@typescript-eslint/parser', parserOptions: { ecmaFeatures: { jsx: true, impliedStrict: true, }, ecmaVersion: 2018, project: './tsconfig.json', sourceType: 'module', }, plugins: [ 'import', 'react', 'react-native' ], settings: { 'import/resolver': { typescript: {}, }, }, rules: { 'global-require': 0, 'linebreak-style': [2, 'unix'], 'no-console': [ 'error', { allow: ['warn', 'error', 'info', 'log'], }, ], 'lines-between-class-members': [ 2, 'always', { exceptAfterSingleLine: true, }, ], 'no-use-before-define': [ 2, { functions: true, classes: true, variables: false, }, ], 'prefer-destructuring': [ 2, { array: false, object: true, }, ], 'react/prefer-stateless-function': 0, 'react/prop-types': 0, 'react/jsx-filename-extension': [ 2, { extensions: ['.js', '.jsx', '.tsx'], }, ], 'jsx-a11y/accessible-emoji': 0, 'react-native/no-color-literals': 0, '@typescript-eslint/no-use-before-define': [ 2, { functions: true, classes: true, variables: false, }, ], '@typescript-eslint/explicit-function-return-type': { allowExpressions: true, allowTypedFunctionExpressions: true, }, }, } 複製程式碼
# /node_modules/* and /bower_components/* ignored by default 複製程式碼
Prettier 程式碼格式化
ESLint 能夠檢測出程式碼中的潛在問題,提高程式碼質量,但是並不能完全統一程式碼風格。而 Prettier 在格式化程式碼方面具有更大優勢。Prettier 掃描檔案中的樣式問題,並自動重新格式化程式碼,以確保縮排、間距、分號、單引號和雙引號等遵循一致的規則。
VsCode 支援
如果你只是想要格式化你的 JS 或 TS 程式碼,你可以忽略這一部分
安裝 Prettier Plugin
配置 Prettier Plugin
注意:除了以下配置,建議你把其他格式化外掛,比如 beautify 直接解除安裝,並配置 prettier 為預設格式化程式。
prettier.requireConfig 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 複製程式碼
- prettier: 主 prettier 庫
- eslint-config-prettier : 關閉所有不必要或可能與 prettier 的規則衝突的ESLint規則。
- eslint-plugin-prettier : 以 ESLint 外掛的形式執行 prettier
配置檔案
.eslintrc.js
module.exports = { extends: [ 'prettier', 'plugin:prettier/recommended', 'prettier/react', 'prettier/@typescript-eslint', ], } 複製程式碼
.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/* src/**/*.js src/**/*.jsx src/**/*.ts src/**/*.tsx 複製程式碼
EditorConfig 跨編輯器配置統一
當多人共同開發一個專案的時候,往往會出現大家用不同編輯器的情況。就前端開發者來說,有人喜歡 Sublime,有人喜歡 Webstorm , 也有人喜歡 Atom,還有人喜歡 Vim,HBuilder 等等。各種不同程式語言的開發者喜歡各種不同的編輯器。EditorConfig 這個專案就是為了解決跨編輯器開發專案的程式碼風格統一問題的。
VSCode Plugin
安裝
安裝完後不需要配置,直接在專案中新增配置檔案即可。
配置檔案
# 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
和更多的:hankey:
$ 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並且不要讓:hankey:滑入你的程式碼庫!對暫存區概念不熟悉的同學可以看下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', }, } 複製程式碼
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'] }, } 複製程式碼
相關資料
- Using ESLint and Prettier in a TypeScript Project : TypeScript、ESLint、Prettier、VSCode
- 使用 ESLint + Prettier 簡化程式碼 Review 過程 : Zeit Now、DevOps
- 用Prettier和ESlint來統一提交程式碼 : ESLint、Prettier、husky、lint-staged
- 用 ESLint 和 Prettier 寫出高質量程式碼 :ESLint、Prettier、husky、lint-staged
- 使用ESLint+Prettier來統一前端程式碼風格 :ESLint、Prettier
- 使用ESLint & Prettier美化Vue程式碼 :Vue、ESLint、Prettier、husky、lint-staged、填坑
- 用 husky 和 lint-staged 構建超溜的程式碼檢查工作流 : husky、lint-staged