前言
最近在寫一個部落格的專案,前端用的 vue+typescript+element-ui
,後臺則選擇了 koa2+typescript+mongoDB
的組合。寫這篇部落格的目的也是在寫後臺的過程遇到一些問題,查了很多資料才解決。於是權當總結,亦是記錄,可以給別人做一個完整的參考。
基本資訊
這裡列出來的是會用到的一些配置資訊,畢竟一直都在更新,可能這裡說的以後某個版本就不支援了。
"nodemon" : "^1.18.3",
"ts-node" : "^7.0.1",
"typescript" : "^3.1.1"
"node" : "9.0.0"
複製程式碼
問題描述
這次遇到的問題其實都和typescript有關。koa2已經出來很久了,開發基本成熟,但是這次找資料的時候鮮有發現使用typescript開發的,即便有,也都很簡單,而且沒法解決我的問題。
那言歸正傳,使用ts開發koa,因為不涉及webpack打包編譯,所以就會遇到幾個問題:
- 編譯
- 實時重新整理,重啟伺服器
- debugger
這些確實是初期很困擾我的地方,使用node開發,最簡單的無非是 node xxx.js
,進一步也就是熱更新。但引入ts後就需要考慮編譯和實時重新整理的問題。畢竟不像每改一點程式碼,就手動重啟伺服器,手動編譯。
解決方案
以下是我的解決方案,後面我會說一下為什麼這樣寫,如果來不及看或者只想要答案的話複製就行。
"watch" : "ts-node ./app/index.ts",
"start" : "nodemon --watch app/index.js",
"build" : "tsc",
"debugger" : "nodemon --watch ./app -e ts,tsx --exec node --inspect -r ts-node/register ./app/index.ts",
"watch-serve": "nodemon --watch './app/**/*' -e ts,tsx --exec ts-node ./app/index.ts"
複製程式碼
那我們一個一個來說。
npm run watch
這個命令就是在本地使用ts-node
啟動一個伺服器。來看一下對ts-node
的描述。
TypeScript execution and REPL for node.js, with source map support. Works with typescript@>=2.0.
這是一個在node.js
的執行和互動的typescript環境,簡而言之就是為了ts而生的!!
那這條命令就是根據當前的入口執行程式,唯一的一個問題是,不支援熱更新。所以pass。
npm run build
&& npm run start
這倆放一起說是因為相關性比較高。可以說是相互依賴的關係吧。
先說第一條命令,很簡單,就是編譯當前的ts專案檔案,輸出目錄需要在tsconfig.json
中配置。我給大家看下我的執行結果。
app
是我的專案檔案,執行命令後,會在根目錄下建立dist
資料夾存放我編譯好的js檔案,開啟就是這樣。
現在再說第二條命令,就是根據編譯好的檔案入口啟動伺服器。並且支援熱更新,但是,注意這裡有個但是
,它只支援編譯過後的檔案的熱更新,其實就是用js開發koa的啟動命令,那這時候在原始檔中的任何修改都不會有作用,所以pass。
npm run watch-serve
重點來了,這才是解決問題的關鍵!!!
這裡完美的解決了程式碼的熱更新,實時編譯,伺服器重啟等問題。很好的提升了開發體驗。
這個解決方案有一些中文部落格提到,但是當初用的時候不知道為啥這樣用,導致後期犯了一些現在看來很低階的錯誤,這個就不提了。不過確實沒人說明這段命令的意思,直到昨天碰到一個問題,我才好好正視這個惡魔。
nodemon
和ts-node
前文都介紹過了,我在這裡只會針對具體的配置解釋一下。原本我的理解是這裡用逗號分隔了兩個不同的命令,但是我太天真了。來看一下文件的介紹。
By default, nodemon looks for files with the .js, .mjs, .coffee, .litcoffee, and .json extensions. If you use the --exec option and monitor app.py nodemon will monitor files with the extension of .py. However, you can specify your own list with the -e (or --ext) switch like so:
nodemon -e js,jade
複製程式碼
Now nodemon will restart on any changes to files in the directory (or subdirectories) with the extensions .js, .jade.
nodemon
有預設吃的幾種檔案型別,分別是 .js, .mjs, .coffee, .litcoffee, and .json
,而我這裡用的 .ts
,並不在預設支援檔案裡,因此這裡使用 -e
來指定我需要擴充套件的檔案型別,這裡的逗號也不過是用來分隔不同型別用的。那這裡提到了 --exec
這個配置。原文裡說如果用nodemon
啟動app.py
這個檔案,那麼將預設支援.py
這種擴充套件型別。另外文件裡還寫了別的。
nodemon can also be used to execute and monitor other programs. nodemon will read the file extension of the script being run and monitor that extension instead of .js if there's no nodemon.json:
nodemon --exec "python -v" ./app.py
複製程式碼
Now nodemon will run app.py with python in verbose mode (note that if you're not passing args to the exec program, you don't need the quotes), and look for new or modified files with the .py extension.
這裡說明,除了預設支援的擴充套件,通過這個配置,可以支援和正在執行的指令碼一樣的擴充套件。並且,如果擴充套件程式不需要傳引數的話,可以不寫單引號。
綜上所述,一個命令用於增加支援的檔案型別,一個配置用來執行和監視其他型別的程式。
至於---watch
這個引數。
By default nodemon monitors the current working directory. If you want to take control of that option, use the --watch option to add specific paths:
nodemon --watch app --watch libs app/server.js
Now nodemon will only restart if there are changes in the ./app or ./libs directory. By default nodemon will traverse sub-directories, so there's no need in explicitly including sub-directories.
Don't use unix globbing to pass multiple directories, e.g --watch ./lib/*, it won't work. You need a --watch flag per directory watched.
這裡面需要注意的有兩點,一是nodemon
會預設監視當前指令碼檔案執行的資料夾,另一個就是如果要指定具體的資料夾時,需要些詳細的路徑,比如絕對路徑或者相對路徑,絕對不要使用萬用字元。因此我命令列中的使用是無效且違反規則的,然而非要這樣寫也不影響執行。
原本到這也就結束了,然而昨天用了一個npm包,我想看看怎麼執行的,於是遇到了debugger
的問題,這也是迫使我去認真弄懂這段命令的原因。
npm run debugger
基本的除錯方式網上到處都有,我就不說了,問題還是匯入typescript之後,讓一切都混亂起來。我最開始嘗試了以下幾種命令:
'nodemon --inspect --watch ./app -e ts,tsx --exec ts-node ./app/index.ts'
'nodemon --watch --inspect ./app -e ts,tsx --exec ts-node ./app/index.ts'
'nodemon --watch ./app -e ts,tsx --exec ts-node --inspect ./app/index.ts'
複製程式碼
這些都可以自己試著執行一下,反正也沒啥用。然後就是今天一直想著這件事,換了幾個關鍵字google,找到這兩個地方。
感謝stackoverflow和github,相互印證著看好像就明白是怎麼回事了。
這裡說下-r
這個引數:
這裡用於預載入一個模組,並且可以多次使用這個引數,那說回我寫的命令裡,ts-node/register
就是一個模組,或者不嚴謹的說,register
是ts-node
下的一個方法。這裡就是使用node預載入ts-node的register模組用來執行ts程式,並且開啟debugger模式。
後語
至此為止,在編譯,熱更新,debugger方面的坑應該是踩完了,希望後面的人看了我寫的文章能少走些彎路吧。如果有些的不對的地方可以留言指正。所有的原始碼我應該暫時不會放出,至少等我寫完吧。
就醬紫,