シリアル通信実装でハマった(Nuxt3 + TypeScript + Electron)
環境
- PC: Windows(x64) / Mac(arm64)
- Yarn: 1.22.19
- Node.js: 20.5.1
- Nuxt.js: 3.7.0
- TypeScript: 5.2.2
- Electron: 26.1.0
- serialport: 12.0.0
はじめに
Nuxt3 + TypeScript + Electronで開発中のデスクトップアプリにserialportを導入しようとした。
serialport
Access serial ports with JavaScript. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them!
そこで、yarn add -D serialport
でをインストールして、mainプロセスでサンプルコードを実行した。
SerialPort.list().then((ports) => {
ports.forEach((port) => {
console.log(port.path);
});
});
{
"name": "nuxt-app",
"private": true,
"packageManager": "yarn@1.22.19",
"main": "dist-electron/main.js",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev --dotenv ../.env src",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"format": "prettier --write .",
"lint": "eslint ./**/*.{vue,ts}"
},
"devDependencies": {
"@mdi/font": "^7.2.96",
"@nuxt/devtools": "latest",
"@nuxtjs/eslint-config-typescript": "^12.1.0",
"electron": "^26.1.0",
"electron-rebuild": "^3.2.9",
"eslint": "^8.48.0",
"eslint-plugin-vue": "^9.17.0",
"nuxt": "^3.7.0",
"nuxt-electron": "^0.6.0",
"prettier": "^3.0.3",
"sass": "^1.66.1",
"serialport": "^12.0.0",
"typescript": "^5.2.2",
"vite-plugin-electron": "^0.14.0",
"vite-plugin-vuetify": "^1.0.2",
"vuetify": "^3.3.15"
},
"dependencies": {}
}
エラー内容
Error: No native build was found for platform=win32 arch=x64 runtime=electron abi=116 uv=1 armv=8 libc=glibc node=18.16.1 electron=26.1.0
どうやらplatform=win32 arch=x64
用のNative Buildが見つからない...
Windows特有のエラーなのかと思い、Macでも同じ環境で確かめてみた。
Error: No native build was found for platform=darwin arch=arm64 runtime=electron abi=116 uv=1 armv=8 libc=glibc node=18.16.1 electron=26.1.0
同一エラーがでている...
以前Python(pyserial)でシリアル通信を行ったときはこのようなエラーは発生しなかった。
試したこと
-
Native Moduleをrebuildする
- Electron公式ドキュメントusing-native-node-modulesを読み、@electron/rebuildを導入してみた
-
node_modulesからserialportを削除してinstallしなおす
rm --recursive node_modules/serialport
yarn install --no-save --build-from-source serialport@12.0.0
解決策
viteのbuild時にserialportをbundleさせず、外部から読み込むようにnuxt.config.ts
に設定した。
electron: {
build: [
{
entry: "electron/main.ts",
+ vite: {
+ build: {
+ rollupOptions: {
+ external: ["serialport"],
+ },
+ },
+ },
},
],
},
これで無事にbuildできるようになった!
何が問題だったのか
まずserialport公式ドキュメントguide-installationを読むと、serialportはNative Moduleであり、PlatformやArchitectureに依存したコードを含んでいることがわかる。
This assumes you have everything on your system necessary to compile ANY native module for Node.js.
例えば、Windowsの場合だと、node-gypが必要である。また、node-gypをインストールするためにはVisual C++が必要となる。(結構面倒...)
Node-Serialport supports Windows 10+. Precompiled binaries are available, but if you want to build it from source you'll need to follow the node-gyp installation instructions. Once you've got things working, you can install Node-Serialport from source with:
npm install serialport
Node-gyp's documentation doesn't mention it, but it sometimes helps to create a C++ project in Visual Studio so that it will install any necessary components not already installed during the past two hours of setup. This will solve some instances ofFailed to locate: CL.exe
.
上記のように、環境ごとに必要なツールを用意することで今回のエラーは解決すると考える。
しかし、実行するプラットフォーム/アーキテクチャによって必要なツールを入れることは面倒である。
- 結論:必要なNative Moduleが少量の場合はbundleさせない
複数のNative Moduleを利用する場合
Native Moduleのダウンロード/インストールにたくさんの時間を要してbuild時間が長くなるため要検討!
Nuxt3はbuildツールとしてViteを採用しているため、Viteのbuild時にserialportをbundleさせないようにする。そうすることで、build時に必要なNative Moduleを動的にダウンロード/インストールするようになり、プラットフォーム/アーキテクチャに依存せずbuildすることができる。