I have built an app using GitHub's Electron. I am using the recommended way of loading modules, the ES6 syntax of:
import os from 'os'
After downloading the boilerplate the app is working fine. I have been able to import scripts in the background.js file without issue. Below is how I am loading my custom module:
import { loadDb } from './assets/scripts/database.js';
However, when I open a new browser window (clipboard.html) within Electron I am then loading a JavaScript file (clipboard.js) which in turn tries to import modules. At this point I am getting an Unexpected token import error.
My clipboard.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Electron Boilerplate</title>
<link href="./stylesheets/main.css" rel="stylesheet" type="text/css">
<script>
window.$ = window.jQuery = require('./assets/scripts/jquery-1.12.1.min.js');
</script>
<script src="./assets/scripts/clipboard.js"></script>
</head>
<body class="clipboard">[...]</body></html>
My clipboard.js file:
import { remote } from 'electron'; // native electron module
import { loadDb } from './assets/scripts/database.js';
const electron = require('electron');
document.addEventListener('DOMContentLoaded', function () {
var db = loadDb();
db.find({ type: 'text/plain' }, function (err, docs) {
var docsjson = JSON.stringify(docs);
console.log(docsjson);
});
});
Just to re-iterate, the same code is used within app.html, which is my app's main window, and this does not error.
It feels like the main window is initialising something that my clipboard.html window isn't (perhaps 'Rollup'?), but there's nothing explicit within my app's code to suggest this.
You need to run clipboard.js through rollup first. Rollup parses the import statements. You have to modify tasks/build/build.js to do that.
var bundleApplication = function () {
return Q.all([
bundle(srcDir.path('background.js'), destDir.path('background.js')),
bundle(srcDir.path('clipboard.js'), destDir.path('clipboard.js')), // Add this line
bundle(srcDir.path('app.js'), destDir.path('app.js')),
]);
};
#user104317 got it right, clipboard.js just didn't get "compiled" by rollup.
Just wanted to add that in your case, it should have been:
var bundleApplication = function () {
return Q.all([
bundle(srcDir.path('background.js'), destDir.path('background.js')),
bundle(srcDir.path('app.js'), destDir.path('app.js')),
bundle(srcDir.path('assets/scripts/clipboard.js'), destDir.path('assets/scripts/clipboard.js')),
]);
};
Then you could have left it at ./assets/scripts/clipboard.js.
If you end up having a lot of independent js files (you shouldn't if you're building a SPA), consider listing them automatically, like done in ./tasks/build/generate_spec_imports.js
Related
Whenever I import python modules in a pyodide, it gives this error.
pyodide.js:108 Invalid package name or URI
I am not sure how to properly import modules,
I have tried this which was mentioned in the docs.
pyodide.loadPackage('<module address>')
(this returns a promise on whoes resolution I run this method)
pyodide.runPython('
<python code here>
')
Upon execution, I get the error mentioned above.
Javascript Code:
<html>
<head>
<script type="text/javascript">
// set the pyodide files URL (packages.json, pyodide.asm.data etc)
window.languagePluginUrl = 'https://pyodide-cdn2.iodide.io/v0.15.0/full/';
</script>
<script src="https://pyodide-cdn2.iodide.io/v0.15.0/full/pyodide.js"></script>
</head>
<body>
Pyodide test page <br>
Open your browser console to see pyodide output
<script type="text/javascript">
languagePluginLoader.then(function () {
pyodide.loadPackage('<address>').then(() => {
console.log(pyodide.runPython('
import sys
from <my package> import *
sys.version
'));
console.log(pyodide.runPython('print(1 + 2)'));
});
});
</script>
</body>
</html>
There is a chance that this question might be unclear, but please let me know if you have trouble understanding something.
Also, the string passed in the runPython() method is the python code, just to avoid confusion.
I even tried uploading the module to a server as the docs mentioned a URL using the HTTP protocol, was pretty stupid trying this but I did.
Docs: https://pyodide.readthedocs.io/en/latest/using_pyodide_from_javascript.html#loading-packages
Update: Pyodide v0.21.0
Starting with Pyodide 0.18.0, runPythonAsync does not automatically load packages, so loadPackagesFromImports should be called beforehand.
So, to import a third-party package like numpy we have two options: we can either pre-load required packages manually and then import them in Python
// JS
await pyodide.loadPackage('numpy');
// numpy is now available
pyodide.runPython('import numpy as np')
console.log(pyodide.runPython('np.ones((3, 3)))').toJs())
or we can use the loadPackagesFromImports function that will automatically download all packages that the code snippet imports:
// JS
let python_code = `
import numpy as np
np.ones((3,3))
`
(async () => { // enable await
await pyodide.loadPackagesFromImports(python_code)
let result = await pyodide.runPythonAsync(python_code)
console.log(result.toJs())
})() // call the function immediately
More examples can be found here
(async () => { // enable await
let python_code = `
import numpy as np
np.ones((3,3))
`
let pyodide = await loadPyodide();
await pyodide.loadPackagesFromImports(python_code)
console.log(pyodide.runPython(python_code).toJs())
})() // call the function immediately
<script src="https://pyodide-cdn2.iodide.io/v0.21.0/full/pyodide.js"></script>
Note also, that starting with version 0.17, Pyodide uses JsProxy for non-JS datatypes. So, before printing the results, it has to be converted using toJs.
Old answer (related to Pyodide v0.15.0)
It is not clear what you are passing as <address> in pyodide.loadPackage('<address>'), but it should just be the package name (e.g. numpy).
Also, note that Pyodide currently supports a limited number of packages. Check out this tutorial on it for more details.
If you want to import a third-party package like numpy there are two options: you can either pre-load required packages manually and then import them in Python using pyodide.loadPackage and pyodide.runPython functions:
pyodide.loadPackage('numpy').then(() => {
// numpy is now available
pyodide.runPython('import numpy as np')
console.log(pyodide.runPython('np.ones((3, 3)))'))
})
Or you can use pyodide.runPythonAsync function that will automatically download all packages that the code snippet imports.
Here is the minimal example for pyodide.runPythonAsync
let python_code = `
import numpy as np
np.ones((3,3))
`
// init environment, then run python code
languagePluginLoader.then(() => {
pyodide.runPythonAsync(python_code).then(output => alert(output))
})
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/pyodide/v0.21.0/full/pyodide.js"></script>
</head>
<body>
</body>
</html>
I'm using electron with svelte as my frontend framework.
I have JS files that contain functions used by my svelte components.
When I try to import a node module using require - it returns an empty object.
When I use require inside a svelte component it works fine. (I've set nodeIntegration: true in my electron.js file).
How could I fix this?
EDIT: An example:
<!--SvelteComponent.svelte-->
<script>
import {func} from "./jsFile";
</script>
//jsFile.js
const fs = require("fs"); // This require returns an empty object
export function func {...}
I also get a Rollup warning: (!) Plugin node-resolve: preferring built-in module 'fs' over local alternative at 'fs', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
It turns out I should have used window.require instead of require
Here's a fragment of a working svelte component from my application. All imported or required objects just work fine.
<script>
import '../../../node_modules/materialize-css/dist/css/materialize.css';
import '../../../css/material-icons-svelte.css'; // we'd have to adjust the font paths!! check extra.css
import '../../../node_modules/codemirror/lib/codemirror.css';
import '../../../node_modules/materialize-css/dist/js/materialize.js';
const {getState, getStore} = require('../../../dist/store/store.renderer');
const {ipcRenderer} = require('electron');
const _ = require('lodash');
Edit
I added this to my App.svelte component, that I use on a svelte app with electron and, well, it works. Prints the fs object to the console and it's not empty
const fs = require('fs')
console.log(fs);
nodeIntegration is set to true, this my index.html:
<!doctype html>
<html>
<head>
<meta charset='utf8'>
<meta name='viewport' content='width=device-width'>
<link rel='stylesheet' href='../../../css/global.css'>
<link rel='stylesheet' href='../../../dist/app/myapp/extra.css'>
<link rel='stylesheet' href='../../../dist/app/myapp/bundle.css'>
</head>
<body class="grey lighten-4">
<script src='../../../dist/app/myapp/bundle.js'></script>
</body>
</html>
And I'm on electron 8.2.5
I'm making a website to learn PHP and Javascript/JQuery, i don't have much experience yet and i'm trying to understand what's the best structure to implement
PHP creates an array of strings
i can access the array from index.php via json_encode
then i want to send the array to a function in a class which is in a .mjs file
the problem is that in the index.php file, by the script tags i can't import the module, and if i use script type="module" i can use the import
but i get this error:
Failed to load module script: The server responded with a non-JavaScript MIME type of "" in main.mjs::1
the MDN reference the mjs extension is used to prevent that.
that's why i'm stuck.
server directory looks like this:
index.php
js/main.mjs
js/index.mjs
Code snippets:
index.php
<head>
<meta charset="utf-8">
<title>Website</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="js/jquery-3.4.1.slim.min.js"></script>
<script src="js/main.mjs" type="module"></script>
<script type="module">
import {start_index} from "./js/main.mjs";
initialize();
function initialize()
{
var arr = <?php echo json_encode($images_arr); ?>;
start_index(arr);
}
</script>
</head>
main.mjs
function start_index(arr)
{
import {gallery_manager} from './index.mjs';
var gallery_mngr = new gallery_manager();
gallery_mngr.initialize(arr);
}
export {start_index};
index.mjs
class gallery_manager
{
constructor(){}
var images = "";
var placeholder = "../images/common/placeholder.png";
public function initialize(arr)
{
images = arr;
alert(images[0]);
}
function switchByTimer()
{
}
function switchImage(new_image, direction)
{
}
}
export {gallery_manager};
MAIN PROBLEM:
Your web server doesn't appear to "understand" what an "mjs" file is, so it isn't sending the appropriate MIME type in the response's HTTP header.
SUGGESTION: change ".mjs" to "js" and see if that helps. "mjs" is oriented toward NodeJS.
IMPORTANT QUESTIONS:
Q: You're using a web server, correct?
Q: What kind of web servier? Apache2/Linux? IIS Express local Windows PC? Something else?
STRONG SUGGESTION: familiarize yourself with Chrome Developer Tools.
I've managed to fix my code, paulsm4 has lit a spark in my brain
.mjs extension strangely does not work, i have no idea why it's advised to use that extension for javascript modules as it is stated in the MDN reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
also, some of my JS code was broken, especially class variables and functions
because i'm still learning the syntax..
now it's working as supposed
index.php
<link rel="stylesheet" type="text/css" href="style.css">
<script src="js/jquery-3.4.1.slim.min.js"></script>
<script src="js/main.js" type="module"></script>
<script type="module">
import start_index from "./js/main.js";
initialize();
function initialize()
{
var arr = <?php echo json_encode($images_arr); ?>;
start_index(arr);
}
</script>
main.js
import gallery_manager from './index.js';
function start_index(arr)
{
var gallery_mngr = new gallery_manager(arr);
gallery_mngr.initialize();
}
export default start_index;
index.js
class gallery_manager
{
constructor(images, placeholder)
{
this.images = images;
this.placeholder = "../images/common/placeholder.png";
}
initialize()
{
alert(this.images[0]);
}
switchByTimer()
{
}
switchImage(new_image, direction)
{
}
}
export default gallery_manager;
I can't figure this out. I have a small app setup with an index.html that includes a javascript file. On the same directory as that file is another file named myJsModule.js with the following code:
export default class{
doStuff()
{
console.log("calling goStuff() from external Module");
}
}
The main javascript file that is loaded from the html then does the import in this way:
import myJsModule from "myJsModule";
// TESTING MODULES
let myNewModule = new myJsModule();
myNewModule.doStuff();
I have a local web server running using Node, so I'm accesing this index.hmtl through my localhost: http://127.0.0.1:8080.
Im getting the following error: Uncaught SyntaxError: Unexpected identifier (referring to myJsModule on my main js file). I also tried using babel to transpile this into previous javascript. I had the same problem using the "require".
Shouldn't my local server figure this out? Or am I using this wrong?
As of Chrome 61, modules are natively supported. I was able to get your example working with the following HTML and JavaScript.
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Native Module</title>
</head>
<body>
<p>Hello, world!</p>
<script type="module">
import MyJsModule from './MyJsModule.js';
let myJsModule = new MyJsModule();
myJsModule.doStuff();
</script>
</body>
</html>
MyJsModule.js:
export default class MyJsModule {
doStuff() {
console.log("calling doStuff() from external Module");
}
}
I'm getting the error across all browsers. I says "unable to process binding "component"...". I have read quite a number of articles including the requirejs site. I've checked out what can cause the error but I'm lost as to whether they apply to my code or not. To the best of my knowledge, I'm not manually loading anything using the script tag and every module is loaded with requirejs.
I created a knockout project using yoman: yo ko. After that components are added using yo ko:component [name of component]. The page loads fine when the most of the time but periodically gives the error below. The frequency seems to be increased when I use two components. I edited the new component and removed the reference to the knockout object and the error still happens though not as frequently.
The exact error is as follows:
Uncaught Error: Unable to process binding "component: function (){return f}"
Message: Mismatched anonymous define() module: function (a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}}
http://requirejs.org/docs/errors.html#mismatch
Below are some of the code in the files (if it helps)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ko-cai</title>
<!-- build:css -->
<link href="bower_modules/semantic/dist/semantic.css" rel="stylesheet">
<link href="bower_modules/c3/c3.css" rel="stylesheet">
<link href="css/styles.css" rel="stylesheet">
<!-- endbuild -->
<!-- build:js -->
<script src="app/require.config.js"></script>
<script data-main="app/startup" src="bower_modules/requirejs/require.js"></script>
<!-- endbuild -->
</head>
<body>
<div>
<!--<side-bar></side-bar>
<page-container></page-container>-->
<dashboard></dashboard>
this is a test
</div>
</body>
</html>
require.config.js
// require.js looks for the following global when initializing
var require = {
baseUrl: ".",
paths: {
"crossroads": "bower_modules/crossroads/dist/crossroads.min",
"hasher": "bower_modules/hasher/dist/js/hasher.min",
"jquery": "bower_modules/jquery/dist/jquery",
"knockout": "bower_modules/knockout/dist/knockout",
"knockout-projections": "bower_modules/knockout-projections/dist/knockout-projections",
"signals": "bower_modules/js-signals/dist/signals.min",
"text": "bower_modules/requirejs-text/text",
"semantic": "bower_modules/semantic/dist/semantic",
"lodash": "bower_modules/lodash/dist/lodash",
"c3": "bower_modules/c3/c3",
"d3": "bower_modules/d3/d3",
"config": "../../cai/config",
"observations": "../../cai/observations"
},
shim: {
"semantic": { deps: ["jquery"] },
"c3": { deps: ["d3"]},
"config": { deps: ["knockout"]},
"observations": { deps: ["knockout","jquery"]}
}
};
dashboard.html
<h2>dashboard</h2>
<p data-bind='text: message'></p>
dashboard.ts
/// <amd-dependency path="text!./dashboard.html" />
import ko = require("knockout");
export var template: string = require("text!./dashboard.html");
export class viewModel {
public message = ko.observable("Hello from the dashboard component too!");
constructor (params: any) {
}
public dispose() {
// This runs when the component is torn down. Put here any logic necessary to clean up,
// for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
}
}
dashboard.js
define(["require", "exports", "knockout", "text!./dashboard.html"], function(require, exports, ko) {
exports.template = require("text!./dashboard.html");
var viewModel = (function () {
function viewModel(params) {
this.message = ko.observable("Hello from the dashboard component too!");
}
viewModel.prototype.dispose = function () {
// This runs when the component is torn down. Put here any logic necessary to clean up,
// for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
};
return viewModel;
})();
exports.viewModel = viewModel;
});
//# sourceMappingURL=dashboard.js.map
What am I doing wrong?
How do I fix this as it makes testing very difficult?
Where can I check which of the known issues apply to my code so I look for a fix.
After some more investigations, I was able to come up with a solution. May not be the best but I'm yet to see another. The problem had to do with require.js. It appears that it does not matter what is contained in the file (I even tried one with a blank function and got the mismatch error). I however noted that, when I execute the same require statement after the error, it actually works. I added a component loader to knockout to fetch the Config of the components. Below is the loader that worked for me. Hope it is useful to someone until a better solution is found or we get to the bottom of this issue.
//register a custom loader
ko.components.loaders.unshift({
getConfig: function(name,callback){
ko.components.defaultLoader.getConfig(name, function(c){
if (c && c.require){ //do custom loading here. make first attempt to fetch the config
try{
require([c.require],function(config){
callback(config);
});
}catch(e){
//todo: check that this is mismatch error and try again. else throw exception
require([c.require], function(config){ //make the request again
callback(config);
});
}
} else {
callback(c);
}
})
}
});
Have you checked the requirejs documentation? More precisely the list behind a link from the error you posted:
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API.
Do not manually code script tags in HTML to load scripts that have
define() calls in them.
If you manually code an HTML script tag, be sure it only includes
named modules, and that an anonymous module that will have the same
name as one of the modules in that file is not loaded.
If the problem is the use of loader plugins or anonymous modules but
the RequireJS optimizer is not used for file bundling, use the
RequireJS optimizer.
If the problem is the var define lint approach, use /*global define
*/ (no space before "global") comment style instead.
http://requirejs.org/docs/errors.html#mismatch