简体   繁体   中英

Serving static files in Electron (React app)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM