在 Electron 中提供静态文件(React 应用程序)

Posted

技术标签:

【中文标题】在 Electron 中提供静态文件(React 应用程序)【英文标题】:Serving static files in Electron (React app) 【发布时间】:2016-11-07 08:52:35 【问题描述】:

我正在做一个需要在 Electron 中构建桌面应用程序的项目。大部分功能将在 React 中构建,但有一部分我们需要集成 3rd 方静态 html 杂志。我需要一些关于如何做到这一点的建议。我目前正在构建一个概念验证应用程序,并且基于此https://github.com/chentsulin/electron-react-boilerplate

如何在 /static/ 服务器上添加静态 HTML 文件。我知道我可以在 express 中做到这一点,但我真的不想仅仅为了提供静态文件而包含整个 express 框架。

我在看这个https://www.npmjs.com/package/serve-static,但不知道如何将它集成到我的反应应用程序中并将其捆绑到电子应用程序中。

【问题讨论】:

嘿@ales,我想知道以下答案对您有用吗?在开发模式下,我使用 web pack 给我错误“找不到模块反应”,意味着模块解决问题,而没有拦截协议它可以工作,知道吗? 【参考方案1】:

我找到了另一个不使用expressserve-static 的解决方案,我们只 需要自定义 Electron 内置的 interceptFileProtocol() 来提供静态内容。

代码:(main.js)

(我使用electron-quick-start 作为 Electron 模板)

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()
)

参考: protocol.interceptFileProtocol()

说明

通常,如果您将 React 应用程序作为普通网站运行,则所有静态内容都应由 HTTP [GET] 方法提供。尽管它们使用相对路径,但您的 HTTP 服务器将处理路径解析工作。

但是,在 Electron 下运行时,情况会发生变化。

你的静态内容通常使用相对路径,如./picture.jpg,Electron 将使用file 协议而不是HTTP 协议,并在根路径下查找文件,如C://.//。所以像./picture.jpg 这样的静态内容将无法正确加载。

通过自定义interceptFileProtocol(),所有静态内容的请求都将指向您的工作目录,而不是Windows(或其他操作系统)根目录。

最后,我不确定它是否适合所有 Electron 项目,但如果您已经有一个 React 项目(或其他一些 SPA)并想用 Electron 包装它,这个解决方案可以使用。

【讨论】:

这对我有用,但后来我在 index.html 中使用相对路径要求我的索引 js 文件时遇到了麻烦。通过使用require('electron').remote.app.getAppPath() 获取应用程序路径,最终要求它使用绝对值 你在哪里添加@ChrisDolphin?我在这里遇到了一个大问题,在开发模式下运行良好,但打包后应用程序无法运行,让我抓狂 在这里工作,我更改了 url = path.join(require('electron').remote.app.getAppPath(), WEB_FOLDER, url),谢谢,打包应用程序时工作 在这里工作,我更改了 url = path.join(require('electron').remote.app.getAppPath(), WEB_FOLDER, url),谢谢,打包应用程序时工作 嗨,我发现使用registerFileProtocol(语法与interceptFileProtocol 相同)创建自定义app 协议更容易,因此它不会干扰file://。此外,您可能需要删除 URL 的查询参数,例如 app://foobar.js?version=2,您应该删除 ?version=2。例如,在 Electron 应用程序中安装 MathJax 对我很有用。【参考方案2】:

作为对上述@yeze322 出色答案的补充,这里有一个适用于所有不太熟悉节点和电子的人(比如我)的工作示例。我花了一些时间才找到正确的 require 语句。

main.js(来自@yeze322 的代码加上所需的导入)

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()
  
)

【讨论】:

没什么私人的-但这应该只是对@yeze322的回答的评论。我花了一些时间在两个答案之间寻找我应该使用哪个答案;) 谢谢,我能够使用它通过 Electron 运行 Blazor WebAssembly 应用程序。将 Blazor WebAssembly 应用程序制作成静态文件后。【参考方案3】:

在你的主文件中

const app = require("app")
app.on("ready", () => 
  ...

在这里你可以像在 node.js 中一样启动服务器

  const serveStatic = require('serve-static')
  // or
  const express = require('express')
  ...

【讨论】:

【参考方案4】:

把第3个patry资源放到resources目录下就可以解决问题了

【讨论】:

以上是关于在 Electron 中提供静态文件(React 应用程序)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Electron 和 React 从目录读取文件名并输出到 JSON 的方法

如何为 electron + react js + next 进行生产构建

在使用 react 构建的网站中提供另一个(独立)页面或静态文件

如何在 React + Electron 应用程序中重新定位目标不佳的构建文件?

如何在组合 django-react 应用程序中提供静态文件(如图像)

在使用react构建的网站中提供另一个(独立)页面或静态文件