javascript modules and CORS - javascript

I am trying to understand modules in JavaScript but when I try to write a very simple module I get CORS error.I am using bracket as my text editor and the odd part is when I'm using live preview in brackets the code works but when I normally open the .js file I get error.
index.html
<!DOCTYPE html>
<html>
<head>
<title> JS </title>
</head>
<body>
<script type="module">
import {add} from './libA.js';
console.log(add(10,20));
</script>
</body>
</html>
libA.js
export function add(a,b) {
return a+b ;
}
*I get this error ->
Access to Script at 'file:///F:/WEB%20DEV/JavaScript/libA.js' from origin `null` has been blocked by CORS policy:
Invalid response.
Origin 'null' is therefore not allowed access.
(I even tried the latest version of chrome too)

Many browsers do not allow you to access files on the local filesystem with JavaScript (even if the HTML document is also on the local filesystem).
This extends to loading JavaScript modules.
Install a webserver and use that (with a URL like http://localhost/) for testing.

If you have node installed I would recommend installing http-server package. You'll be up and running in no time! Fixed my problem and I can run my application in chrome using the server.

I had the same, removed the type="module" and then the error was gone. Not sure why.

install apache it will have more uses in the future. avoid instead of using third party application like nodejs and sub thid party mini frameworks is a headache. Once you run apache you can run modules. with no nodejs required to be opened

Related

Why JS scripts of type "module" need a web server to work? [duplicate]

Alright, I have looked on this site and have found several different answers, none of which have worked for me.
Basically had a js file that had many functions in it along with the main code for the app. I wanted to move all my functions to another js file so that I could clean up my code a little. I am fairly new to js but I know in python it was as simple as saying "import (module) as (nickname) from (path)"
anyways let's say I have a function named show message in my functions.js module.
export function show_message(){
alert("Hello");
}
and then I at the top of my main.js file I did
import { show_message } from './functions.js'
//I have also tried to import like this:
import * as func from './functions.js'
//And then I call it
show_message();
//I have also tried
func.show_message();
I know this is something simple, but as I said everywhere I have looked I have seen different answers, none of which work for me. I am using Firefox btw. I am also getting an error in the console saying that my import declarations need to be at the top of my module, I fixed that by specifying the type in my HTML link (script src="/static/main.js" type="module")
The error went away but is now saying "same origin policy disallows reading the remote resource at the file (path) (reason: cors request not HTTP)."
And the other error says "module source URI is not allowed in this document".
which makes me think maybe my syntax for importing is right and the error is in my HTML code?
Any help is appreciated.
0. The short answer
You need to install and run a local web server. - For a suggestion on how,
read on.
1. The basics
I tried a simple HTML file – index.html – as follows:
<!-- index.html - minimal HTML to keep it simple -->
<html>
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="#">
</head>
<body>
<h1>Hello world!</h1>
<p>Experimenting with JavaScript modules.</p>
<script type="module" src="js/functions.js"></script>
</body>
</html>
In the subfolder js I put the JavaScript file functions.js:
// js/functions.js
alert('Hello');
When double-clicking index.html, my default web browser – Firefox 89.0
(64-bit) – shows the following, after pressing F12.
Notice how the JavaScript code is not running:
The error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///C:/stackexchange/reproduce/jsModule/moduleNW/basics/js/functions.js. (Reason: CORS request not http).
A cheating "solution" is to (temporarily) remove type="module" from the HTML
code.
The alert then displays without errors.
But I want to run the JavaScript code as a module, so I put back
type="module" in the HTML.
2. Install and run a local web server
To run it as a module, it needs to run on a web server.
Thus, if you want to run the code on your own computer, you will need to
(install and) start a local web server.
One currently popular alternative is live-server.
Here is what worked for me.
Open a terminal. (On Windows: cmd.exe.)
Type npm and hit Enter to see if Node.js is installed.
If you get command not found, download at https://nodejs.org/en/download/
and install. 1
(On Ubuntu, you can try sudo apt install -y nodejs.)
Install live-server: npm install live-server -g.
Change directory to where your page lives: cd <path-to-index.html>.
Start the server: live-server .
(Should open localhost:8080 in your default browser and show the alert.
See below.)
Note 1.
I am on Windows 10, but the above instructions should work fine on Linux and
macOS too.
Note 2.
Here I used Firefox 89.0, but I have tried Google Chrome 91.0 as well.
The only notable difference is the CORS error message, which in Chrome reads:
Access to script at 'file:///C:/stackexchange/reproduce/jsModule/basics/js/functions.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
3. Exporting and importing
Next I create a new folder demo2 containing the following demo2.html:
<!-- demo2.html - even shorter HTML for simplicity -->
<body>
<h1>Hello world!</h1>
<p>Javascript modules.</p>
<script type="module" src="js/main.js"></script>
</body>
I also create the following three JavaScript files in the subfolder js:
// js/module1.js
export function hi () { console.log('Hi from module 1.'); }
and
// js/module2.js
export function howdy () { console.log('Howdy from module 2!'); }
and
// js/main.js
import { hi } from './module1.js';
import { howdy } from './module2.js';
hi();
howdy();
Now I run live-server from the terminal in the folder where demo2.html
resides.
This time I start by typing
live-server --port=1234 --entry-file=demo2.html
and hitting Enter. Screenshot:
References:
Installing Node.js live-server
The live-server docs
Live-server can't find the file specified
Export and Import
1 On Windows 10, I once needed to
repair the installation.
On the script tag you are using to load the js in the browser you need to add the attribute
type="module"
It will look like the following:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
utils.mjs:
export function addTextToBody(text) {
const div = document.createElement('div');
div.textContent = text;
document.body.appendChild(div);
}
This is if you are not using a bundler like webpack and working directly in the browser.
Source of code: https://jakearchibald.com/2017/es-modules-in-browsers/
You might want to use broswerify instead. It allows you to write NodeJS-style modules and then compiles them into a single browser-friendly JavaScript file, allowing you to get all the performance benefits of loading only a single file. It also means you can easily use the same code both server side and client side.
If you want to stick with separate files, it looks like you are well on your way. Unlike regular JavaScript files, modules are subject to Cross-Origin Resource Sharing (CORS) restrictions. They have to be loaded from the same origin, and cannot be loaded from the local filesystem. If you are loading them from the local file system, move them to a server. If you are already hosting them on a server, add the Access-Control-Allow-Origin: * header to the response that serves the module file.
Lots more gotchas and solutions here and here.
function show_message(){
alert("Hello");
}
export { show_message };
and
import { show_message } from './functions'
i think this should do the trick. this is a named export/import technique. you can under this name find more information if you desire it.
Shortcut for Accepted answer
In case you are using Visual Studio Code just install the Live Preview extension by Microsoft.
In any HTML file click the Show preview icon. It will automatically run a local server and show up in the code editor. After every edit you make it refreshes. You can also show it in your default browser.
No need for command line anymore!
JavaScript has had modules for a long time. However, they were implemented via libraries, not built into the language i.e. you can't import or export part of those modules into your js files (whole library needs to be loaded). ES6 is the first time that JavaScript has built-in modules.
Please refer Here for more info about ES modules.
But things have changed and ES modules are now available in browsers! They're in…
Safari 10.1+, Chrome 61+, Firefox 60+, Edge 16+, etc,.
Now, you need to create your JS file using a new extension .mjs, like,
// utils.mjs
export function addTextToBody(text) {
const div = document.createElement('div');
div.textContent = text;
document.body.appendChild(div);
}
and then, you can import that file into your html page like,
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Please refer Here for more info about using ES module in browsers.
Consider going through this url some extension might be causing an issue with the loading of modules:
This blog might be an answer to what you're expecting.
You should first check if browser accepts type="module" and use fallback if it doesn't like this:
<script type="module" src="module.mjs"></script>
<script nomodule src="fallback.js"></script>
This might be the main reason for the CORS error as written here:
Unlike regular scripts, module scripts (and their imports) are fetched
with CORS. This means cross-origin module scripts must return valid
CORS headers such as Access-Control-Allow-Origin: *
So you need to add CORS header to the module file
Consider this blog for CORS issue. You should add CORS header ie. Access-Control-Allow-Origin: * to the server config most probably.
Using JS modules in the browser
On the web, you can tell browsers to treat a element as a module by setting the type attribute to module.
<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>
More on
https://developers.google.com/web/fundamentals/primers/modules
If you're using webpack and babel and want to import the code into your bundle, I guess it should be one of the following:
export default function show_message(){
alert("Hello");
}
and then in your code:
import show_message from 'path/to/show_message.js'
// or
import { default as someOtherName } from 'path/to/show_message.js'
Or if you'd like to export several functions:
const show_message = function(){
alert("Hello");
}
export { show_message };
and then in your code:
import { show_message } from 'path/to/show_message.js'
// or
import { show_message as someOtherName } from 'path/to/show_message.js'
Hope that helps.
I know this old thread but I just fixed this problem myself by using Parcel to launch my website Parcel index.html, in my situation I was using Live server and it didn't work until I switched to parcel .
Instead of using .js, try using .mjs.
Let's say your module file is /modules/App.js, just change it to /modules/App.mjs.
And ofcourse, make sure you have added type="module" in script tag, like this - <script type="module" src="./index.js" defer></script>
My folder structure -
index.html
index.js
modules/App.mjs
This worked for me!

Cannot import 3rd party JavaScript module

I'm attempting to import a 3rd party SDK into a simple project with a very simple setup. I have an index.html file that looks like this:
<!DOCTYPE html>
<html lang="en-us">
<body>
<h1>SDK Test</h1>
<script type="module" src="/js/main.js"></script>
</body>
</html>
I have a main.js file that looks like this:
import MyAlgoConnect from '/#randlabs/myalgo-connect';
console.log("It Worked!");
I also have the #randlabs directory in my project running on an Apache server, so that in Apache's htdocs directory, it looks like this:
But I always get an error in my browser console that says:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
I originally tried using <script src="/js/main.js"></script> in the index.html file, but it returned with the error:
Uncaught SyntaxError: Cannot use import statement outside a module (at main.js:3:1)
There's a whole bunch of different files and additional folders within the myalgo-connect folder, so when I try going to my local apache server at 127.0.0.1:8080/#randlabs/myalgo-connect in my browser it just returns an html document showing the contents of the folder, which is why I assume I'm getting an error in the first place.
According to the SDK's documentation, I think I'm following its Quick Start steps exactly: https://connect.myalgo.com/docs/getting-started/quickstart
I've been searching the internet for days trying to figure out why I can't get this to work. I've also asked a question on the associated discord server but haven't had a response. My experience with web development is very limited, so this is probably just an issue of inexperience on my part, but I cannot figure out what I'm doing wrong. If anyone can shed some light on this, I would be very grateful!
I recommend to setup basic node processor which then compiles application into js file.
https://vuejs.org/guide/quick-start.html
https://reactjs.org/docs/create-a-new-react-app.html
https://nextjs.org/docs/getting-started
I recommend also to setup the TypeScript as it helps a lot with data types and recommendations.
This is example how you can use the MyAlgoConnect by Randlabs (React): https://github.com/Diatomix/Diatomix-frontend/blob/dff9a531ceac4341a3780c004f2bc2206b255ed4/src/components/Authenticate.tsx#L163
Example how to use Algorand with Vue.js : https://github.com/scholtz/wallet

How to use JQuery Keyframes with Webpack/React?

I am a bit new to website hosting. I am currently running a locally hosted page that runs with webpack. I am running this server with react as well. Thus far when I required the usage of something such as JQuery, React, or other plugins, I would add them to my server through the terminal in a manner such as:
npm install react-dom --save-dev
This has worked for everything thus far, but I have run into JQuery keyframes. Normally JQuery and JQuery keyframes can be used by adding these script tags to your base html file:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src='/path/to/jquery.keyframes[.min].js'></script>
Of these two, I cannot load in jquery keyframes via a plugin, so I thought that my only solution was to add the the jquery.keyframes.js file to my folders. I added this file to my main folder and added the script tag to my index.html:
<script src='.../jquery.keyframes.js'></script>
This is the part where I am getting confused. I began by getting the issue:
Refused to execute script from 'http://localhost:3000/jquery.keyframes.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
I read up on this issue, and eventually I was able to "fix" this issue by changing my script tag to:
<script src='.../jquery.keyframes.js' type="text/js"></script>
I'm really not sure if this is a proper fix. I am certainly still uncertain about my issue because when I try to use the command:
$.keyframe.define(aKeyframe);
I get the error:
Cannot read property 'define' of undefined
This implies that I still haven't added the file correctly, or maybe I haven't imported properly into my JavaScript file. The only solutions I can see are:
1) The jquery.keyframes.js file should be in node_modules somewhere due to it being an extension of jquery which is there.
2) There was another way to fix the MIME type error.
3) I should have some import statement like:
import $.keyframe from "../jquery.keyframe.js";
At the top of my JavaScript file.
Thank you in in advance for reading and submitting to this question.

ES6: import module from URL

Is it possible to import javascript module from external url in ES6?
I tried (using babel-node):
import mymodule from 'http://...mysite.../myscript.js';
// Error: Cannot find module 'http://...mysite.../myscript.js'
2018 Update: The module loader spec is now a part of the ES Spec - what you are describing is allowed and possible with <script type="module"> in browsers and with a custom --loader with Node.js as well as with Deno if you're into that.
The module loader spec and the import/export syntax are separate. So this is a property of the module loader (not a part of the ES spec). If you use a module loader that supports plugins like SystemJS.
Update in 2022, it seems it works at least in latest Chrome, Firefox and Safari as of now, as long as the server provides a response header of content-type: application/javascript; charset=utf-8 for the js file.
Try these two files with a vanilla web server:
index.html
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Hello World</title>
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
hello.js
import ip6 from 'https://cdn.jsdelivr.net/gh/elgs/ip6/ip6.js';
const el = document.createElement('h1');
const words = "::1";
const text = document.createTextNode(ip6.normalize(words));
el.appendChild(text);
document.body.appendChild(el);
This is a HUGE deal! Because we can say bye to Webpack now. I am a little too excited now!
You could also use scriptjs which in my case requires less configs.
var scriptjs = require('scriptjs');
scriptjs('https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.standalone.js', function() {
L.mapbox.accessToken = 'MyToken';
});
TL;DR:
For now, no.
Long answer:
There are two different specs: the ES6 defines the syntax to exporting/importing.
And there is the Loader Spec that actually defines how this modules will load.
Spec-speak aside, the important part for us developers is:
The JavaScript Loader allows host environments, like Node.js and browsers, to fetch and load modules on demand. It provides a hookable pipeline, to allow front-end packaging solutions like Browserify, WebPack and jspm to hook into the loading process.
This division provides a single format that developers can use in all JavaScript environments, and a separate loading mechanism for each environment. For example, a Node Loader would load its modules from the file system, using its own module lookup algorithm, while a Browser Loader would fetch modules and use browser-supplied packaging formats.
(...)
The primary goal is to make as much of this process as possible consistent between Node and Browser environments. For example, if a JavaScript program wants to translate .coffee files to JavaScript on the fly, the Loader defines a "translate" hook that can be used. This allows programs to participate in the loading process, even though some details (specifically, the process of getting a particular module from its host-defined storage) will be different between environments.
So we depend on the host environment (node, browser, babel, etc) to resolve/load the modules for us and provide hooks to the process.
The specification describes how exactly a module specifier in import is resolved:
https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
It says URLs are allowed, both absolute and relative ones (starting with /, ./, ../), and it does not differentiate between static and dynamic imports. Further in the text, there's an "Example" box showing examples of valid specifiers:
https://example.com/apples.mjs
http:example.com\pears.js (becomes http://example.com/pears.js as step 1 parses with no base URL)
//example.com/bananas
./strawberries.mjs.cgi
../lychees
/limes.jsx
data:text/javascript,export default 'grapes';
blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f
example in pure javascript how to import google code and replace element on any page to google translate button (can be run from browser debug console for any site you want)
importScriptURI("https://translate.google.com/translate_a/element.js");
document.getElementsByTagName("h1")[0].innerHTML='<div id="google_translate_element"></div>';
setTimeout(()=>{ new google.translate.TranslateElement({pageLanguage: 'en'},'google_translate_element');},1000);

Running server-side python in JS: difficulty with pico

I have webpage that needs to run some computation on start up. I want to keep this computation on the server side so the client cannot access the source code. I discovered pico, a module that is supposed to be "a bridge between server-side python and client side JavaScript".
I have a simply test.py:
import pico
def hello():
return "Hello World"
My JavaScript is also simple:
pico.load("../../../test.py");
pico.main = function() {
var displayMessage = function(message){
console.log("hello2");
console.log(message);
}
test.hello(displayMessage);
}
"../../../test.py" is the relative location of the python script to the pico folder
I then run "python -m pico.server" on the command line. When I go to my web page, open inspector, and go to the console I get the error: "Uncaught SyntaxError: Unexpected token i". 'i' is presumably from the first line import. Note that this same error happens if I don't run the pico.server command.
Any help would be great, as well as suggestions for alternative methods of doing this serverside vs clientside.
I may have an answer for you, however I have not been able to replicate the same error.
pico.load does not seem to work when file extensions are included in the argument, this is due to the function being designed to load sub-modules directly (i.e. module.sub_module) as in the pico API:
pico.load(module, [callback])
Load the Python module named module. The module will be available as a global >variable of the same name.
Submodules may be loaded by using dotted notation e.g. module.sub_module
To make sure I included ".py" file extension on the pico test page I have been working on and it failed to load the module, so this may be a problem if you are using the file extension.
Another possible issue was mentioned in a comment by holderweb. In the first pico example HTML the file client.js is included in an external <script> tag, this includes the functionality required to use pico. So you must have something similar to the following tag in your index.html head section:
<script type="text/javascript" src="/pico/client.js"></script>
For more insight I would be interested in seeing what/if the server logs at command line when the error occurs, and also the contents of your index.html page. Hope this helped!

Categories