五分鐘瞭解 Node.js Shebang

本文最初發佈於Medium網站,經原作者授權由InfoQ中文站翻譯並分享。

圖片

JavaScript是一種解釋性語言,需要將其源代碼提供給某些解釋器才能運行。如果要使用Node.js運行JavaScript文件,通常會運行以下命令:

$ node yourfile.js

輸入解釋器(node)的名稱後,你就明確告訴了外殼如何運行腳本。

但是這些知識可以放在腳本本身中,這樣就可以像運行二進制文件一樣直接運行它:

$ ./yourfile.js

僅當你對該文件有執行權限(例如,可以使用chmod u+x yourfile.js設置)並設置了正確的“Shebang”時,此方法纔有效。

Shebang

Shebang或hashbang(#!代碼的英文發音)是文件的第一行,它告訴OS使用哪個解釋器。它通常看起來像這樣:

#!/absolute/path/to/the/interpreter [optional params]

Shebang是一項操作系統特性,可用於運行任何解釋語言:Python、Perl等。對於Node.js,它可以(但通常不會)看起來像這樣:

#!/usr/bin/node

只有Shebang在文件的第一行時,Node.js纔會高興地將其忽略爲註釋(即使它前面有空行或//comment行也不會起作用)。瀏覽器也會將其忽略(Chrome74+,FF67+)。

多數人在/usr/bin/node上都有一個Node.js二進制文件或符號鏈接。如果Node.js不在/usr/bin/node上,操作系統就會抱怨了。例如bash會說bad interpreter: No such file or directory script won’t execute。但有沒有辦法告訴操作系統使用Node.js運行腳本,而不用在乎它安裝在哪裏呢?

#!node是沒用的,因爲Shebang需要絕對路徑。

認識一下env吧

env主要用於在修改後的環境中運行命令。這裏的重點是“命令”,因爲env幾乎總是位於/usr/bin/env,而“命令”可以是PATH上的任何內容。

如果我們不是寫/usr/bin/node而是寫/usr/bin/env node,我們就會告訴OS運行env,而env將運行node,最後node將依次執行腳本。

簡單來說

這是Node腳本最常見的Shebang:

#!/usr/bin/env node

但是,env還可以使用其他一些技巧。

將參數傳遞給Node.js

將-S選項傳遞給env會使它解析之後發生的一切,從而打開一扇新的大門:將參數傳遞給命令。

例如,假設我們要運行帶有特殊標誌的node,以在運行當前文件時啓用ESM模塊。我們可以使用這個Shebang:

#!/usr/bin/env -S node --experimental-module

再舉一個例子:如果我們想在運行當前腳本之前運行另一個腳本,可以使用Node的-r選項:

#!/usr/bin/env -S node -r ./my/other/file.js

或打開檢查口:

#!/usr/bin/env -S node --inspect

請注意,如果你運行諸如nodeyourfile.js之類的腳本,Node.js將不會嘗試解析Shebang中的參數,而只會忽略它。內核在運行文件之前使用Shebang來確定如何運行它。

設置環境變量

還記得我們說過env可以在修改後的環境中運行命令嗎?實際上這就是它名稱的來源,而且它的功能非常強大。假設我們希望腳本以生產模式運行,我們可以設置NODE_ENV環境變量:

#!/usr/bin/env -S NODE_ENV=production node

否則,運行腳本時NODE_ENV將爲undefined或使用用戶終端的設置。
Node.js支持許多環境變量。例如,我們可以使用NODE_OPTIONS傳遞下列CLI標誌:

#!/usr/bin/env -S NODE_OPTIONS=--experimental-modules node

從一個空環境開始

如果我們希望腳本在運行時不訪問用戶終端上的任何環境變量,則可以使用-i標誌來運行它,該標誌代表“忽略環境”:

#!/usr/bin/env -S -i node

符號-相當於-i,所以我們也可以這樣寫:

#!/usr/bin/env -S - node

強制禁用DEBUG

也許我們不想清除所有環境變量,但要屏蔽其中一些。例如DEBUG(如果你使用的是流行的debug包)。也許我們不希望腳本用戶將DEBUG作爲腳本運行時設置標誌。那麼我們使用-u標誌代表未設置的環境變量。

#!/usr/bin/env -S -u=DEBUG - node

如果用戶以DEBUG=* ./yourfile.js運行腳本,他們將看不到任何調試信息,但你還是可以用DEBUG=* node ./yourfile.js運行腳本,從而看到DEBUG輸出。

鎖定Node.js運行時版本

有時你想鎖定用於運行腳本的node版本。在NPM@3之前,我們可以使用engineStrict,但是該功能已移除,現在我們只能在package.json中設置engines,它可能位於腳本旁邊也可能不在,取決於engine-strictconfig配置標誌的設置。

但是有一種更簡單的方法。由於node也是NPM包,並且npx允許運行任何NPM包,因此你可以編寫:

#!/usr/bin/env -S npx node@6

這可能會在運行腳本後嘗試下載請求的Node版本(因此,如果NPX緩存中不存在所請求版本的Node,則無法在沒有互聯網連接的情況下運行)。
提示:你可以使用process.version檢查節點版本

使用TypeScript運行它

沒有規則說我們必須運行node。假設TypeScript和TS Node全局可用(npm -i g typescript ts-node),我們可以指定ts-node作爲解釋器:

#!/usr/bin/env ts-node

並讓它作爲TypeScript程序運行文件。
在這些示例中,文件都可以使用.js擴展名或你喜歡的其他任何文件類型,甚至可以沒有擴展!

原文鏈接:《Node Shebang》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章