Working with JavaScript module - javascript

I read this and this, and wrote the below files:
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script type="module">
(async () => {
const moduleSpecifier = './lib.mjs';
const {_default, repeat, shout} = await import(moduleSpecifier);
repeat('hello');
// → 'hello hello'
document.getElementById("demo").innerHTML = shout('Dynamic import in action');
// → 'DYNAMIC IMPORT IN ACTION!'
})();
</script>
</head>
<body>
<h1>This is a Heading</h1>
<p id="demo">Loading ..</p>
</body>
</html>
lib.mjs:
export const repeat = (string) => `${string} ${string}`;
export function shout(string) {
return `${string.toUpperCase()}!`;
}
But once trying it at chrome, I got the below:
Access to Script at 'file:///Users/hasan/Documents/mjs/lib.mjs' from
origin 'null' has been blocked by CORS policy: Invalid response.
Origin 'null' is therefore not allowed access.
In nodejs I can add the below line, but can I do it to my file, knowing that it is not running from server!
response.setHeader('Access-Control-Allow-Origin', '*');
UPDATE
I tried running it from this server, and set the CORS, but got the below error:
Failed to load module script: The server responded with a
non-JavaScript MIME type of "". Strict MIME type checking is enforced
for module scripts per HTML spec.
UPDATE 2
It worked with me when I renamed the .mjs to .js, is this means the .mjs not yet supported!!

The first error output is because JavaScript modules are fetched with CORS, and I guess you did not use a server that set up the proper headers as explained in this article: https://developers.google.com/web/fundamentals/primers/modules
In your second attempt with 200 OK Web Server extension for Chrome, it does not yet support JavaScript modules because of lacking MIME type support. There are an issue for this on the developers' Github https://github.com/kzahel/web-server-chrome/issues/133

Related

Access to script blocked by CORS policy

I am making a simple test project including 2 JavaScript files , where i export and import modules , as shown below .
However ,when opening html page , an error generated in the console shows that :
Access to script at 'file:///C:/Users/index2.js' from origin 'null' has been blocked by CORS policy
Failed to load resource: net::ERR_FAILED (index2.js:1)
I tried to desactivate CORS but that leads always to the same error , i am using Google Chrome browser .
what is abnormal in code and what to do to resolve this problem ?
index2.js :
export default class test {
static method () {
return ('hello world' ) ;
}
index.js :
import test from './index2.js';
console.log (test.method()) ;
in index.html :
<script type = "module" src="./index.js"></script>
I resolved the problem by setting up a local webserver , I Used XAMPP , the link below shows the installation and usage :
https://www.maketecheasier.com/setup-local-web-server-all-platforms/

Long load using ES6 modules in Chrome

My javascript app is for a kiosk and is only targeting the Chrome browser. I'm using Chrome version 65. I am trying to use ES6 modules without using a transpiler like Babel. My code was originally:
in index.html:
<script src="js/index.js"></script>
index.js:
import Main from './classes/Main.js';
const init = () => {
const app = new Main();
};
init();
Main.js:
export default class Main {
constructor() {
}
}
Originally I got the error "Uncaught SyntaxError: Unexpected identifier" from index.js line 1. Then based on ES6 module Import giving "Uncaught SyntaxError: Unexpected identifier" I added 'type="module"' to the html tag:
<script type="module" src="js/index.js"></script>
This did load, but it takes my browser about 15 seconds to load index.js and main.js according to the network profiler. What could be going on?
So I ran some tests on my local box. I have a simple NodeJs server running with the following three files:
index.html
<!doctype html>
<html>
<head>
<title>es6 Module test</title>
<script>
console.time('load module');
console.time('time until constructor called');
</script>
<script type="module" src="module.js"></script>
<script>
console.timeEnd('load module');
</script>
</head>
<body>
See console output.
</body>
</html>
module.js
import Main from './Main.js';
const init = () => {
const app = new Main();
};
init();
and
Main.js
export default class Main {
constructor() {
console.timeEnd('time until constructor called');
}
}
Running this code in Chrome 65 (On a Mac)
I get the following output:
Run 1
load module: 0.141845703125ms
time until constructor called: 7.90087890625ms
Run 2
load module: 0.139892578125ms
time until constructor called: 6.5498046875ms
Run 3
load module: 0.160888671875ms
time until constructor called: 7.14404296875ms
Run 4
load module: 0.297119140625ms
time until constructor called: 7.4228515625ms
My download times ranged between 2ms and 10ms for each of the three files.
I really can't tell why your times are so much slower. But they should not be. Maybe your server is getting hammered and unable to respond fast enough?
Possible things to check:
What happens if you try to download each of the files from the address bar? Do they still take forever to download?
What about on a different server?
I was was having the same problem when serving my files using:
python -m SimpleHTTPServer
After changing to use python3 http.server instead it fixed the problem:
python3 -m http.server

Unable to connect to Openfire server from the script running browser side

At first, I was connecting to Openfire using following script.
const {Client} = require('#xmpp/client')
const client = new Client()
client.start('xmpp://localhost:5222').catch(err => {
console.error('start failed', err)
})
client.handle('authenticate', authenticate => {
return authenticate('gabbar', 'gabbar#123')
})
But it shows me an error 'require is not defined'. so I searched the internet and found that browserify could do my work. so I made the bundle.js file using index.js of my HTML page and included it in the HTML page.
<head>
<meta charset="UTF-8"/>
<title>xmpp.js example</title>
<script src="bundle.js"></script>
<!-- <script src="index.js"></script>-->
</head>
but then I am getting the error
no compatible connection method found
Is anybody can tell any other way of doing it. I tried also same as given in example directory of xmpp.js client package, but that is giving me error like XMPP is not a function. Following is the code which I wrote after looking at example files.
index.js
const {xmpp, xml} =
typeof require === 'undefined' ? window.xmpp : require('#xmpp/client') // For you; require('#xmpp/client')
const {client} = xmpp()
client.start('xmpp://localhost:5222').catch(err => {
console.error('start failed', err)
})
client.handle('authenticate', authenticate => {
return authenticate('gabbar', 'gabbar#123')
})
sample.html
<head>
<meta charset="UTF-8"/>
<title>xmpp.js example</title>
<script src="node_modules/xmpp.js/dist/xmpp.min.js"></script>
<script src="index.js"></script>
</head>
these are the two ways I tried connecting to openfire from the browser side but none of them worked for me. please, can anybody tell me what I am doing wrong or any other possible better way of doing this?
xmpp:// is not supported in the browser. Only ws:// (websockets) is supported in browser. If the server supports websockets, you would do something like:
client.start('ws://domain:port) or client.start('ws://domain:port/xmpp-websockets)
The other option is to use Node not in a browser. Which would be accomplished by running node on it's own without a browser or running that code in the background process of Electron (same as just running node by itself, but you can communicate with the renderer process to interact with a UI)

Cannot load modules with traceur - tries to access file via xhr

I am trying to use traceur. When I want to load a module though, I get an error that it was unsuccessful. My code is based on the example traceur provided in its documentation on modules.
Here is the main.html:
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
<script>
System.traceurOptions = { experimental: true }
</script>
<script type="module" src="ProfileView.js"></script>
And the loaded module:
// ProfileView.js
import {firstName, lastName, year} from './Profile.js';
function setHeader(element) {
element.textContent = firstName + ' ' + lastName;
}
// rest of module
// Profile.js
export var firstName = 'David';
export var lastName = 'Belle';
export var year = 1973;
I get the following error in Chrome:
XMLHttpRequest cannot load
file:///C:/Code/Tests/Traceur/ProfileView.js. Cross origin requests
are only supported for protocol schemes: http, data, chrome,
chrome-extension, https, chrome-extension-resource.
WebPageTranscoder FAILED to load
file:///C:/Code/Tests/Traceur/ProfileView.js
Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest':
Failed to load 'file:///C:/Code/Tests/Traceur/ProfileView.js'.
I know that you cant make xhr-requests via the file system but I have seen some tutorials in which the code is structured similarly to mine and it works there...
What may I be doing wrong?
You cannot access the file system with xhr, you should open those pages over http by running a local webserver. If you really want to enable file system access you can: http://www.chrome-allow-file-access-from-file.com/
I.e. you start chrome chrome.exe --allow-file-access-from-files

Chrome can't load web worker

I am working on a project that uses a web worker.
In my head section I have this code:
var worker = new Worker("worker.js");
// More code
This works fine in Safari, but Chrome reports the following error:
Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'.
Why does this work perfectly in Safari but not Chrome? How do I fix this?
Thank you.
Chrome doesn't let you load web workers when running scripts from a local file.
I use a workaround. Chrome blocks Worker but not <script>. Hence the best way to make a universal solution is this:
function worker_function() {
// all code here
}
// This is in case of normal worker start
// "window" is not defined in web worker
// so if you load this file directly using `new Worker`
// the worker code will still execute properly
if(window!=self)
worker_function();
You then link it as normal <script src="...". And once the function is defined, you use this abomination of a code:
new Worker(URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], {type: 'text/javascript'})));
The problem has been properly explained by Noble Chicken but I have a more general solution for it. Instead of installing wamp or xamp, with python you can navigate to the folder your project is hosted in and type: python -m http.server
Just that and you will have a running server on that folder, reachable from localhost.
You can also use the --allow-file-access-from-files flag when you launch Chrome.
Example for MacOsX :
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files
More info : Web worker settings for chrome
It is because of the security restrictions. You need to use http:// or https:// protocol instead of file:///.
If you have NodeJS installed, you can simply do the following.
- Note that this is one of many options available
Install local-web-server
$ npm install -g local-web-server
Now you can use it in any folder that you want to access the contents through http .
$ ws
Navigate to http://localhost:8000 (default port: 8000)
I had the same problem as your post too. The solution is that you have to run it with localhost (wamp or xamp). It will done.
Another workaround is use Google's web server for Chrome extension. Choose your work directory and start the server, Done!
This is inspired by Thomas answer above. But with one caveat that
I wanted to distribute only the HTML, so i manually converted the js to dataURL. and enabling the data URL check box in it.
const myWorker = new Worker("data:application/x-javascript;base64,b25tZXNzYW...");
Easy way to make local http server in chrome is this app:
Web Server for Chrome
https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb/related
Description:
A Web Server for Chrome, serves web pages from a local folder over the network, using HTTP. Runs offline.
Web Server for Chrome is an open source (MIT) HTTP server for Chrome.
It runs anywhere that you have Chrome installed, so you can take it anywhere. It even works on ARM chromebooks.
It now has the option to listen on the local network, so other computers can access your files. Additionally, it can try and get an internet address.
Many people use this to do basic web development on a chromebook. It is also handy for sharing files over a local network between computers, or even on the internet.
Once you install it, navigate to http://127.0.0.1:8887
And it is not unsecure as flag --allow-file-access-from-files
you need a web server for request from HTTP protocol Instead of local file
and work correctly :)
Chrome load the file but cannot run it. Use Firefox. It's working for me.
With Python 2.x being more widely deployed than Python 3.x, something like python -m SimpleHTTPServer 8000 is more generally applicable, and not just for Mac OS X. I found it necessary for use under Cygwin, for instance.
With that in place, this example worked like a champ.
function worker_fun(num){
num ++
// console.log(num)
postMessage(num);
setTimeout(worker_fun.bind(null,num), 500)
}
var w
function startWorker(){
var blob = new Blob([
"onmessage = function(e){\
" + worker_fun.toString() + "\
worker_fun(e.data.num);}"
]);
var blobURL = window.URL.createObjectURL(blob);
if (typeof(Worker) != 'undefined'){
if (typeof(w) == 'undefined'){
w = new Worker(blobURL);
w.onmessage = function(event){
document.getElementById('num').innerHTML = event.data;
}
w.postMessage({
num:parseInt(document.getElementById('num').innerHTML)})
}
}
}
function stopWorker() {
w.terminate();
w = undefined;
}
As mentioned chrome does not support it. I like to define my workers in the same file. This is a working workaround which will increase a number found in innerHTML of the element the with id=num every 500ms.
A probably reason is chrome doesn't let you load web workers when running scripts from a local file. And I try run the code on my firefox, can not either.
To load web worker from file in a project set up with Webpack and TypeScript I used a script as Tomáš Zato suggested. However, I had to modify the worker file.
worker.ts
(() => {
console.log("worker_function loaded");
// #ts-ignore
window.worker_function = () => {
self.onmessage = ({ data: { question } }) => {
// #ts-ignore
self.postMessage({
answer: 42,
});
};
}
})();
index.ts
async function run() {
console.log('run()');
const worker = new Worker(
// #ts-ignore
URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], { type: 'text/javascript' }))
);
worker.postMessage({
question: 'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
});
worker.onmessage = ({ data: { answer } }) => {
console.log(answer);
};
}
run();
index.html
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Offscreen canvas with web worker sample project</title>
<script async type="text/javascript" src="worker.js"></script>
<script async type="text/javascript" src="app.js"></script>
</head>
<body>
<h1>web worker sample project</h1>
</body>
</html>
webpack.config.js (version 5)
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
mode: "production",
entry: {
app: "./src/index.ts",
worker: "/src/worker.ts"
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "build")
},
performance: {
hints: false
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
]
},
resolve: {
extensions: [".js", ".ts"]
},
plugins: [
new CopyPlugin({
patterns: [
{ from: "src/index.html", to: "" }
]
})
]
};
Yes, It will not work in chorome if your are loading local file. But it will work fine in firefox browser. And you have to add below code in HTML file.
<head>
<meta charset="UTF-8" />
</head>

Categories