I am working on a project (just for my own interest) to make a faster searching file explorer
. I am used to making my web-projects in Nuxt, so I wanted to try if I could combine electron with Nuxt
to make a nice simple application.
For this project, I need to do some server side rendering (getting directories and drives from the users computer). I do this by using the integrated server api routes
from nuxt. This basically works the same as a rest api, so i can just fetch from my frontend to that route.
Works verry nice in development mode in the browser! But when I want to fetch the directories from the server side api, the functionality does not work because it cannot host the server-side.
Electron also relies on the 'nuxt generate'
command, because electron needs an index.html. When trying to use 'nuxt build'
instead, it does not create the required index.html anymore
.
Any one knows a solution so this still works? You can play around at my github repository.
To run the functionality in the browser, use the startup command yarn dev
, and to run it using electron, use yarn generate
, then use yarn start
to run the application.
I tried multiple approaches, and after a couple of days I got it to work.
My first approach, was to use import { fork, spawn } from 'child_process'
(one of the fork or spawn methods from child_process) to spin up the server that allows SSR by running nuxt build
(which generates .output/server/index.mjs
) and run it using:
fork(path.join(process.env.ROOT, '.output/server/index.mjs'))
This worked great when running electron .
in my package.json as a command, because it did spin up the server, and by using window.loadURL('http://localhost:3000')
(instead of the index.html), the SSR was working and the frontend page was loaded.
But the problem was that fork or spawn from child_process are not working after packaging the app using electron-builder. This is because the environment does not contain node anymore after building the package in an app.
My second approach (after trying to make approach 1 work for 2 days) was to use const { pathToFileURL } = require('url')
to load the module and to call the script in the main.js electron file. This is done by dynamically importing the script and running it by using:
const modulePath = path.join(process.env.ROOT, '.output/server/index.mjs');
const moduleUrl = pathToFileURL(modulePath).href;
const { default: startServer } = await import(moduleUrl);
if (typeof startServer === 'function') {
startServer();
}
This method works in development mode, but also after packaging the application using electron-builder!. The only added configuration that you need to do is including the following text in your package.json:
"build": {
"extraResources": [
".output/server/**"
]
}
Conclusion: make sure you use the second approach to make SSR work with Nuxt 3 and Electron. Do not forget to run the server script first, and then create the window, so make for example a function called startWebServer and a function called createWindow to run this code:
app.whenReady()
.then(startWebServer)
.then(createWindow)