Electron: 本地文件的自定义协议和要求

创建于 2016-02-17  ·  3评论  ·  资料来源: electron/electron

我是电子的新手,并试图为我的应用程序和分布式客户端 js 文件使用自定义协议,即require d。 但是,我无法加载模块,因为require忽略了我的自定义方案。 这是我的环境:

lib/ - node scripts
  main.js - node entry script
resources/ - client side resources
  css/
  html/
    index.html
  js/ - client side scripts
    main.js
    test.js
package.json

lib/main.js 基于公共主页的示例:

// lib/main.js
'use strict';

const electron = require('electron');
const app = electron.app;  // Module to control application life.
const BrowserWindow = electron.BrowserWindow;  // Module to create native browser window.
const path = require('path');

var mainWindow = null;

app.on('ready', function() {
  const protocol = electron.protocol;

  /* js, css, fonts, ... */
  protocol.registerFileProtocol('resource', (request, callback) => {
    var url = request.url.substr(11);
    callback({path: path.join(__dirname, '../resources', url)});
  });

  /* html, possible rendered from other files like markdown or jade */
  protocol.registerFileProtocol('view', (request, callback) => {
    var url = request.url.substr(11);
    callback({path: path.join(__dirname, '../resources/html', url)});
  });


  // Create the browser window.
  mainWindow = new BrowserWindow({width: 800, height: 600});

  // and load the index.html of the app.
  mainWindow.loadURL('view://index.html');

  // Open the DevTools.
  mainWindow.webContents.openDevTools();

  // ...
});

注意view://协议背后的过程,以后会编译其他文件成html,比如markdown或者jade( view://index.jade会编译jade文件,返回html字符串)。

<!-- resources/html/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Electron Test</title>
  </head>
  <body>
    <h1>Electron Test</h1>

    <script src="resource://js/main.js"></script>
  </body>
</html>

html 文件将通过我的自定义resource://协议访问 css 或 js 文件等资源。 主文件正确执行,但是我不能在那里require另一个文件:

// resources/js/main.js
const test = require('./test'); // Error: Cannot find module './test'

test.sayHello();
// resources/js/test.js
exports.sayHello = function() {
  console.log('Hello!');
};

我正在使用electron . ,v0.36.7 执行它。

当错误发生时,在 devtools 中检查require后面的代码(大约module.js:336 ,节点当前主节点的第337行)时, request"./test"paths仅包含电子核心模块的一个条目,我找不到扩展该搜索路径列表的方法。

我检查了其他问题(#4459、#2539),这些问题似乎与同一个问题有关,但它们对我没有帮助(例如,使用预加载脚本操纵module的路径或 globalPaths 不起作用.

任何想法如何让这个工作? 或者您会建议使用单个 JavaScript 文件吗? (我使用 TypeScript 作为预处理器,它可以连接所有源文件)。

最有用的评论

我为它可能涉及的任何人找到了这个解决方案:
WEB_FOLDER 包含 index.html 和所有其他相关引用内容。
如果您的索引文件不在子文件夹中(本例中为 web),您可以将其设置为任何空字符串

function createWindow() {
  const WEB_FOLDER = 'web';
  const PROTOCOL = 'file';

  electron.protocol.interceptFileProtocol(PROTOCOL, (request, callback) => {
      // // Strip protocol
      let url = request.url.substr(PROTOCOL.length + 1);

      // Build complete path for node require function
      url = path.join(__dirname, WEB_FOLDER, url);

      // Replace backslashes by forward slashes (windows)
      // url = url.replace(/\\/g, '/');
      url = path.normalize(url);

      console.log(url);
      callback({path: url});
  });

  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false
    }
  });

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: 'index.html',
    protocol: PROTOCOL + ':',
    slashes: true
  }));

所有3条评论

您可以在module.paths查看 Node 模块的搜索路径,如果您的resources/js不在其中,则require将无法找到test.js .

我认为是因为您没有正确操作模块搜索路径,您可能会在社区中获得一些想法。

当您通过<script>标签加载.js文件时,它会嵌入到文档中,因此

<body>
  <h1>Electron Test</h1>
  <script src="resource://js/main.js"></script>
</body>

在功能上等同于

<body>
  <h1>Electron Test</h1>
  <script>
    const test = require('./test'); // Error: Cannot find module './test'
    test.sayHello();
  </script>
</body>

这意味着./test是相对于index.html解析的,而不是相对于js/main.js 。 要解决这个问题,你可以这样做

<body>
  <h1>Electron Test</h1>
  <script>
    require('../js/main.js');
  </script>
</body>

我为它可能涉及的任何人找到了这个解决方案:
WEB_FOLDER 包含 index.html 和所有其他相关引用内容。
如果您的索引文件不在子文件夹中(本例中为 web),您可以将其设置为任何空字符串

function createWindow() {
  const WEB_FOLDER = 'web';
  const PROTOCOL = 'file';

  electron.protocol.interceptFileProtocol(PROTOCOL, (request, callback) => {
      // // Strip protocol
      let url = request.url.substr(PROTOCOL.length + 1);

      // Build complete path for node require function
      url = path.join(__dirname, WEB_FOLDER, url);

      // Replace backslashes by forward slashes (windows)
      // url = url.replace(/\\/g, '/');
      url = path.normalize(url);

      console.log(url);
      callback({path: url});
  });

  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false
    }
  });

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: 'index.html',
    protocol: PROTOCOL + ':',
    slashes: true
  }));
此页面是否有帮助?
0 / 5 - 0 等级