I am working on a project where I need to build a desktop app in Electron. The majority of functionality will be built in React, but there will be a part where we need to integrate a 3rd party static HTML magazine. I need some advice on how to do this. I am building a proof of concept app currently and I have based it on this https://github.com/chentsulin/electron-react-boilerplate
how would I add that on /static/ I server static HTML files. I know I could do it in express, but I really don't want to include the entire express framework just for serving static files.
I was looking at this https://www.npmjs.com/package/serve-static but have no Idea how to integrate it in my react app and bundle it into electron app.
I found another solution without using express
or serve-static
, we only need to cusomize Electron built-in interceptFileProtocol()
to serve static contents.
Code :(main.js)
(I use the electron-quick-start as Electron template)
function createWindow () {
window = new BrowserWindow({ width: 800, height: 600 })
window.loadURL(url.format({
pathname: 'index.html', /* Attention here: origin is path.join(__dirname, 'index.html') */
protocol: 'file',
slashes: true
}))
window.on('closed', () => {
window = null
})
}
app.on('ready', () => {
protocol.interceptFileProtocol('file', (request, callback) => {
const url = request.url.substr(7) /* all urls start with 'file://' */
callback({ path: path.normalize(`${__dirname}/${url}`)})
}, (err) => {
if (err) console.error('Failed to register protocol')
})
createWindow()
})
Reference : protocol.interceptFileProtocol()
Explaination :
Normally, if you run React app as a normal website, all static contents should be served by HTTP [GET]
method. Though they use relative paths, your HTTP server will handle the path parsing work.
However, when running under Electron, things change.
Your static contents usually use relative path like ./picture.jpg
, Electron will use file
protocol instead of HTTP
protocol and find the file under root path like C://.//
. So static contents like ./picture.jpg
won't be loaded correctly.
By customizing interceptFileProtocol()
, all static contents' requests will be pointed to your working directory instead of Windows(or other OS) root.
Finally, I'm not sure whether it's a good solution for all Electron projects, but if you already have a React
project (or some other SPA) and want to wrap it with Electron, this solution would be fine to use.
As an addition to the great answer from @yeze322 above, here a working sample for all not so familiar with node and electron (like me). It took me some time to find out the correct require statements.
main.js (code from @yeze322 plus required imports)
const { app, BrowserWindow, protocol } = require('electron')
const path = require('path')
const url = require('url')
let mainWindow
function createWindow() {
mainWindow = new BrowserWindow({ width: 800, height: 600 })
mainWindow.loadURL(url.format({
pathname: 'index.html', /* Attention here: origin is path.join(__dirname, 'index.html') */
protocol: 'file',
slashes: true
}))
mainWindow.on('closed', function () {
mainWindow = null
})
}
app.on('ready', () => {
protocol.interceptFileProtocol('file', (request, callback) => {
const url = request.url.substr(7) /* all urls start with 'file://' */
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (err) => {
if (err) console.error('Failed to register protocol')
})
createWindow()
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})
In your main file you have
const app = require("app")
app.on("ready", () => {
...
Here you can start the server like you would do in node.js
const serveStatic = require('serve-static')
// or
const express = require('express')
...
}
将3rd patry资源放在resources目录下可以解决问题
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.