electron-viteを使ってみる
https://www.memodify.com を個人開発で細々と作っている。自分で使う分にはだいぶ機能は足りてきていて、普通に日々の仕事のメモ帳としてここ数年使ってきている。
最初はNuxt.jsで作り始めた。最初のコミットは2019-01-22だったので、5年くらい開発しているらしい。見返して自分でも驚いた。https://zenn.dev/tmtk75/scraps/f9d01a97d78893 このスクラップがNext.jsへ移行したときの調査。
ということでNext.jsを使っているのだが、いろいろ見てるとAppRouterやTurbopackは不安定だし、メインの最終形はelectron製のデスクトップアプリ[1]なのでSSRとか使わない。ということで現状でNext.jsの機能をほとんど使ってなく、Next.jsをこの先も使い続けるのにちょっと疑問に思ってたところにelectron-viteが目に入ってきたので試してみる。
-
一応 https://memodify.app としてWebにもデプロイはしているが、これはほとんどおまけ。 ↩︎
scaffolding.
npm create @quick-start/electron
生成されたディレクトりでnpm i
してnpm run dev
するとElectronアプリとして起動する。起動速度さすがに早い。
あとhttp://localhost:5173でrendererプロセスが見られる。ブラウザで開くとelectronの起動と見かけが異なる。ロゴとか表示されていない。IPCが実行できずに失敗しているだけで、その辺りを直すと表示されるので問題ない。
Next.jsをやめて最初に困りそうなところはroutingなので、react-routerを調べる。
このチュートリアルで大体必要そうなことはできそうな感触。Tailwind CSS入れてみる。
動いた。ついでにsassも入れて動くの確認。
続いてMUI追加。
npm install --save-dev @mui/material @emotion/react @emotion/styled
TextFieldが動くのを確認。
jestの代わりにvitest入れてみる。
src/test/sum.test.ts
適当に置いてみたら認識してテストできてしまった。
IPCを呼び出すtRPCもなんとか動いた。
createTRPCNext
の代わりにcreateTRPCReact
を使うところで少しハマった。
あとNext.jsだとtrpc.withTRPC(MyApp)
に相当する部分を自前でproviderを追加する必要があるところ、ここも少し調べるのに時間かかった。
<QueryClientProvider client={queryClient}>
<trpc.Provider client={trpcClient} queryClient={queryClient}>
...
そういえばuseRouter
はNext.jsのhookだな。react-router-domベースで実装しないと。
electronなしでrendererだけbrowserでserveして確認したいときは、vite
がインストールされているので、以下で起動してhttp://localhost:5173
npx vite src/renderer
vite.config.js
viteのことよく知らないからviteの設定にもざっと目を通しておく。
main, preload, rendererごとにvite.config.jsを置ける。
electron.vite.config.jsにまとめて書くこともできる。設定が被ったときはどっちが優先されるかは未調査。
asset
お。asset handling、これは便利そうだな。
環境変数
MAIN_VITE_
, PRELOAD_VITE_
, RENDERER_VITE_
でそれぞれ公開先を限定できるのか。
大体把握したので、既存コードをelectron-vite下に移行しようとしたら全然だめだった。
- viteには
process.env
ない。 - PouchDBのimportで失敗してそう。
一気に移行は厳しそうな感触。
PouchDB使ってる限りは今のところ無理そう。
と思ったらworkaroundがあった。
これでなんとか動かすだけなら回避。
MUI Grid2絡みでこれにヒット。
Gridを使うようにして回避。
react-router-domに自分のuse-caseには致命的な仕様があってvite + electronへの移行は難しそうなことが判明。
- electronではhash routerを使う必要あり。browser routerは動かない。
- <a href="#something">...</a>のようなリンクをクリックしたときにroutingが意図通り動かない。not foundになる。
これはNext.jsのrouterに思いっきり依存しているところだったな。
今作ってるやつの移行は無理そうだ。
react-router-domに自分のuse-caseには致命的な仕様があってvite + electronへの移行は難しそうなことが判明。
electron-serveで解決できることが分かった。
というか、今のNext.js版でも同じことしてた。
ということで移行再開。
Bufferを使うためにvite-plugin-node-polyfillsを導入。
viteでESM必須になったので、commonJSのmoduleをなんとかした。
- lunr -> Fuse.js
- mermaid v9 -> mermaid v10
requireを全て消し去った。
ほぼ同名の https://electron-vite.github.io というのもあってこっちのほうがwrap具合が薄そうなので試してみたんだけど、薄すぎて設定が多くなってしまって https://electron-vite.org へ戻った。
私がviteに慣れてなくてうまく使えないだけだと思うのでうまく使える人は前者のほうがあっているかも。
packagte.jsonを眺めると、最終的に以下のような構成になった。順不同
いろいろ早くなって満足。
- react
- electron-vite (https://electron-vite.org)
- react-router-dom
- comlink
- biome
- prettier
- vitest
- tanstack query
- mui
- fuse.js
- unified
- zod
比較検討したもの
- https://electron-vite.org vs https://electron-vite.github.io : 薄さより便利さを選んだ。
- react-router-dom vs tanstack router : routingでのtype safeは魅力だったが、そこまで必要ないかと思いシンプルさを選択
- biome vs eslint : biomeに従えばいいのは楽。import aliasを設定するときに乗り換えた。tailwindcssのクラス名sortに対応したらformatterもbiomeにする予定。
- vitest vs jest : 早いし、ESM対応してるし。
- mui vs 他のUIライブラリ : autocomplete@muiをがっつり使い込んでるので移行しづらい
- zod vs valibot : valibotは軽量という触れ込みだけど、今のところあまりそこにメリットを見いだせていない。