# 從 pnpm 設定到 nexe 打包:打造可獨立運行的 Next.js Standalone 專案 ## 更改 pnpm 設定 最一開始使用 pnpm 編出來的 standalone,發現只能在當前目錄中運行,如果把 standalone 目錄整個移到新的資料夾空間將會導致無法運行。這是因為 pnpm 原本的 node_modules 機制 (軟連結對照) 所造成的,我們可以透過更改 pnpm 設定讓 node_modules 資料夾結構跟原本 npm 的結構一樣 ### 更改 pnpm-workspace.yaml 加入以下設定 ``` nodeLinker: hoisted ``` - nodeLinker: 將常用依賴提升 (hoisted) 到最上層的 node_modules,與 npm 類似 ## 更改 next.config.ts 在輸出 standalone 之後,運行程式時發現,有些 module 會無法運行,筆者就剛好遇到 java-bridge 這個套件需要 jar 檔而沒有複製到的問題,這時候就可以在 next.config.ts 當中把套件的路徑加入到 outputFileTracingIncludes 設定中,這樣建置時就會把相關檔案複製到輸出目錄當中。 ``` { outputFileTracingIncludes: { "/api/**/*": [ "../../node_modules/java-bridge/**", // 加入有額外檔案的套件路徑 "../../node_modules/raccoon-dcm4che-bridge/**", ], "*": [ "public/**/*", ".next/static/**/*", ] } } ``` ## 更改路徑相關的程式碼 :::danger 這段非常重要,沒更改的話,基本上讀寫檔皆無法正常運作 ::: - 更改所有的 `process.cwd()` 程式碼,因為 nexe 會使用虛擬 filesystem 包裹起來,如果使用 `process.cwd()` 的話會得到 `/snapshot` 開頭的路徑 - 這時,必須寫個 function 來判斷是否在虛擬 filesystem 中,並用 process.execPath 替代 ``` export const getWritableRoot = () => { const cwd = process.cwd(); // 如果當前路徑是在 nexe 的虛擬 filesystem 中,返回執行檔的真實目錄 if (cwd.startsWith("/snapshot")) { return path.dirname(process.execPath); } return cwd; } ``` ## 使用 nexe 包裹成單一執行檔 因為筆者建完 standalone 之後,覺得再附上單一執行檔的話,就可以很方便地用成一個 zip 給別人使用,所以就嘗試使用 nexe 來包裹 :::info 請務必先安裝以下工具 (windows) - NASM: https://www.nasm.us/pub/nasm/releasebuilds/ - python > 3.9 - MS build tool: 可參考 https://github.com/nexe/nexe?tab=readme-ov-file#windows ::: - 進到 `.next/standalone` 運行以下指令 ``` nexe server.js --build -t windows ``` :::info 如果要把 public 和 standalone 都打包進去,可以運行以下指令 ```bash nexe .next/standalone/server.js \ -r "public/**/*" \ -r ".next/standalone/**/*" \ -o next-app-executable ``` ::: - 建置完之後,就會多出一個 server.exe,建議透過 cmd 執行,可以方便查看錯誤,如果使用雙擊打開蠻有機會出現跳出 cmd 小黑窗直接消失的情況 :::warning 另外,非常建議將整個專案與 standalone 一起打包。筆者在執行時,曾遇過 module not found 或 .next 資料夾遺失的問題,最後乾脆把 nexe 當成替使用者自動下載 Node.js 的方案來解決。 :::
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up