Hello. With the release of Chrome 89 (as well as Deno 1.8), it became possible to use Import maps - a mechanism that allows you to gain control over the behavior of JavaScript imports.
Despite the fact that modern development is built using native modules, we cannot run applications without first building them. One of the goals of import maps is precisely to solve this problem.
In short, now it will be completely legal and without any collectors to write, say, like this:
import React from 'react';
Let's see how it all works under the cut.
In order for the import directive or import () expression to be able to resolve paths to modules in a new form, these paths need to be described somewhere. Yes, there turned out to be no magic with the engine compartment resolution of dependencies as in the same Node.js or webpack.
Import maps are specified using a script tag with a type = "importmap" attribute in JSON format.
And now for an example. We start a static server (for example, using python -m SimpleHTTPServer 9000) and create two files:
index.html
<!DOCTYPE html>
<html>
<body>
<script type="importmap">
{
"imports": {
"mylib": "./my-lib.mjs"
}
}
</script>
<script type="module">
import { sayHi } from "mylib";
sayHi();
</script>
</body>
</html>
and my-lib.mjs
export function sayHi() {
console.log("hi!");
}
We open the page in the browser, and voila: "hi!" Was displayed in the console. Next, let's take a closer look at how it works.
Structure
, , JSON : imports scopes. - , ( ).
Imports
imports β , ( ) . /, ../, ./ URL.
"imports": {
"module-name": "address"
}
"", . / .
"my-pack" index.mjs :
export default function mainFunc() {
console.log("text from mainFunc");
}
"my-pack" "some-module" some-helper.mjs :
export function someHelper() {
console.log("text from someHelper");
}
importmap index.html:
<script type="importmap">
{
"imports": {
"mypack": "./my-pack/index.mjs",
"mypack/": "./my-pack/"
}
}
</script>
,
import mainFunc from "mypack";
import { someHelper } from "mypack/some-module/some-helper.mjs";
Scopes
, (, ), , . . :
<script type="importmap">
{
"imports": {
"mypack": "./my-pack/index.mjs",
"mypack/": "./my-pack/"
},
"scopes": {
"some/other/url/": {
"mypack": "./my-pack/index-v2.jsm"
}
}
}
</script>
, url some/other/url/ "mypack" "./my-pack/index-v2.jsm", "./my-pack/index.mjs".
. :
<script type="importmap">
{
"imports": {
"a": "/a-1.mjs",
"b": "/b-1.mjs",
"c": "/c-1.mjs"
},
"scopes": {
"/scope2/": {
"a": "/a-2.mjs"
},
"/scope2/scope3/": {
"b": "/b-3.mjs"
}
}
}
</script>
:
Specifier |
Referrer |
Resulting URL |
a |
/scope1/foo.mjs |
/a-1.mjs |
b |
/scope1/foo.mjs |
/b-1.mjs |
c |
/scope1/foo.mjs |
/c-1.mjs |
|
|
|
a |
/scope2/foo.mjs |
/a-2.mjs |
b |
/scope2/foo.mjs |
/b-1.mjs |
c |
/scope2/foo.mjs |
/c-1.mjs |
|
|
|
a |
/scope2/scope3/foo.mjs |
/a-2.mjs |
b |
/scope2/scope3/foo.mjs |
/b-3.mjs |
c |
/scope2/scope3/foo.mjs |
/c-1.mjs |
, script. :
<script type="importmap">
{
"imports": { ... },
"scopes": { ... }
}
</script>
src:
<script type="importmap" src="some/address/to/import-map.importmap"></script>
, MIME type application/importmap+json.
, .
, :
An import map is added after module script load was triggered.
. , . :
Multiple import maps are not yet supported. https://crbug.com/927119
Deno
In Deno, import maps are connected using the --import-map flag:
deno run --import-map=import_map.json index.ts
Where import_map.json is the import map and index.ts is the file to run (compile).