Example
<!-- index.html -->
<script type="module">
import 'someModule'
</script>
TypeError: Error resolving module specifier: someModule
Uncaught TypeError: Failed to resolve module specifier "someModule". Relative references must start with either "/", "./", or "../".
Q:
Is it possible to catch this error?
Who dispatch this error?
Context
In this case, the dependency can be caught and resolved using the service worker.
<script type="module">
import '/someModule'
</script>
You are not importing it in right way as per the error log.
Valid module specifiers must match one of the following:
A full non-relative URL. As in, it doesn't throw an error when put through new URL(moduleSpecifier).
Starts with /.
Starts with ./.
Starts with ../.
Other specifiers are reserved for future-use, such as importing built-in modules.
Just try this code:
<script type="module">
import {someModule} from './someModule.js';
</script>
You cannot catch that error, unless you use some non-standard uncaught exception handler, like window.onerror in browser or process.setUncaughtExceptionHandler in Node.js.
Catching that error is impossible because import statements are allowed only outside of any blocks, in the module-global scope. Therefore, if you try to wrap the import into a try..catch, it will throw a SyntaxError.
Instead, you could use the dynamic import() syntax proposal, which can be called anywhere; and handle its promise rejection.
Related
i want to know how i can import the #metaplex/js module into a js file connected to the html. If i use the import statement i get an error saying "Import identifiers must start with ".", "./"" and things like this. For solanaWeb3 i had to add a script tag with a unpkg link as src and its working. Id like to know where can i find the same script src for #metaplex.js so i can use that too ;).
import { programs } from "#metaplex/js"
this is the import statement used and this is the error i get
Uncaught TypeError: Error during the resolution of the module identificator “#metaplex/js”. Module identificators must start with “./”, “../” o “/”.
You could try:
<script src="https://unpkg.com/#metaplex/js#latest/lib/index.iife.min.js">
</script>
Coming back to some old project, I discover nothing was loading. Checking the console log I see the following:
Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
In my script I got the following:
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three/build/three.module.js"
import { OBJLoader } from "https://cdn.skypack.dev/three/examples/jsm/loaders/OBJLoader.js"
import { FirstPersonControls } from "https://cdn.skypack.dev/three/examples/jsm/controls/FirstPersonControls.js"
I try to step back some versions and not until I reach 0.136.0 does this error go away. Has the way one imports three.js changed, or is this a bug?
Also, would there be some way of catching this at runtime? Like I get the latest version number from Skypack and try an import. If failed, automatically step back a decimal and try again.
Edit
#Mugen87 offers using importmap. I change my code with the following:
<script type="importmap">
{
"imports": {
"three": "https://cdn.skypack.dev/three/build/three.module.js",
"three/OBJLoader": "https://cdn.skypack.dev/three/examples/jsm/loaders/OBJLoader.js",
"three/FirstPersonControls": "https://cdn.skypack.dev/three/examples/jsm/controls/FirstPersonControls.js"
}
}
</script>
<script type="module">
import * as THREE from "three"
import { OBJLoader } from "three/OBJLoader"
import { FirstPersonControls } from "three/FirstPersonControls"
I get the following error:
Uncaught SyntaxError: The requested module '/-/three#v0.137.5-HJEdoVYPhjkiJWkt6XIa/dist=es2019,mode=raw/build/three.module.js' does not provide an export named 'default'
The CDN you're using (cdn.skypack.dev) does some re-exporting on their side, which is causing the problem.
The file you're referencing in your import isn't actually the three.js module, but a re-direct.
That file does an export * (which is fine), AND an export {default}, which is where the failure is occurring. Three.js does not have a default export.
Skypack is likely applying this redirect universally to all modules, so it's not that they necessarily KNOW this is happening, but they should definitely be testing their system before hosting a specific module...
Try changing your importmap to reference the following URL, and it should work:
https://cdn.skypack.dev/-/three#v0.137.5-HJEdoVYPhjkiJWkt6XIa/dist=es2019,mode=raw/build/three.module.js
I try to import mathjs as a module in a browser (client side). I copied this file on the server, and then try to import the JS module, but it always fails. Here are some trial I already made:
import { mathjs } from "./math.min.js"
SyntaxError: The requested module './../modules/math.min.js' does not
provide an export named 'mathjs'
import { math } from "./math.min.js"
SyntaxError: The requested module './../modules/math.min.js' does not
provide an export named 'math'
import { create, all } from "./math.min.js"
SyntaxError: The requested module './math.min.js' does not provide an export named 'all'
I also try:
import("/math.min.js");
Uncaught (in promise) TypeError: Cannot set property 'math' of undefined
Note that the path is OK, I checked. I'm probably missing something, but I can't find what I am doing wrong. Any help is welcome.
Here is a repl.it with the code: https://repl.it/#FifiLulu/NewJollyRoutes
You'll need to add:
<script type="module">
to your html file.
Lets say I import the following html file with
<link rel="import" href="somefile.html">
and the somefile.html looks like this:
<template>
<some-tags>...</some-tags>
</template>
<script type="module">
export default { some object }
</script>
Normally I would import a es6 module like so
import MyVariable from 'somefile.js'
but in this case I cannot point to the html file and I don't know how to import the module I imported through the link. Is that even possible or do I need to replace the export default with a global variable?
Module support in browsers is very new and being done in small bites. As far as I can tell from what specification we have for this so far, the only module specifiers currently supported are URLs that refer to a JavaScript resource. The export you've shown can't currently be imported. From that linked spec:
To resolve a module specifier given a script script and a JavaScript string specifier, perform the following steps. It will return either a URL record or failure.
Apply the URL parser to specifier. If the result is not failure, return the result.
If specifier does not start with the character U+002F SOLIDUS (/), the two-character sequence U+002E FULL STOP, U+002F SOLIDUS (./), or the three-character sequence U+002E FULL STOP, U+002E FULL STOP, U+002F SOLIDUS (../), return failure.
This restriction is in place so that in the future we can allow custom module loaders to give special meaning to "bare" import specifiers, like import "jquery" or import "web/crypto". For now any such imports will fail, instead of being treated as relative URLs.
Return the result of applying the URL parser to specifier with script's base URL as the base URL.
Instead, move that export into its own file and import it with a module specifier referring to the file.
You might extract the code into a another file, e.g. somefile.js :
export default {
//...
};
Then you can import that in your template:
<template>
<some-tags>...</some-tags>
</template>
<script type="module">
import somefile from "somefile.js";
//... Whatever
</script>
And in any other code... Note that you currently must use webpack or a similar system to convert your code to ES6. Javascript modules are not well supported yet.
I know that in the new ES6 module syntax, the JavaScript engine will not have to evaluate the code to know about all the imports/exports, it will only parse it and “know” what to load.
This sounds like hoisting. Are the ES6 modules hoisted? And if so, will they all be loaded before running the code?
Is this code possible?
import myFunc1 from 'externalModule1';
myFunc2();
if (Math.random()>0.5) {
import myFunc2 from 'externalModule2';
}
After doing some more research, I've found:
Imports ARE hoisted! according to the spec of ModuleDeclarationInstantiation
ALL the dependent Modules will be loaded before running any code.
This code will have no errors, and will work:
localFunc();
import {myFunc1} from 'mymodule';
function localFunc() { // localFunc is hoisted
myFunc1();
}
It will be a SyntaxError. According to this part of specification:
Module :
ModuleBody
ModuleBody :
ModuleItemList
ModuleItemList :
ModuleItem
ModuleItemList ModuleItem
ModuleItem :
ImportDeclaration
ExportDeclaration
StatementListItem
It means that module can contain only ImportDeclaration's, ExportDeclaration's or StatementListItem's.
According to this StatementListItem could
not contain ImportDeclaration nor ExportDeclaration.
import myFunc1 from 'externalModule1';
is an import declaration, while:
if (Math.random()>0.5) {
import myFunc2 from 'externalModule2';
}
is a statement. So your code will result to a syntax error.
What about "will they all be loaded before running the code?". This part of specification contain next sentence:
NOTE: Before instantiating a module, all of the modules it requested must be available.
So, yeah. They will all be loaded before running the code.
ES6 specification is a subject to change but this draft is explicit:
The static variable resolution and linking pass checks for conflicts
in imported variable names. If there is a conflict between two
imported names, or an imported name and another local binding, then it
is a compile-time error.
And trying to import at runtime is doubtful idea, not only in ES6. Also from the draft:
Compilation resolves and validates all variable definitions and
references. Linking also happens at compile-time; linking resolves and
validates all module imports and exports.
You can see that Babel's ES6 implementation isn't too happy with it.