[TOC]
>[success] # 為什么要規范化
~~~
1.'軟件開發需要多人協同'、'不同開發者具有不同的編碼習慣和喜好'、'不同的喜好會增加項目的維護成本'
'每個項目或者團隊需要明確統一的標準'
2.開發過程中需要規范化內容,'代碼、文檔、甚至是提交日志'、'開發過程中人為編寫的成果物'、'代碼標準化規范'
3.如何實時規范化'編碼前人為的標準約定'、'通過工具實現 Lint'
~~~
>[info] ## 規范路上前端做了什么
~~~
1.JS的弱類型和動態類型,JS的變量在聲明時無需指定其類型。并且在其聲明之后,可以為其隨便賦值不同的類型。
JS由于不需要關注變量的類型,可以使代碼更加簡潔,也能使開發者集中更多的精力在處理業務邏輯之上。
但由于其無法保證變量類型,從而在程序運行期可能發生跟類型相關的錯誤。 比如:
var s = 1;
s(); //Uncaught TypeError: s is not a function
而這樣的錯誤對于JAVA在編譯期間就會檢查出來。
2.為了可以在編寫中發現問題,前端出現了很多種嘗試類似'TypeScript、CoffeeScript或Elm' 輔助工具出現了'Lint'
'Lint'工具最早是使用于UNIX系統中C語言的程式碼靜態分析工具,主要是用來標記語法結構上有可疑的、濳在的問題
語法或指令,在前端類似的這種類似工具有'JSLint與JSHint',隨著時代推移'ESLint'由Nicholas C. Zakas創造,正如
是為ES新標準語法所設計,相比其他js 檢查工具來說'ESLint'的功能具有
2.1. 有更多規則選項可以依需求或喜好設定
2.2. 函式庫或框架的開發者可以依需求再開發擴充
2.3.支持更高的es 語法和實驗特性和JSX 語法
2.4.提供錯誤警告
3.ESlint需要將源碼轉為AST 的特點并且還可以擴展規則,默認的解析器也能替換,這種自由度高
可插拔的形式,最后'ESLint' 成為現階段'js' 代碼質量檢查的工具
~~~
>[info] ## Eslint -- 專注于 JavaScript 代碼質量檢查
~~~
1.'Eslint'最為主流的 JavaScript Lint 工具,檢測 JS 代碼質量可以統一開發者的編碼風格
2.'ESLint' 使用 Node.js 編寫
~~~
>[danger] ##### 安裝eslint
~~~
1.先初始化項目 -- 'npm init -y'
2.安裝Eslint 模塊為開發依賴 -- 'npm install eslint -D'
2.1.通過npx 可以產看'eslint' 版本 -- 'npx eslint --version'
~~~
>[danger] ##### 如何使用
~~~
1.初始化生成配置文件 -- 'npx eslint --init'
初始化的時候會詢問幾個問題:
問題1 : 如何使用ESLint ?
只檢查語法錯誤 | 檢測語法錯誤以及問題代碼 | 檢測語法錯誤以及問題代碼以及代碼風格
問題2: 你的項目模塊化選擇類型?
JS modules(import/export) | CommonJS(require/exports) | None of these
問題3:項目使用框架
問題4: 是否使用TS
問題5: 運行環境 Browser | Node
問題6: 定義代碼風格
主流代碼風格 | 個人自定義 | 根據代碼判斷
問題7:配置文件格式 JS | YARM | JSON
問題8: 安裝額外的插件Y
安裝完成后會出現.eslintrc.js文件
2.根據上面的詢問選好配置后
2.1.'npx eslint [文件路徑]' -- 檢查對應文件中編碼格式。路徑可以使用路徑通配符
2.2.'npx eslint [文件路徑] --fix' -- 自動修正代碼風格
~~~
>[danger] ##### eslint 檢查的是什么
~~~
1.通過執行elint 的指令看到了編寫文件產生的錯誤和幫助我們修改了錯誤,eslint 到底檢查的是什么?
1.1.'語言語法檢查':比如檢查出字符串引號或者函數調用括號沒有匹配等問題。
1.2.'編碼錯誤檢查':比如檢查出開發者在使用一個不存在的變量或者變量定義了卻沒有使用等問題。
1.3.'代碼風格檢查':比如檢查出開發者沒有使用分號(與所選風格有關)等問題。
注意他不會檢查你js api調用的是否正確,明確他能做的
~~~
>[danger] ##### eslint 檢查指令
~~~
# 檢測單個文件
npx eslint file1.js file2.js
# 檢測src和scripts目錄
npx eslint src scripts
2.案例
var a = "1";
const zz = "1000"
~~~
* 檢查對應文件中編碼格式 給出了錯誤原因

>[danger] ##### 修復 fix
~~~
1.--fix后綴,是ESLint提供自動修復基礎錯誤的功能,它只能修復一些基礎的不影響代碼邏輯的
錯誤,比如代碼末尾加上分號、表達式的空格等等。
2.例如:'npx eslint src scripts --fix' / 'npx eslint file1.js file2.js --fix'
3.案例
var a = "1";
const zz = "1000"
~~~
* 執行 --fix
~~~
代碼被自動修改 為下面代碼
const a = '1';
const zz = '1000';
~~~

>[danger] ##### 指定文件 -- ext
~~~
1.eslint 修復和檢查都可以指定具體文件或者具體文件夾,例如可以指定具體文件'aa.vue',
'aa.js',但是指定文件時候例如'/src' 這個文件下會有各種文件類型,但eslint 默認只會檢測
文件夾中的'js' 文件,此時需要使用'ext'
2.注意只有在指定是文件夾時候使用'ext' 才會生效,舉個例子"npx?eslint?--ext?.js,.jsx,.vue?src"
~~~
>[info] ## eslintignore 忽略指定文件
~~~
1.對于一些公共的js,或者測試腳本,不需要進行檢測,我們可以通過在項目根目錄創建一
個.eslintignore告訴ESLint去忽略特定的目錄或者文件
~~~
>[info] ## eslint 配置文件 -- .eslintrc.*
~~~
1.eslint 提供了配置文件在里面可以配置想要檢查的規則:
1.1.'JavaScript' - 使用 .eslintrc.js 然后輸出一個配置對象。
1.2.'YAML' - 使用 .eslintrc.yaml 或 .eslintrc.yml 去定義配置的結構。
1.3.'JSON' - 使用 .eslintrc.json 去定義配置的結構,ESLint 的 JSON 文件允許 JavaScript 風格的注釋。
1.4.'(棄用)' - 使用 .eslintrc,可以使 JSON 也可以是 YAML。
1.5.'package.json' - 在 package.json 里創建一個 eslintConfig屬性,在那里定義你的配置。
優先級 '.eslintrc.js' > '.eslintrc.yaml' >'.eslintrc.yml' >'.eslintrc.json' >'.eslintrc'> 'package.json'
2.配置文件中的字段說明:
2.1.'parser' 解析器'ESLint '默認使用 'Espree' 作為其解析器,主要將寫的內容轉成ast 根據規則來驗證
2.2.'extends'ESLint遞歸地擴展配置
2.3.'rules': 定義規則,可以覆蓋掉extends的配置
2.4.'parserOptions':解析器配置
2.5.'plugins':為eslint新增一些檢查規則
2.6.'env': 一個環境定義了一組預定義的全局變量
~~~
>[danger] ##### parser -- 解析器
~~~
1.想成為eslint 的parser解析器需要滿足兩點
1.1.'它必須是一個 Node 模塊,應該使用 npm 單獨安裝解析器包.'
1.2.'它必須符合 parser interface(https://eslint.bootcss.com/docs/developer-guide/working-with-plugins#working-with-custom-parsers)'
2.關于其他解析器'Esprima','Babel-ESLint','@typescript-eslint/parser '
2.1.'esprima':ESLint最開始使用的解析器
2.2.'espree':由于后來'esprima'沒有更新無法在支持,ESLint自己基于esprima v1.2.2開發的一個解析器(默認自帶)
2.3.'babel-eslint':一個對Babel解析器的包裝,使其能夠與ESLint兼容。
2.4.'@babel/eslint-parser':從 v11.xx 版本開始,babel-eslint 不再維護和更新
2.5.'@typescript-eslint/parser':將TypeScript轉換成與estree兼容的形式,以便在ESLint中使用。
關于解析器的選擇,如果你是Ts那么你需要使用的是'@typescript-eslint/parser',如果你正在嘗試新的一些'ES'
語法中的實驗屬性使用'babel' 提供的解析,當然如果你僅僅是想支持最新的最終 ES 標準可以使用eslint 默認
以目前寫文章的節點裝飾器為例屬于一個實驗屬性,在使用默認的eslint的解析器 是不行的,你需要使用'babel'
'簡短的使用教程':
需要安裝'npm install @babel/core @babel/eslint-parser @babel/plugin-proposal-decorators --save-dev'
解釋一下'decorators' 裝飾器目前在第二階段因此需要下載'babel' 插件,關于配置
module.exports = {
"parser":"@babel/eslint-parser",
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": "eslint:recommended",
// 相當于配置@babel/eslint-parser 解析器的配置
parserOptions: {
// 如果你 沒有寫 類似.babelrc 將需要requireConfigFile設置fasle
// 表示不使用配置文件
requireConfigFile: false,
// 因為沒有配置類似.babelrc 所以需要配置babelOptions聲明使用的插件
babelOptions: {
plugins: [["@babel/plugin-proposal-decorators",{"legacy": true}]],
}
},
"rules": {
}
};
如果你配置了類似'.babelrc' 文件那么你就可以不用配置'parserOptions' 這個參數
~~~
[你使用@babel/eslint-parser 遇到了麻煩參考 Updating babel-eslint to @babel/eslint-parser for React apps
]( https://tjaddison.com/blog/2021/03/updating-babel-eslint-to-babeleslint-parser-for-react-apps/)
>[danger] ##### parserOptions
~~~
1.可以使用解析器選項覆蓋該設置以啟用對其他 ECMAScript 版本以及 JSX 的支持。簡單理解配合你的
解析器,之前說過默認的解析器是'espree'去gitub 搜索你可以發現當傳入不同參數的時候配置器將會
有不同的結果返回。
~~~
>[danger] ##### plugins
~~~
1.plugin插件主要是為eslint新增一些檢查規則,ESLint 雖然可以定義很多的 rules,只是檢查 JS 語法。如果需要檢查
Vue 中的 template 或者 React 中的 jsx,就束手無策了。引入插件的目的就是為了增強 ESLint 的檢查能力和范圍
簡單的說像vue react 這類新的框架會有自己的規則,這類規則需要去安裝額外的插件
2.插件名稱可以省略 'eslint-plugin- 前綴'
{
"plugins": [
"plugin1", // eslint-plugin-plugin1的簡寫
"eslint-plugin-plugin2"
]
}
3.但是要說明一下:如果僅配置`"plugins": ["vue"]`,vue文件中template內容還是會解析失敗。
這是因為不管是默認的espree還是babel-eslint解析器都無法解析.vue中template的內容;
`eslint-plugin-vue`插件依賴`vue-eslint-parser`解析器,而`vue-eslint-parser`解析器只會解析template內容,不會檢測`script`中的JS內容,因此我們還需要指定一下解析器:
{
????"extends":?["eslint:recommended"],
????"plugins":?["vue"],
????"parser":?"vue-eslint-parser",
????"parserOptions":?{
????????"parser":?"babel-eslint",
????????"ecmaVersion":?12,
????????"sourceType":?"module",
????},
}
上面`parserOptions.parser`看的有點迷糊,這是由于外層的解析器只能有一個,我們已經用了
`vue-eslint-parser`就不能再寫其他的;因此`vue-eslint-parser`的做法是在解析器選項中再傳
入一個解析器選項用來處理`script`中的JS內,相當于此時有兩個解析器在工作
~~~
>[danger] ##### extends -- 繼承
~~~
1.'extends' 從零開始配置eslint 規則是一件麻煩的事但是可以引用其他已經配置好的完整規則文件
1.1."eslint:recommended" 啟用 ESLint 推薦開啟的規則 ( 查看具體開啟規則'https://eslint.bootcss.com/docs/rules/')
1.2."eslint:all" 開啟 ESLint 中所有核心規則
在初始化eslint 時候提供的另外三種選擇:
1.3.'Google標準':安裝 'npm install eslint-config-google -g'
1.4.'Airbnb標準':安裝依賴'eslint-plugin-import, eslint-plugin-react, and eslint-plugin-jsx-a11y等插件',想查看
具體詳細的依賴可以執行指令'npm info "eslint-config-airbnb@latest" peerDependencies'
1.5.'Standard標準,它是一些前端工程師自定的標準'安裝執行
'npm install eslint-config-standard eslint-plugin-standard eslint-plugin-promise -g'
2.'extends 屬性值的組成':
2.1.eslint:開頭的ESLint官方擴展,有兩個:eslint:recommended(推薦規范)和eslint:all(所有規范)。
2.2.plugin:開頭的擴展是插件類型擴展
2.3.eslint-config:開頭的來自npm包,使用時可以省略eslint-config-,比如上面的可以直接寫成standard
2.4.@:開頭的擴展和eslint-config一樣,是在npm包上面加了一層作用域scope
舉個例子(后面的規則會覆蓋前面的):
{
"extends": [
"eslint:recommended" ,// 使用eslint 推薦規范
"airbnb" ,// 相當于使用了eslint-config-airbnb
"plugin:vue/essential" ,// vue 必不可少的類型規則
'eslint-config-airbnb-base/rules/strict' // 去指定一個具體文件地址
],
}
3.社區封裝的 ESLint plugin,在 npm 上搜索eslint-plugin-就能發現很多,比較出名的有
'eslint-plugin-react ,eslint-plugin-import' 為什么出現這些規則?首先eslint 自帶的規則都是
'es'語法本身的規則,那像vue ,react 這種內置的'eslint' 規則并不包含因此出現,以vue 為例
"extends": [
' plugin:vue/base '//:基礎
'plugin:vue/essential '//:必不可少的
'plugin:vue/recommended ' //:推薦的
'plugin:vue/strongly-recommended ' //:強烈推薦
]
4.如果 extends 配置的是一個數組,那么最終會將所有規則項進行合并,出現沖突的時候,后面的會覆蓋前面的;
~~~
>[danger] ##### plugins 和 extends 中 plugin區別
~~~
1.'plugins' 理解成擴展校驗規則,即原本'eslint' 是為了'js'出現的,隨著前端的發展,出現一些其
他格式文件例如'vue',此時eslint 這種可插拔設計,在'plugins' 擴展將其檢測規則擴展到eslint
2.規則就像是一個集合,真正想使用什么規則需要人為去配置,這種配置可以使用'rules' 一條
一條的去指定,當然也可以使用一組配置開啟集合這個就是'extends ' 字段
3.extends除了使用plugin中 config name 的加載方式,往往也會使用eslint-config-xxxx這樣命名的包
module.exports = {
plugins: [
'eslint-plugin-react' // 擴展的規則
],
extends: [
// 新提供的規則一個開啟的配置集合
'eslint-plugin-react/recommended'
],
rules: {
'eslint-plugin-react/jsx-boolean-value': 2 // 如果沒有eslint-plugin-react/recommended需要自己慢慢配置
}
}
~~~
>[danger] ##### rules
~~~
1.規則的校驗說明,有 3 個報錯等級
1.1.'off 或 0':關閉對該規則的校驗;
1.2.'warn 或 1':啟用規則,不滿足時拋出警告,且不會退出編譯進程;
1.3.'error 或 2':啟用規則,不滿足時拋出錯誤,且會退出編譯進程;
通常規則只需要配置開啟還是關閉即可;但是也有些規則可以傳入屬性,比如:
{
rules: {
'quotes': ['error', 'single'], // 如果不是單引號,則報錯
'one-var': ['error', {
'var': 'always', // 每個函數作用域中,只允許 1 個 var 聲明
'let': 'never', // 每個塊作用域中,允許多個 let 聲明
'const': 'never', // 每個塊作用域中,允許多個 const 聲明
}]
}
}
2.通過 rules 單獨配置的規則優先級比 extends 高
3.關于規則像在'extends ' 中介紹的根據開頭找到他的組織去看他的規則都有哪些可以自己配置
4.也可以在文件中指定規則,主要注釋要使用 /**/ 形式,并且 eslint + 規則 + 等級,下面例子
就是'no-var' 是不準使用var 的規則,error 就是使用了要報錯的等級
/* eslint no-var: error */
var a = '1'
更多規則:
/* eslint-disable */ -- '該注釋放在文件頂部,eslint不會檢查整個文件'
/* eslint-enable */ -- '重新啟用eslint檢查'
/* eslint-disable eqeqeq */'只禁止某一個或多個規則'
/* eslint-disable-next-line */'下一行禁止eslint檢查'
// eslint-disable-line '當前行禁止eslint檢查'
~~~
>[danger] ##### globals
~~~
1.ESLint會檢測未聲明的變量,并發出報錯,比如node環境中的process,瀏覽器環境下的全局
變量console,以及我們通過cdn引入的jQuery定義的$等;我們可以在`globals`中進行變量聲明
2.但是node或者瀏覽器中的全局變量很多,如果我們一個個進行聲明顯得繁瑣,因此就需要
用到我們的`env`,這是對環境定義的一組全局變量的預設,可以參考下面'env' 字段
~~~
~~~
{
????"globals":?{
????????//?true表示該變量可讀寫,false表示變量是只讀
????????"$":?true,
????????"console":?false
????}
}
~~~
>[danger] ##### env
~~~
1.舉個例子當我們在項目使用了 瀏覽器環境全局變量'window','node 環境global','jquery $',這些某種
環境特帶的讓eslint 知道不是我們用錯了而是這類東西是某環境下的
2.es6 中除了模塊之外的其他特性,同時將自動設置 parserOptions.ecmaVersion 參數為 6
以此類推 ES2017 是 8,而 ES2021 是 12(parserOptions.ecmaVersion 關于它可以看parserOptions)
{
"env": {
"browser": true, // 項目中有代碼在瀏覽器環境運行
"node": true, // 項目中有代碼在 Node.js 環境下運行
"es6": true // 啟動 ES6 全局變量和類型,同時會自動設置解析器為ES6
}
}
~~~
[更多環境配置](https://eslint.bootcss.com/docs/user-guide/configuring#specifying-environments)
>[info] ## 一個整體的配置
~~~
// .eslintrc.js
module.exports = {
env: { // 標記當前代碼最終的運行環境
browser: true, // 代碼運行在瀏覽器環境
es2020: true
},
// 語法解析器配置ts 語法需要自己的語法解析器因此要聲明
// parser: '@typescript-eslint/parser',
extends: [ // 記錄共享配置類似繼承的概念,下面的意思是使用node_modules 模塊安裝的'standard'檢查作為模板
'standard' // 如果需要在多個項目共享一個eslin配置,可以定義一個公共配置文件并在此集成
// 繼承規則配置 不需要單獨配置開關
'plugin:react/recommended'
],
parserOptions: { // 設置語法解析器的相關配置 控制是否允許使用某一個ES版本的語法
ecmaVersion: 11
},
rules: { // 配置eslint中每一個校驗規則的開啟/關閉
'no-alert': "error" // 內置規則名稱: off/warn/error
// // 2 - ERROR 該規則解決React未使用錯誤
// 'react/jsx-uses-react': 2
},
// plugins: [
// // eslint-plugin-react 插件
// 'react'
// '@typescript-eslint'
// ]
global: { // 額外聲明代碼中可使用全局成員 最新版本默認配置已不再體現
// 例如要使用jQuery對象
"jQuery": "readonly"
}
}
~~~
https://developer.51cto.com/art/202103/650933.htm
>[info] ## 參考文章
[eslint 官網](https://eslint.cn/docs/user-guide/)
[從 ESLint 開始,說透我如何在團隊項目中基于 Vue 做代碼校驗](https://mp.weixin.qq.com/s/iwm2UtEEmsJgZx0D7yT1zA)
[eslint 配置文件 -- .eslintrc ](https://segmentfault.com/a/1190000020656606?utm_source=tag-newest)
[eslint 配置文件 -- .eslintrc](https://www.cnblogs.com/taoshengyijiuai/p/8431413.html)
- 工程化 -- Node
- vscode -- 插件
- vscode -- 代碼片段
- 前端學會調試
- 谷歌瀏覽器調試技巧
- 權限驗證
- 包管理工具 -- npm
- 常見的 npm ci 指令
- npm -- npm install安裝包
- npm -- package.json
- npm -- 查看包版本信息
- npm - package-lock.json
- npm -- node_modules 層級
- npm -- 依賴包規則
- npm -- install 安裝流程
- npx
- npm -- 發布自己的包
- 包管理工具 -- pnpm
- 模擬數據 -- Mock
- 頁面渲染
- 渲染分析
- core.js && babel
- core.js -- 到底是什么
- 編譯器那些術語
- 詞法解析 -- tokenize
- 語法解析 -- ast
- 遍歷節點 -- traverser
- 轉換階段、生成階段略
- babel
- babel -- 初步上手之了解
- babel -- 初步上手之各種配置(preset-env)
- babel -- 初步上手之各種配置@babel/helpers
- babel -- 初步上手之各種配置@babel/runtime
- babel -- 初步上手之各種配置@babel/plugin-transform-runtime
- babel -- 初步上手之各種配置(babel-polyfills )(未來)
- babel -- 初步上手之各種配置 polyfill-service
- babel -- 初步上手之各種配置(@babel/polyfill )(過去式)
- babel -- 總結
- 各種工具
- 前端 -- 工程化
- 了解 -- Yeoman
- 使用 -- Yeoman
- 了解 -- Plop
- node cli -- 開發自己的腳手架工具
- 自動化構建工具
- Gulp
- 模塊化打包工具為什么出現
- 模塊化打包工具(新) -- webpack
- 簡單使用 -- webpack
- 了解配置 -- webpack.config.js
- webpack -- loader 淺解
- loader -- 配置css模塊解析
- loader -- 圖片和字體(4.x)
- loader -- 圖片和字體(5.x)
- loader -- 圖片優化loader
- loader -- 配置解析js/ts
- webpack -- plugins 淺解
- eslit
- plugins -- CleanWebpackPlugin(4.x)
- plugins -- CleanWebpackPlugin(5.x)
- plugin -- HtmlWebpackPlugin
- plugin -- DefinePlugin 注入全局成員
- webapck -- 模塊解析配置
- webpack -- 文件指紋了解
- webpack -- 開發環境運行構建
- webpack -- 項目環境劃分
- 模塊化打包工具 -- webpack
- webpack -- 打包文件是個啥
- webpack -- 基礎配置項用法
- webpack4.x系列學習
- webpack -- 常見loader加載器
- webpack -- 移動端px轉rem處理
- 開發一個自己loader
- webpack -- plugin插件
- webpack -- 文件指紋
- webpack -- 壓縮css和html構建
- webpack -- 清里構建包
- webpack -- 復制靜態文件
- webpack -- 自定義插件
- wepack -- 關于靜態資源內聯
- webpack -- source map 對照包
- webpack -- 環境劃分構建
- webpack -- 項目構建控制臺輸出
- webpack -- 項目分析
- webpack -- 編譯提速優護體積
- 提速 -- 編譯階段
- webpack -- 項目優化
- webpack -- DefinePlugin 注入全局成員
- webpack -- 代碼分割
- webpack -- 頁面資源提取
- webpack -- import按需引入
- webpack -- 搖樹
- webpack -- 多頁面打包
- webpack -- eslint
- webpack -- srr打包后續看
- webpack -- 構建一個自己的配置后續看
- webpack -- 打包組件和基礎庫
- webpack -- 源碼
- webpack -- 啟動都做了什么
- webpack -- cli做了什么
- webpack - 5
- 模塊化打包工具 -- Rollup
- 工程化搭建代碼規范
- 規范化標準--Eslint
- eslint -- 擴展配置
- eslint -- 指令
- eslint -- vscode
- eslint -- 原理
- Prettier -- 格式化代碼工具
- EditorConfig -- 編輯器編碼風格
- 檢查提交代碼是否符合檢查配置
- 整體流程總結
- 微前端
- single-spa
- 簡單上手 -- single-spa
- 快速理解systemjs
- single-sap 不使用systemjs
- monorepo -- 工程
- Vue -- 響應式了解
- Vue2.x -- 源碼分析
- 發布訂閱和觀察者模式
- 簡單 -- 了解響應式模型(一)
- 簡單 -- 了解響應式模型(二)
- 簡單 --了解虛擬DOM(一)
- 簡單 --了解虛擬DOM(二)
- 簡單 --了解diff算法
- 簡單 --了解nextick
- Snabbdom -- 理解虛擬dom和diff算法
- Snabbdom -- h函數
- Snabbdom - Vnode 函數
- Snabbdom -- init 函數
- Snabbdom -- patch 函數
- 手寫 -- 虛擬dom渲染
- Vue -- minVue
- vue3.x -- 源碼分析
- 分析 -- reactivity
- 好文
- grpc -- 瀏覽器使用gRPC
- grcp-web -- 案例
- 待續