如何使用 pkg 將 Node.js 專案打包成可攜式執行檔

如何使用 pkg 將 Node.js 專案打包成可攜式執行檔

目錄

為了在沒有 Node.js 的環境中執行專案,我們可以使用 pkg 將專案打包成可攜式執行檔。 雖然 pkg 已經停止維護了,但是它仍然是一個很好用的工具,然而使用上有不少需要注意的地方,這篇文章將會介紹如何使用 pkgNode.js 專案打包成可攜式執行檔。

轉成 CommonJS 並合併成單一檔案

由於 pkgNode.js 中對 ESM 的支援度不是很完整,為了避免自己的專案及 node_module 中的專案有使用到 ESM 造成的錯誤,我們可以將專案透過 webpack 搭配 Babel 轉換成 commonjs 並合併成一個檔案來避免這個問題。

  • 首先安裝 webpackBabel 相關套件
npm install -D webpack webpack-cli copy-webpack-plugin @babel/cli @babel/core @babel/node @babel/preset-env babel-loader
  • root 創建 webpack.config.js 檔案
const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
  mode: "development",
  // mode: 'production',
  entry: "./src/index.mjs",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.js",
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
  resolve: {
    extensions: [".js", ".mjs"],
  },
  target: "node",
  plugins: [
    new CopyWebpackPlugin({
      patterns: [
        { from: "path/to/your/assets/file.txt", to: "file.txt" },
        { from: "path/to/your/assets/folder/", to: "folder/" },
      ],
    }),
  ],
};
  • root 創建 .babelrc 檔案
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        },
        "modules": "commonjs"
      }
    ]
  ]
}

接著執行 webpack 後,將會在 dist 資料夾中看到 index.js 以及一些複製的檔案。 查看 index.js 會發現已經將自己的以及 node_module 中的檔案轉換成 commonjs 並合併成一個檔案。

npx webpack

使用 pkg 打包檔案

完成上述步驟後,就可以使用 pkg 打包檔案了。

  • 首先安裝 pkg
npm install -D pkg
  • root 創建 pkg.config.json 檔案

會建議不要在 package.json 中設定 pkg 的設定,因為這樣會讓 package.json 變得不容易管理,所以建議將 pkg 的設定獨立出來。 設定 assets 以及 targetsassets 是要複製到執行檔中的檔案,targets 是要打包的平台 (需要注意在 arm64 的平台上可以打包 x64 的執行檔,但是在 x64 的平台上無法打包 arm64 的執行檔)。 並且 node 的版本需要設定成 18,在 Windows 上可以使用 nvm 切換版本,在 macOSLinux 上建議使用 asdf 切換版本。

{
  "pkg": {
    "assets": ["dist/file.txt", "dist/folder/**/*"],
    "targets": [
      "node18-win-x64",
      "node18-macos-x64",
      "node18-linux-x64",
      "node18-win-arm64",
      "node18-macos-arm64",
      "node18-linux-arm64"
    ],
    "outputPath": "dist"
  }
}
  • 使用 pkg 打包檔案
npx pkg dist/index.js --config pkg.config.json

打包完成後,將會在 dist 資料夾中看到打包好的執行檔。

補充

雖然 pkg 的指令很簡單,但是在打包的過程中,還是不免會碰到一些相容性及版本打包的問題,但是只要透過上述第一步驟的轉換,就可以避免大部分的問題。 另外,若是在專案中有使用 __dirname__filename 這兩個變數,需要注意根據 README 在打包後這兩個變數會變成 /snapshot,所以會建議使用下面的方法來取代 __dirname__filename 等變數。

import path from "path";

export function getAppDir() {
  if (process.pkg && process.pkg.entrypoint) {
    return path.dirname(process.pkg.entrypoint);
  }
  return process.cwd();
}
標籤 :
comments powered by Disqus

相關文章

小米二合一無線充電寶 30W 10000mAh:完美結合行動電源與無線充電座的體驗

小米二合一無線充電寶 30W 10000mAh:完美結合行動電源與無線充電座的體驗

今天我要帶大家探索一款新的科技產品,那就是小米的二合一無線充電寶 30W 10000mAh。自從我換了 Google Pixel 6,我就一直對無線充電充滿了好奇心。但市面

閱讀更多
使用 youtube-dl / yt-dlp 下載 Youtube 最佳畫質與音質的影片

使用 youtube-dl / yt-dlp 下載 Youtube 最佳畫質與音質的影片

youtube-dl 是一個開源可以下載 Youtube 影片的工具,然而由於版權問題,導致專案被刪除,有神人將專案 fork 出來,並且繼續維護,所以改用 yt-dlp 來取代。 youtube-dl / yt-dlp 不只可以下載 Youtube

閱讀更多
為什麼 clone 下來的檔案不是正確的格式?認識 Git LFS

為什麼 clone 下來的檔案不是正確的格式?認識 Git LFS

最近遇到同事 git clone 一個專案,發現 clone 下來的壓縮檔居然是文字檔案!但我們在遠端看到的是壓縮檔,為什麼會這樣呢?原來是因為專案使用了 Git LFS,所以在

閱讀更多