Electron中关于静态资源加载问题的解决方案
作者:_island
Electron中的关于静态资源加载问题解决方案
今天来给大家分享一个比较实用的npm包,electron-serve
它是用来干嘛的呢
通常,我们在使用electron框架的时候会使用到loadFile/loadURL进行页面的加载,分别是加载本地文件和加载网络文件
在构建生产环境中,当我们使用loadFile加载本地文件的时候可能会出现资源找不到的情况,(net::ERR FILE NOT FOUND)
这是因为我们构建出来的产物中资源引入路径出现了问题
比如您使用了Vite构建工具,您需要在vite.config.ts将base属性设置为./,告诉Vite我的资源路径都是相对于当前页面的目录的
那么,在electron中引入是没问题的,但事情总不是那么一帆风顺的
当nuxtjs/nextjs想引入到electron中显示时,你会遇到资源路径引用的问题(如下图)

那么这个问题怎么解决,前面我们提到只要将base设置./,就可以解决这个问题,但在nuxt中这并不能生效

它还是以一个绝对路径的方式去寻找它的依赖,所以还是会出现找不到的问题
这个时候,我们可以换一种解决方式,不应该一头扎进base里
我们是不是可以像开发环境一样开一个devServer来解决这个问题?
electron-serve
这就到了本篇文章的主角,electron-serve登场了
pnpm install electron-serve
它是一个在electron中开启静态服务器的npm包,让我们可以以网络协议的方式去访问我们的静态资源
我们使用它也是很简单的,只要在electron主线程中的main.js/ts中引入它,并调用它的serve方法即可
import serve from 'electron-serve'
// 这里填写我们的静态资源目录
serve({ directory: 'renderer' })
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1000,
height: 800,
})
// 通过app协议去访问静态资源,这个是electron-serve中处理的,我们只需要这样子写就可以了
mainWindow.loadURL('app://./index.html')
}
配置好之后,我们再运行一下项目,这时你就会发现找不到资源的问题已经得到解决了

另外,这个库还解决了一个问题:当我们使用loadFile加载本地文件时,是无法正常使用vue-router/react-router中的history模式的。因为这些路由机制依赖于history.pushState,因为loadFile使用的是file协议,会导致找不到对于路径的资源
electron-serve的实现原理
翻看了下源码,发现electron-serve的实现原理很简单
- 大致分为下面两步
- 当
electron时,创建一个会话(或者使用外部传入的会话) - 先是注册了一个特定的协议为
app(这个参数是可以外部传入的,默认为App),告诉electron当遇到这个app协议的时候,应该使用提供的hander函数进行处理
- 当
handler函数实现
const handler = async (request, callback) => {
// 获取index文件路径,访问时路径时跳转index.html
const indexPath = path.join(options.directory, `${options.file}.html`);
// 处理请求的路径文件
const filePath = path.join(options.directory, decodeURIComponent(new URL(request.url).pathname));
// 获取相对路径
const relativePath = path.relative(options.directory, filePath);
// 判断路径是否准确,如果不正确则返回错误
// ..说明为上级目录或者绝对路径,返回错误
const isSafe = !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
if (!isSafe) {
callback({error: FILE_NOT_FOUND});
return;
}
// 最终得到的路径
const finalPath = await getPath(filePath, options.file);
// 获取文件的后缀
const fileExtension = path.extname(filePath);
// 判断文件是否为html或者asar(electron中的一种压缩包格式),如果不是则返回错误
if (!finalPath && fileExtension && fileExtension !== '.html' && fileExtension !== '.asar') {
callback({error: FILE_NOT_FOUND});
return;
}
// 最后返回资源路径
callback({
path: finalPath || indexPath,
});
};
到此这篇关于Electron中关于静态资源加载问题的解决方案的文章就介绍到这了,更多相关Electron静态资源加载问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
