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>
Related
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\"",
I'm new to extension development and not good at bundlers so I'm using chrome-extension-webpack-boilerplate to start developing my extension.
I want to make a simple timer extension, so after following the bolirplate repository's instructions, I downloaded a module called tiny-timer with yarn add tiny-timer. Then changed the popup.html and popup.js (added code from the tiny-timer repo that works fine on RunKit).
manifest.json:
{
"name": "Chrome Timer Extension",
"options_page": "options.html",
"background": {
"page": "background.html"
},
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icon-34.png"
},
"icons": {
"128": "icon-128.png"
},
"manifest_version": 2,
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}
popup.js
import "../css/popup.css";
const Timer = require("tiny-timer");
console.log(Timer);
const timer = new Timer();
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1 id="timer"></h1>
<button id="pause">Pause</button>
<button id="reset">Reset</button>
<button id="continue">Go</button>
</body>
</html>
Popup output:
Module
>default: class Timer
Symbol(Symbol.toStringTag): "Module"
__esModule: true
>[[Prototype]]: Object
Uncaught TypeError: Timer is not a constructor
at eval (popup.js?dffe:3)
at Module../src/js/popup.js (popup.bundle.js:1271)
at __webpack_require__ (popup.bundle.js:727)
at fn (popup.bundle.js:101)
at Object.0 (popup.bundle.js:1286)
at __webpack_require__ (popup.bundle.js:727)
at popup.bundle.js:794
at popup.bundle.js:797
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.
Using Typescript 2.0 (tsc version 2.0.3).
I have unsuccessfully attempted to use the xml2js node library inside an angular2/typescript application (see https://www.npmjs.com/package/xml2js). Seems clear I am not familiar enough with the way the SystemJS sets up the library for consumption.
To install the xml2js library I did the following:
npm install --save xml2js
npm install --save #types/xml2js
Here are the relevant files:
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"outDir" : "build"
}
}
systemjs.config.js
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'build',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
'#angular/upgrade': 'npm:#angular/upgrade/bundles/upgrade.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
'lodash' : 'npm:lodash',
'xml2js' : 'npm:xml2js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
lodash: {
main : 'index.js',
defaultExtension: 'js'
},
xml2js: {
defaultExtension: 'js'
}
}
});
})(this);
The consuming file:
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/Rx';
import * as _ from 'lodash';
import * as xml2js from 'xml2js';
#Injectable()
export class CatalogService {
constructor (private http:Http) {
}
getCatalog() {
//return Promise.resolve(['This', 'That']);
var xml = "<root>Hello xml2js!</root>"
xml2js.parseString(xml, function (err, result) {
alert(result);
});
alert(_.indexOf([1, 2, 1, 2], 2));
}
}
index.html file
<html>
<head>
<title>Angular QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<dsa-app>Loading DSA App...</dsa-app>
</body>
</html>
With that setup, I do get an error as follows:
zone.js:1382 GET http://localhost:3000/node_modules/xml2js/ 404 (Not Found)
The lodash library loads fine, so I am pretty sure the issue here has to do with the way the xml2js library is defined more than my setup.
Closest solution I have seen for this is a bit dated for Angular 2.0, but I put it here for reference: Use JS library xml2js with Angular 2
Although the question specifically addresses using that library, any other ideas on how to parse/convert xml into something manageable inside TypeScript would also come in handy.
Update:
As suggested I started adding "main" definitions to my systemjs configuration. However, I though part of this was that the dependencies would be loaded/figured out from the node content.
Thus modifying the system.config.js to have:
xml2js: {
main: 'lib/xml2js.js',
defaultExtension: 'js'
},
Move the issue to where now I get 404 entries for sax and xmlbuilder.
Thus, I added the following too:
sax: {
main: 'lib/sax.js',
defaultExtension: 'js'
},
xmlbuilder: {
main: 'lib/index.js',
defaultExtension: 'js'
}
Which address the sax and xmlbuilder, but then more errors popup.
I thought the whole idea with using the SystemJS and the tsconfig would be that these would be figured out from the node modules, adding all the tree dependencies on the packages seems to defeat the purpose.
I think the issue here is in your systemjs config - you haven't defined main for xml2js. Because of that systemjs doesn't know which file to load, so tries to load the NPM directory directly for some reason (loading /node_modules/xml2js as a file, which clearly isn't going to work). Note that your lodash config does specify 'index.js', presumably leading to /node_modules/lodash/index.js being loaded when you import lodash, which is why that works.
If you specify a 'main' for xml2js in your systemjs config that pointing to lib/xml2js.js then systemjs should be able to find it correctly.
As noted by #tim-perry, the issue here was the way the package was defined.
A further issue in my work is that I was making wrong assumptions about what SystemJS would do for me. I need to look into a different tool (starting with JSPM) that would do the tree walk when loading the base module. In my example, lodash was working because it is self contained. However, xml2js had a lot of dependencies, that had a lot of dependencies, that had a lot of dependencies ... thus applying the solution of adding the package definition for each dependency took care of the issue albeit in a very cumbersome way.
Again, thanks to #tim-perry and #artem who helped with this.
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.