[Next Note] - 把 TypeScript、ESLint、Prettier、Alias 摻再一起做沙尿牛丸
Introduction & 前言
你開發使用 Tab 還是 Space 縮排呢?兩格還是四格?單引號還是雙引號?
哎呀,git pull
下來怎麼排版又跑掉了…
這個 function 傳進來的參數到底是 string 還是 number?
來吧!這篇文章將你的痛處一次解決。
如果你剛好想配置專案的 Alias,但對於 ESlint 及 TypeScript 怎麼設定毫無頭緒,也適合這篇文章的閱讀,最後文章會附上 Source Code。
統一團隊的 Coding Style 吧,筆者認為 TS + ESLint + Prettier 可以稱為前端規範三劍客
Summary & 摘要
這篇文章預設讀者已經有基本的 npm install
能力,或是已經涉略過一點 CRA 框架。
本篇文章預設學習前的基本條件需求:
本篇文章將會學到:
- 如何將團隊的 Coding Style 規範統一
- 解決一些可能會碰到的痛點
- 避免踩到關於規範套件的坑(也許會慢慢更新上來)
為何要寫這篇
最近在建置公司的新專案,有鑒於之前工作時,到後期多個前端一起開發後,常常不同的人有不同的 VSCode 配置,有的人希望使用雙引號,有的人希望使用單引號。
或許單引號雙引號是小事,或許你曾經碰過有人幫你 Code Review 後,修改了一點你的邏輯,但是你發現怎麼改了幾百幾千行?只因為他的縮排跟你不同
為了解決這個情況,在開始接觸 ESLint 後,筆者就決定之後的專案要使用了;而講到專案規範也不得不提 TypeScript,這次將會使用一個新的專案示範如何將 ESLint、TypeScript 還有 Prettier 摻在同一個專案變成完美多汁的沙尿牛丸。
順帶一提,這次不使用 CRA (Create React App) 建立普通專案是因為剛好在新的專案中筆者需要使用 Next,如果你要使用 CRA 或者其他 SSR、CSP 也是可以的,安裝起來其實大同小異。
另外處使這篇文章的產生也是因為筆者在配置 Alias 的路徑時發生一些錯誤,所以想將過程記錄下來。
備註:這邊需要提及一下,這篇文章將會適合初始化專案沒有使用預設推薦安裝的人,現在安裝 Next.js 的時候會詢問是否要一併安裝,下面將會說到兩種安裝方式。
Next 是什麼?
如果你已經會使用 Next 且知道這是什麼了,這段可以跳過
相信會看到這篇的讀者一定大部分都知道 Next 了,但可能有些讀者只有使用過 CRA,不用太擔心,如果你使用 CRA 也可以照著這篇的方式去安裝。
Next 是基於 React 的框架,同時支援 SSR (Server Side Rendering) 與 SSG (Static Side Generation) 兩種方法,如果你還不清楚什麼是 SSR、SSG、CSP…等等的話,可以參考這篇 淺談 SPA、CSR、SSR、MPA、SSG 專有名詞 文章。
這篇文章就不著墨於這邊太多,簡單說一下通常會使用 Next.js 的絕大多情況,當你學習並且使用 CRA 在工作上都穩穩妥妥的,在某天風和日麗的情況下,老闆或 PM 突然跟你說 『欸欸,我們來優化一下網站的 SEO 吧!!』,相信大部分會開始研究 Next 的夥伴們都是從這邊開始的。
接下來就留給讀者去研究了,如果你有興趣也可以參考這篇鐵人賽文章 - 從零開始學習 Next.js,除了為什麼需要使用及 CSR、SSR 等等,也會介紹一系列的使用方式
安裝方式一
這是相對簡單的安裝方式,如果你是使用 CRA 或者你的專案已經存在一段時間,這時候想要中途加入這些套件,請參照安裝方式二。
首先初始化專案,這個步驟猶如 Hello World,都是各位將建立出偉大專案的第一步,參照 Next.js 官網的 Create Next App 安裝方式。
1 | npx create-next-app@latest |
輸入結束後,Next.js 將會詢問三個問題,分別是 專案名稱、是否使用 TypeScript 以及 是否使用 ESLint,如果你都接受使用,這就是安裝最簡單的方式。
建立成功後會像上圖,該需要的設定檔都會出現了。
介紹完第二個安裝方式後,將會介紹如何去簡單配置一些設定,還有如何安裝 Prettier 及配置 Alias。
安裝方式二
這個方式適用於專案初始時沒有安裝 TS、ESLint 的人,或許剛開始你的專案像下圖一樣起始時沒有安裝這些規範套件的。
TypeScript
先確定路徑在專案內,接著先安裝 TypeScript,如果你還不知道 TS 是什麼可以參考 **什麼是 TypeScript**,這邊就不多做介紹。
在終端機內輸入底下指令:
1 | yarn add -D typescript |
這時候不會有什麼變化,在設定 TS 及 ESLint 的時候,都有一個共通點就是需要透過 Config 來設定,所以需要先初始化一個設定檔。
你可以選擇安裝全域的 TypeScript 之後使用指令初始化,也可以透過專案裡 node_modules 去初始化,如下指令:
- 透過全域初始化
1 | 全域安裝 TS |
- 透過 node_modules
1 | 在專案目錄底下初始化 TS 設定檔 |
關於設定檔的內容配置,可以參考 TypeScript 的官方文件
這時候看一下專案架構,會發現多了一個 tsconfig.json,往後關於一些 JS 的規範就可以設定在這裡面。
接下來我們需要手動把檔案改成 .tsx 結尾,這樣 TypeScript 才能監測並且檢查檔案有沒有符合規範。
把專案底下的檔案改完之後,會發現出現很多條紅色蚯蚓,剛開始使用 TS 或許會很頭痛,但是日後開發上會幫助很大。
仔細看一下修改完的檔案出現的錯誤,這時候就要開始去修改 tsconfig.json 的配置。
如果你使用 Next 先安裝一下幾個 types,有時候程式碼會報錯也是因為套件找不到該程式碼定義的 types。
1 | yarn add -D @types/node @types/react @types/react-dom |
將 tsconfig.json 的配置改為下列:
1 | { |
然後重啟專案或者透過 command + p
打開 VSCode 的搜尋欄位,輸入 >TypeScript
會有一個重啟 TS 的選項可以選擇
如果你是使用 Next.js 這時候會有第一個需要排解的地方,打開 pages/index.tsx 會發現引入 import styles from '../styles/Home.module.css'
底下出現紅紅的蚯蚓,要解決的方法就是在專案底下建立 next-env.d.ts,然後內容輸入:
1 | /// <reference types="next" /> |
這時候再重啟即可,之後的配置可以隨著專案需求慢慢新增或者修改。
ESLint
裝完 TS 接下來就是要安裝 ESLint,如果你還不知道這是什麼的話可以參考 **ESLint 是什麼?**。
打開終端機,確定目前路徑在專案底下,輸入以下指令:
1 | yarn add -D eslint eslint-config-airbnb eslint-plugin-jsx-a11y |
是否要多安裝 Airbnb 可以看使用需求,這是一個 ESLint 的規範風格,裡面有定義好一些預設的規範,通常較多人使用,但是也比較嚴格,其餘還有 Standard 及 Google 可以選擇,有興趣的讀者也可以餵狗(Google)搜尋一下或參考這篇文章 五分鐘快速替專案加上 ESLint 文章底下有介紹各種不同的風格差異,這邊就不多做介紹
接下來一樣要初始化 ESlint 的設定檔,你可以選擇安裝全域的 ESLint 之後使用指令初始化,也可以透過專案裡 node_modules 去初始化,如下指令:
- 透過全域初始化
1 | 全域安裝 ESLint |
- 透過 node_modules
1 | 在專案目錄底下初始化 ESLint 設定檔 |
初始化的時候會分別問一些 ESLint 的問題,這些依照專案需求即可,舉例有下面幾個問題,像是你想在什麼情況下使用 ESLint、專案是用什麼模式導入模組、專案使用哪個框架…等等
- ✔ How would you like to use ESLint? · problems
- ✔ What type of modules does your project use? · esm
- ✔ Which framework does your project use? · react
- ✔ Does your project use TypeScript? · No / Yes
- ✔ Where does your code run? · browser
- ✔ What format do you want your config file to be in? · JSON
The config that you’ve selected requires the following dependencies:
eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
- ✔ Would you like to install them now? · No / Yes
- ✔ Which package manager do you want to use? · yarn
這時候再回去看專案,裡面會多出一支 .eslintrc.json,副檔名會依照 What format do you want your config file to be in?
這個問題而不同。
我們稍微修改一下裡面的設定,改為下面的設定,如果你想客製化可以參考 ESLint 的 官網設定
1 | { |
這時候再回去開你的 /pages/index.tsx
,會發現熟悉的紅色毛毛蟲又回來了。
如果使用 VSCode 可以把滑鼠指向紅色蚯蚓,點選 **快速修復…(⇧⌘ㄡ)**,就可以全部一次依照 ESLint 的設定檔規範修正
此外我們也可以修改一下 package.json 的配置,將 “scripts” 那塊加上兩行程式碼:
1 | "lint": "next lint", |
接著在終端機輸入 yarn lint
或 npm run lint
,就可以檢測程式碼有無符合規範,沒有就會出現下圖。
而透過 yarn lint:fix
或 npm run lint:fix
則是可以把整個專案包含 .js,.jsx,.tsx
的檔案一次修復。
修復成功如果都無誤就會出現 ✔ No ESLint warnings or errors
。
Prettier
雖然我們已經有了程式碼的書寫規範,但身為工程師還是會想到更懶的問題,為什麼不能在儲存的時候就幫我們排版排好呢?還要一個一個解決問題或點 快速修復…(⇧⌘ㄡ) 太麻煩了吧。
這時候就要發揮工程師精神,讓我們繼續往下安裝:
1 | yarn add -D prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-react-hooks |
裝完後接著在新建兩支檔案,分別為 .prettierrc 及 .prettierignore,前者同樣為設定檔,後者為 prettier 要忽略不涵蓋的檔案。
.prettierrc 的內容改為:
1 | { |
.prettierignore 的內容改為:
1 | package.json |
然後把 package.json 的 scripts 做一下修改:
1 | "scripts": { |
之後我們就可以先用 yarn lint
檢查程式碼是否符合規範,然後再用 yarn lint:fix
去全域依照 ESLint 及 Prettier 去修正程式碼。
說好的自動修正呢?
你一定會有疑問,不是說好要在儲存後就自動修正嗎?沒錯,如果你是使用 VSCode 的話,請在專案底下新增 .vscode/settings.json
,然後在 settings.json 裡面寫上下面的內容:
1 | { |
之後儲存就會自動修正了!
Alias
其實 Alias 才是促使本篇產出的重點,先說說這是什麼,以往我們在專案中會引入一些靜態文件或者 Components,大部分使用的時候我們都是會寫 import Header from '../../components/Header'
,但是當我們檔案一多,資料夾一多,就可能會產生出 import Header from '../../../../../components/Header'
,在另一個檔案可能又變成 import Header from '../../../components/Header'
,可能這個例子比較誇張一點,但這樣確實不美觀且寫起來不舒服啊。
所以就有了 Alias 可以使用,使用了之後上面的情況可以統一變成 import Header from '@components/Header'
,這就是模板的概念。
首先我們修改一下 tsconfig.json:
1 | { |
多了 baseUrl 讓 TS 知道我們的基本路徑從哪裡開始,下面的 paths 則是設定 Alias 的部分,我們先這樣設定,然後在專案底下多建立一個 components 的資料夾,裡面建立一支 Header.tsx 的檔案,內容打上:
1 | const Header = () => { |
目前專案架構會如下圖
然後回到 /pages/index.tsx
或者隨便一個 .tsx
檔案裡面,在最上面輸入 import Header from "@components/Header";
,會發現紅色蚯蚓又出來了。
踩坑之旅
這次碰到最大的問題就是關於引入報錯,依照 ESLint 检查 TypeScript 时报 “Unable to resolve path to module ‘xxx’” 错误 一文指出 『eslint-plugin-import 原本只支持 ES6 模块,从 README 文档也可以看出默认只支持 .js, .jsx 后缀的这类 JS 社区常见的文件。TypeScript 使用的 .ts 和 .tsx 自然是不支持的,更不用说 import 插件还需要相应的 parser 来解决 TypeScript 解析问题。』 我們可以了解到如果使用了 TS 及 ESLint 再去使用 Alias 會被紅色蚯蚓噴得體無完膚。
目前 ESLint 不認得這個路徑,所以我們必須讓它認得,我們只需要安裝幾個套件,讓程式碼規範套件讀得懂即可:
1 | yarn add -D eslint-import-resolver-alias eslint-import-resolver-typescript eslint-plugin-import |
上面的安裝是為了解決 ESLint 不認得我們在 TS 設定 Alias 的錯誤,安裝完畢後修改 ..eslintrc.json
的內容:
1 | { |
透過上面的修改後,就可以正常的讓 TypeScript 及 ESLint 讀懂我們設定的 Alias 模板,也能知道我們要引入的檔案是不是真的存在了。
總結
TS + ESLint + Prettier 對於前端可以設置一個很好的團隊規範,也能有效地防止每個人有每個人的寫法造成 Code Review 需要去花更多時間解決不必要的衝突。
有了 ESLint 我們也可以搭配之前文章 [Git Note] - 統一團隊的 Git Commit 格式吧!不要再讓 Commit 亂糟糟 裡提過的 Husky,在我們做 pre-commit 的時候就先去幫我們跑一次 Lint,如果不符合規範就拒絕開發者 git push,實在時居家旅行….
Conclusion & 結論
隔了好一段時間沒有寫文章了,這段時間剛好經歷了工作的變動,一些生活上的調整等等,好一段時間都還在思索接下來的規劃。
剛好到了新的工作崗位上碰到了更多新的挑戰,最近卡在這個 Alias 上一段時間,當下心裡第一時間想的是一定要把它記錄回來部落格,希望有人因為這個卡關時,可以剛好看到這篇文章。
其中還是要特別謝謝我的大學室友,沒有他可能我這個問題還在卡關呢。
這次因為新專案加上朋友委託筆者幫忙建置 Electron 的緣故,碰到了一直很想摸索的 Next.js,我想接下來又有更多的東西可以去玩了,下次有機會就來介紹一下 Electron 這個酷東西。
Source Code: 請點我