This question already has answers here:
Unable to use Node.js APIs in renderer process
(2 answers)
Closed 1 year ago.
I am trying to get started with Electron. I was already able to run all simple examples. They all work as expected. When I try to follow the Quick Start Guide I experience the same issue as mentioned in this question: The app launches properly, but does not display the versions of node Chrome and Electron. When I look into the developing tools I see this error:
Uncaught ReferenceError: process is not defined
at index.html:14
However, I have set nodeIntegration to true.
Why is it still not working?
Versions:
npm 7.6.3
node v14.16.0
chromium 89.0.4389.82
Operating System:
Ubuntu 20.04.2 LTS.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body style="background: white;">
<h1>Hello World!</h1>
<p>
We are using node
<script>document.write(process.versions.node)</script>,
Chrome
<script>document.write(process.versions.chrome)</script>,
and Electron
<script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>
main.js
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
package.json
{
"name": "my-electron-app",
"version": "0.1.0",
"author": "username",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^12.0.0"
}
}
Try to set this value when creating your BrowserWindow:
webPreferences: { nodeIntegration: true, contextIsolation: false }
A new major Electron version has been released which broke the tutorial.
The specific breaking change is a new default value of contextIsolation flag.
For more details, see this GitHub issue.
Related
I want to run a simple webserver that shows a .glb file in VR using a-frame.
When I use the "Open in Default Browser" extension in vs code the html below shows without problems, both box and file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, WebVR! • A-Frame</title>
<meta name="description" content="Hello, WebVR! • A-Frame">
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #ECECEC">
<a-gltf-model position="4 -10 -100" rotation="210 0 0" src="/EPE_4.glb" shadow="receive: true"></a-gltf-model>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
</a-scene>
</body>
</html>
However, when I run a server providing the html using Express, with the node command, only the box and plane is visible. Note that the .glb is somewhat large at 200 MB.
Below is my app.js and package.js file.
Thank you in advance for any help.
app.js
const app = express();
const path = require('path');
const router = express.Router();
router.get('/',function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
});
app.use('/', router);
app.listen(process.env.port || 3000);
console.log('Running at Port 3000');
package.js
{
"name": "vr_test2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node ./bin/www",
"devstart": "SET DEBUG=vr_test:* & nodemon ./bin/www"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}
If someone has a similar problem.
Check the browser's console log, mine showed that the webpage couldn't find the .glb file.
I solved this by adding a public folder and serving it to the client by using:
app.use(express.static('public'))
I am trying to setup msw with #web/test-runner (and playwright). The problem is that I don't know how the mockServiceWorker.js can be picked up by the test runner (which uses browser, not nodejs like jest). There is an example with karma:
https://github.com/mswjs/examples/tree/master/examples/with-karma, probably I have to do something similar but I have no idea where to start. Any hints are welcome.
I am not sure if it is important, but let me share my web.test-runner.config.js
import vite from 'vite-web-test-runner-plugin'
import { playwrightLauncher } from '#web/test-runner-playwright';
export default {
plugins: [ vite() ],
coverageConfig: {
include: [ 'src/**/*.{svelte,js,jsx,ts,tsx}' ]
},
browsers: [
playwrightLauncher({ product: 'chromium' })
],
testRunnerHtml: testFramework => `
<!DOCTYPE html>
<html>
<head>
<script type="module">
window.global = window;
window.process = { env: {} };
</script>
<script type="module" src="${testFramework}"></script>
</head>
</html>
};
and my test command
"test": "web-test-runner \"test/**/*.test.ts\"",
In my chrome extension (manifest V3) I want to import some scripts like jquery and more.
Inside my backgound.js I have:
try {
importScripts('/js/jquery-3.4.1.min.js', '/js/common.js');
} catch (e) {
console.error('importScripts: ' + e);
}
...
calling to getCookie...
inside common.js I have function like:
async function getCookie(key) {
return ...;
}
but when I load the extension I get the error:
background.js:22 importScripts: TypeError: Cannot read property 'createElement' of undefined
This error comes from the Jquery library
and after I get another error:
Uncaught (in promise) ReferenceError: getCookie is not defined
because the error in jquery it doesn't load the common script? how can I fix that?
Is there a more stable solution to import the scripts? so that error in one script will not cause a fail to other scripts?
Posting the working solution for me: import the scripts from npm into background service worker:
In my manifest.json adding "type": "module" to my background script:
"background": {"service_worker": "background.js" , "type":"module"}
Inside my background.js simply importing desired module script:
import Dexie from "/node_modules/dexie/dist/modern/dexie.min.mjs"
REMAKRS:
Please notice that from Manifest Version 3 in order to invoke script into web-page from your background service workers you need to use chrome.scripting.executeScript. Example:
//background.js
let [tab] = await chrome.tabs.query({active: true, currentWindow: true})
//invoke function
await chrome.scripting.executeScript({
target: {tabId: tab.id},
function: colorSelectedText,
args: [tab.title]
})
});
//OR
//invoke file
await chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['your_script.js']
})
});
Desirable scripts must be in same parent folder as your manifest.json (wasn't working when I was trying to use two dots ../path)
You can package your extension application with the version of jquery you would like to use . then you add it as part of your service workers. This is how my manifest.json looks like
{
"name": "Foo Bar",
"description": "NA",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"storage"
],
"action": {
"default_popup": "popup.html"
},
"background": { "service_workers": ["bg-loader.js","/js/jquery-3.6.0.min.js" ]}
}
I have a bg-loader.js which i use to import my js logic script where i have my jquery functions
try {
importScripts('/js/index.js' /*, and so on */);
} catch (e) {
console.error(e);
}
Then in my index.html i add my jquery script to my popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
</body>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</html>
I am trying to use the react blueprint library, so I npm install it and then I tried to import it like:
import { Spinner } from "#blueprintjs/core"
I am getting system.src.js:1051 GET http://localhost:8888/#blueprintjs/core 404 (Not Found)
I thought that it has to do with the typings and since there is a tsfile on the module I tried
/// <reference path="../node_modules/#blueprintjs/core/dist/index.d.ts" />
or
/// <reference path="node_modules/#blueprintjs/core/dist/index.d.ts" />
I am still getting the same error. I am new to Typescript, how can I consume a node module like this?
You need to configure SystemJS so it can find and load all necessary modules in the browser. See this answer for general explanation. Here is complete minimal example that creates blueprint spinner:
install prerequisites
npm i #blueprintjs/core
npm i react
npm i react-dom
npm i react-addons-css-transition-group
npm i #types/react
npm i #types/react-dom
npm i #types/dom4
npm i typescript
npm i systemjs
example code in test.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Spinner } from "#blueprintjs/core";
const mySpinner = <Spinner/>;
ReactDOM.render(mySpinner, document.body);
example web page
<!doctype html>
<html>
<head>
<link href="node_modules/#blueprintjs/core/dist/blueprint.css" rel="stylesheet" />
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script>
window.process = { env: {}};
System.config({
map: {
'react': 'node_modules/react',
'react-dom': 'node_modules/react-dom',
'react-addons-css-transition-group': 'node_modules/react-addons-css-transition-group/index.js',
'fbjs': 'node_modules/fbjs',
'tether': 'node_modules/tether/dist/js/tether.js',
'dom4': 'node_modules/dom4/build/dom4.max.js',
'#blueprintjs/core': 'node_modules/#blueprintjs/core/dist',
'classnames': 'node_modules/classnames/index.js',
'object-assign': 'node_modules/object-assign/index.js',
'pure-render-decorator': 'node_modules/pure-render-decorator/index.js'
},
packages: {
'react': { main: 'lib/React.js' },
'react-dom': { main: 'lib/ReactDOM.js' },
'fbjs': {},
'#blueprintjs/core': { main: 'index.js' },
'#blueprintjs/core/common': { main: 'index.js' },
'#blueprintjs/core/components': { main: 'index.js' }
}
});
System.import('./test.js').then(function(t) {
}).catch(function(e) {
console.error(e);
});
</script>
</head>
<body>
</body>
</html>
Note: It looks like SystemJS is unable to load react and react-dom using their bundles provided in node_modules/react/dist/react.js and node_modules/react-dom/dist/react-dom.js. It can however load everything from individual source files from node_modules/react/lib and node_modules/react-dom/lib, provided that you define process variable in the browser.
I want to avoid cluttering up my distribution bundle with library files and use separate script tags for them in the HTML.
One way is like this...
m1.js
module.exports = "first module";
m2.js
module.exports = "second module";
cnd-m1.js
var m1 = "first module";
main.js
var m1 = this.m1 || require("./src/m1");
var m2 = require("./src/m2");
console.log(m1);
console.log(m2);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>browserify test</title>
</head>
<body>
<script type="text/javascript" src="src/cdn-m1.js"></script>
<script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>
Where cdn-m1.js could be a library for example.
The only way I could figure out to make it work is to put a short-circuit fallback in the require statement and --ignore the file in my build.
in package.json
"scripts": {
"build-ignore": "browserify ./main.js -i ./src/m1.js > ./dist/bundle.js",
"build": "browserify ./main.js > ./dist/bundle.js"
},
Using the build-ignore script, the m1 module was stubbed in the bundle making it much smaller (assuming its a 50k line library) and it falls back on the cdn-served version.
bundle.js
function e(t, n, r) {
function s(o, u) {
if(!n[o]) {
if(!t[o]) {
var a = typeof require == "function" && require;
if(!u && a)return a(o, !0);
if(i)return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function(e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for(var o = 0; o < r.length; o++)s(r[o]);
return s
})({
1: [function(require, module, exports) {
// browserify creates a stub for "./src/m1"
}, {}],
2: [function(require, module, exports) {
var m1 = this.m1 || require("./src/m1");
var m2 = require("./src/m2");
console.log(m1);
console.log(m2);
}, {"./src/m1": 1, "./src/m2": 3}],
3: [function(require, module, exports) {
module.exports = "second module";
}, {}]
}, {}, [2]);
Is there a better way to achieve this?
The answer is to use browserify-shim
In order to figure it out, I created a slightly more complicated scenario with a fake lib file (main-a.js) with two sub-dependencies (m1.js and m2.js) and made the app (main-b.js) dependent on the fake lib.
I rolled main-a.js into a stand-alone bundle that exposed one global called fakeLib and used a separate script tag in the index.html to load that.
I then used browserify-shim to build an isomorphic version of the app that required main-a.js in node, but used window.fakeLib in the browser.
using this app:
/**
* main-b.js
*/
require("./src/main-a").say();
This does not work:
"browserify-shim": {
"./src/main-a": "fakeLib"
},
but this does:
"browserify-shim": {
"./src/main-a": "global:fakeLib"
},
You must use this global:
I think that may be due to a bug in browserify because it doesn't agree with the browserify handbook
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>browserify test</title>
</head>
<body>
<div style="white-space: pre;" id="output"></div>
<script type="text/javascript" src="dist/main-a-lib-pretty.js"></script>
<script type="text/javascript" src="dist/bundle-B.js"></script>
</body>
</html>
Fake library...
/**
* m1.js
*/
exports.say = "first module";
.
/**
* m2.js
*/
exports.say = "second module";
.
/**
* main-a.js
*/
var m1 = require("./src/m1");
var m2 = require("./src/m2");
exports.say = function() {
function op(t){
this.document
? document.getElementById("output").textContent += t + "\n"
: console.log(t);
}
op(m1.say);
op(m2.say);
};
package.json for fake lib. This makes a standalone package that exposes fakeLib
{
"name": "browserify-nightmare",
"version": "1.0.0",
"main": "main-a.js",
"dependencies": {
},
"devDependencies": {
"browserify-shim": "^3.8.12"
},
"scripts": {
"build-lib": "browserify ./main-a.js -s fakeLib > ../dist/main-a-lib-pretty.js",
"build-lib-pretty": "browserify ./main-a.js -s fakeLib | js-beautify > ../dist/main-a-lib-pretty.js"
},
"author": "cool.blue",
"license": "MIT",
"description": ""
}
Fake app
/**
* main-b.js
*/
require("./src/main-a").say();
package.json that uses browserify-shim to return fakeLib from require("./src/main-a") in the browser but acts like a normal CommonJS module in node.
{
"name": "browserify-nightmare",
"version": "1.0.0",
"main": "main-b.js",
"browserify-shim": {
"./src/main-a": "global:fakeLib"
},
"browserify": {
"transform": "browserify-shim"
},
"devDependencies": {
"browserify-shim": "^3.8.12"
},
"scripts": {
"build-B": "browserify ./main-b.js > ./dist/bundle-B.js",
"build-B-pretty": "browserify ./main-b.js | js-beautify > ./dist/bundle-B.js"
},
"author": "cool.blue",
"license": "MIT",
"description": ""
}
this answer was super-helpful
git repo
First you have to create a seperate bundle for m1.js:
browserify -r ./src/m1.js > ./dist/m1_bundle.js
then simply create the "normal" bundle and reference to the created m1_bundle.js:
browserify -x m1 -d ./main.js > ./dist/bundle.js
now you have to include the two bundles into your HTML-file.
NOTE: you have to include the m1_bundle.js before the "normal" bundle.js in your HTML.
For more details show my other answer. There i explain, how to do the same thing but with node_modules instead of an own library.