node
dist/
node $entryFile.js
@babel-core-${version}.zip
.yarn/
.pnp.cjs
package.json
yarn.lock
node $entryfile.js
yarn node
compilerOptions
如何在 yarn 2+ 直接使用
node
執行建置/編譯完成後的 js 檔案一些雷跟背後原理解釋
晚點可能整理上部落格
我想把我 nest js 的 code 搬到 Docker 上,俗稱 containerize
但我在 build image 的過程中遇到問題:我想直接將編譯完的
dist/
複製到執行環境,並直接透過node $entryFile.js
來執行但卻會遇到 module not found
我第一反應就是「我忘記搬 node_modules 了,所有 module source 都在 node_modules 裡,只要搬過去就可以解決問題。」
.yarn 下也都只有 .zip 的壓縮包
那麼問題來了:yarn 到底是怎麼拿到 source code 並執行檔案的?
yarn 2+ 靠的是用 .pnp.cjs 這個 file 記錄所有 dependency 名稱及其對應的位置
舉例來說,下圖這個 entry
記錄了 babel 的 core module 放在
@babel-core-${version}.zip
下的哪個位置Okay, makes sense
於是我將
.yarn/
跟.pnp.cjs
也一起搬到執行環境裡(後來發現
package.json
,yarn.lock
也需要搬進去)node $entryfile.js
依舊不能執行還是會跳 module not found 的錯誤
其實我執行前就在想 node 居然這麼有智慧,知道怎麼進 zip 找檔案嗎yarn node
(ref)是以 yarn 的環境執行 node,並在執行前將所有 pnp 的設定都處理好
最後這個錯有點令人哭笑不得
總之我的開發環境主要是用 esmodule,所以我在 root package.json 中有設定 "type": "module"
所以直接 node 執行就會跳 export not defined
剛剛走了個彎路是,我在看到 export not defined 的時候第一反應是改 tsconf 設定,把編譯目標改成 esmodule
具體改法是在
compilerOptions
中設定1. module: ESNext (或任何你想用的版本,ref)
2. moduleResolution: bundler (或任何你想用的形式,ref)
兩個都要設,缺一不可
要在 PnP 環境下直接執行 transpiled code 所需要的最少 source file
1. packages.json
2. .pnp.cjs
3. yarn.lock
4. .yarn/cached/
5. .yarn/unplugged/