Sou novo no electron e estou tentando usar protocolos personalizados para meu aplicativo e arquivos js do lado do cliente distribuídos, que são require
d. No entanto, não consigo carregar os módulos porque require
está ignorando meu esquema personalizado. Este é o meu ambiente:
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 é baseado no exemplo da página inicial pública:
// 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();
// ...
});
Observe que o processo por trás do protocolo view://
compilará outros arquivos em html no futuro, como markdown ou jade ( view://index.jade
compilará o arquivo jade e retornará a string 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>
O arquivo html acessará recursos como arquivos css ou js por meio do meu protocolo resource://
. O arquivo principal é executado corretamente, porém não posso require
outro arquivo lá:
// 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!');
};
Estou executando com electron .
, v0.36.7.
Ao inspecionar o código atrás de require
nos devtools (em torno de module.js:336
, linha 337 no mestre atual do nó) quando o erro ocorre, request
é "./test"
e paths
contém apenas uma entrada para os módulos principais do elétron, e não consegui encontrar uma maneira de estender essa lista de caminhos de pesquisa.
Eu verifiquei outros problemas (# 4459, # 2539) que parecem ser o mesmo, mas eles não me ajudaram (por exemplo, usar um script de pré-carregamento manipulando o caminho de module
ou globalPaths não funciona .
Alguma ideia de como fazer isso funcionar? Ou você recomendaria usar um único arquivo JavaScript? (Estou usando o TypeScript como um pré-processador, que pode concatenar todos os arquivos de origem).
Você pode verificar os caminhos de pesquisa dos módulos Node em module.paths
, se seu resources/js
não estiver nele, require
não será capaz de encontrar test.js
.
Acho que é porque você não manipulou os caminhos de pesquisa de módulo corretamente, você pode ser uma abelha para obter algumas ideias na comunidade .
Quando você carrega um arquivo .js
por meio de uma tag <script>
ela está embutida no documento,
<body>
<h1>Electron Test</h1>
<script src="resource://js/main.js"></script>
</body>
é funcionalmente equivalente a
<body>
<h1>Electron Test</h1>
<script>
const test = require('./test'); // Error: Cannot find module './test'
test.sayHello();
</script>
</body>
O que significa que ./test
é resolvido em relação a index.html
, não em relação a js/main.js
. Para consertar isso, você pode fazer
<body>
<h1>Electron Test</h1>
<script>
require('../js/main.js');
</script>
</body>
Encontrei esta solução para quem possa interessar:
O WEB_FOLDER contém o index.html e todos os outros conteúdos referenciados relativos.
Você pode defini-lo como qualquer string vazia se o seu arquivo de índice não estiver localizado dentro de uma subpasta (web neste exemplo)
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
}));
Comentários muito úteis
Encontrei esta solução para quem possa interessar:
O WEB_FOLDER contém o index.html e todos os outros conteúdos referenciados relativos.
Você pode defini-lo como qualquer string vazia se o seu arquivo de índice não estiver localizado dentro de uma subpasta (web neste exemplo)