A new series is out: Vue2 and Vue3 Tips Booklet
Wechat search [Great Relocation to the World], I will share with you the front-end industry trends, learning methods, etc. as soon as possible.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
When ES modules were first introduced in ECMAScript 2015 as a way to standardize the module system in JavaScript, it did so by specifying relative or absolute paths in the import
statement.
import dayjs from "https://cdn.skypack.dev/dayjs@1.10.7"; // ES modules
console.log(dayjs("2019-01-25").format("YYYY-MM-DDTHH:mm:ssZ[Z]"));
This is slightly different from how modules work in other common module systems, such as CommonJS, and a simpler syntax when using module bundlers like webpack.
const dayjs = require('dayjs') // CommonJS
import dayjs from 'dayjs'; // webpack
In these systems, import specifiers are mapped to a specific (and version) file via the Node.js runtime or related build tools. The user only needs to apply the bare module specifier (usually the package name) in the import statement, and issues surrounding module resolution are automatically resolved.
Since developers are already familiar with this way of importing packages from npm
a build step is required to ensure that code written this way will run in the browser. This problem is solved by import maps . Essentially, it allows import specifiers to be mapped to relative or absolute URLs, which helps control the resolution of modules without requiring a build step to be applied.
How import maps work
<script type="importmap">
{
"imports": {
"dayjs": "https://cdn.skypack.dev/dayjs@1.10.7",
}
}
</script>
<script type="module">
import dayjs from 'dayjs';
console.log(dayjs('2019-01-25').format('YYYY-MM-DDTHH:mm:ssZ[Z]'));
</script>
The import map is specified by the <script type="importmap">
tag in the HTML document. This script tag must be placed before the first <script type="module">
tag in the document (preferably in <head>
) in order for it to be parsed before module parsing. Also, currently only one import map
is allowed per document, and this restriction may be lifted in the future.
Inside the script
tag, a JSON object is used to specify all the necessary module mappings required by the script in the document. The structure of a typical import map is shown below.
<script type="importmap">
{
"imports": {
"react": "https://cdn.skypack.dev/react@17.0.1",
"react-dom": "https://cdn.skypack.dev/react-dom",
"square": "./modules/square.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
In the above imports
object, each attribute corresponds to a mapping. The left side of the mapping is import
the name of the specifier, while the right side is the relative or absolute URL to which the specifier should be mapped.
When specifying relative URLs in mappings, make sure they always start with /
, ./
or ./
. Note that the presence of a package in an import map does not mean that it will necessarily be loaded by the browser. Any module not used by script
on the page will not be loaded by the browser, even if it exists in the import map .
<script type="importmap" src="importmap.json"></script>
You can also specify your mapping in an external file, then link to that file using the src
attribute (as shown above). If you decide to use this method, be sure to set the Content-Type
header to application/importmap+json
when sending the file.
Note that inlining is recommended for performance reasons, and will be used in the rest of this article for examples.
Once the mapping is specified, the ---411d8120edfc2c019c1b96c2d141977a--- specifier can be used in the import
import
statement as follows
<script type="module">
import { cloneDeep } from 'lodash';
const objects = [{ a: 1 }, { b: 2 }];
const deep = cloneDeep(objects);
console.log(deep[0] === objects[0]);
</script>
It is important to note that the mapping in the import map does not affect locations such as the src
attribute of the <script>
tag. So if you use something like <script src="/app.js">
, the browser will try to download a literal app.js
file at that path, regardless of what's in the import map.
Map specifiers to the entire package
Instead of mapping a specifier to a module, you can also map a specifier to a package containing multiple modules. This is achieved by using a designator key and a path ending with a trailing slash.
<script type="importmap">
{
"imports": {
"lodash/": "/node_modules/lodash-es/"
}
}
</script>
This approach allows us to import any module in the specified path instead of the entire main module, which causes all component modules to be downloaded by the browser.
<script type="module">
import toUpper from 'lodash/toUpper.js';
import toLower from 'lodash/toLower.js';
console.log(toUpper('hello'));
console.log(toLower('HELLO'));
</script>
Dynamically build import maps
Mappings can also be constructed dynamically in scripts based on arbitrary conditions, a capability that can be used to conditionally import modules based on feature detection. The following example selects the correct file to import under the lazyload
specifier according to whether IntersectionObserver API
is supported.
<script>
const importMap = {
imports: {
lazyload: 'IntersectionObserver' in window
? './lazyload.js'
: './lazyload-fallback.js',
},
};
const im = document.createElement('script');
im.type = 'importmap';
im.textContent = JSON.stringify(importMap);
document.currentScript.after(im);
</script>
If you want to use this method, make sure to do so before creating and inserting the import map script tag (as above), as modifying an existing import map object will have no effect.
Improve script cacheability by mapping to hashes
A common technique for implementing long-term caching of static files is to use a hash of the file's content in the filename, so that the file remains in the browser's cache until the file's content changes. When this happens, the file will get a new name so that the latest update is immediately reflected in the app.
In the traditional way of bundling scripts, this technique can be problematic if a dependency that is depended on by multiple modules is updated. This will cause all files that depend on that dependency to be updated, forcing the browser to re-download them, even if only one character of the code is changed.
import map provides a solution to this problem by allowing each dependency to be updated individually through remapping techniques. Suppose you need to import a method from a file named post.bundle.8cb615d12a121f6693aa.js
:
<script type="importmap">
{
"imports": {
"post.js": "./static/dist/post.bundle.8cb615d12a121f6693aa.js",
}
}
</script>
Instead of writing this:
import { something } from './static/dist/post.bundle.8cb615d12a121f6693aa.js'
It can be written like this:
import { something } from 'post.js'
When updating the file, only import map
needs to be updated. Since the references to their exports have not changed, they will remain cached in the browser, while the updated script will be downloaded again due to the updated hash.
<script type="importmap">
{
"imports": {
"post.js": "./static/dist/post.bundle.6e2bf7368547b6a85160.js",
}
}
</script>
Use multiple versions of the same module
It is easy to implement multiple versions of a package in an import map, all you need to do is to use different import specifiers in the map, as shown in the following figure:
<script type="importmap">
{
"imports": {
"lodash@3/": "https://unpkg.com/lodash-es@3.10.1/",
"lodash@4/": "https://unpkg.com/lodash-es@4.17.21/"
}
}
</script>
By using scopes, the same import specifier can also be used to refer to different versions of the same package. This allows us to change the meaning of import specifiers within a given scope.
<script type="importmap">
{
"imports": {
"lodash/": "https://unpkg.com/lodash-es@4.17.21/"
},
"scopes": {
"/static/js": {
"lodash/": "https://unpkg.com/lodash-es@3.10.1/"
}
}
}
</script>
With this mapping, any module under the /static/js
path will use https://unpkg.com/lodash-es@3.10.1/
when referencing the lodash/specifier in an import statement, while other modules will use https://unpkg.com/lodash-es@4.17.21/
.
Using NPM packages with import map
As demonstrated in this article, any production version of an NPM package that uses ES Modules can be used in import maps via CDNs such as ESM, Unpkg, and Skypack.
Even though packages on NPM are not designed for the ES module system and native browser import behavior, services like Skypack and ESM can turn them into packages that can be used in import maps. The search bar on the Skypack homepage can be used to find browser-optimized NPM packages that can be used out of the box without fiddling with build steps.
Detect import map support
As long as the HTMLScriptElement.supports()
method is supported, the import map support can be detected in the browser:
if (HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) {
// import maps is supported
}
Support for older browsers
Import map makes it possible to use bare module specifiers in browsers without relying on the complex build systems that are currently prevalent in the JavaScript ecosystem, but which are not currently widely supported in web browsers.
At the time of writing this article, Chrome and Edge browsers version 89 and later have full support, but Firefox, Safari, and some mobile browsers do not support this technology. In order to preserve the use of import maps in these browsers, a suitable polyfill must be employed.
An example of a polyfill that can be used is the ES Module Shims polyfill , which adds support for import maps and other new module features to any browser that supports the ES Module Baseline (~94% of browsers). All we need to do is include the es-module-shim
script in the HTML file before the import map script
<script async src="https://unpkg.com/es-module-shims@1.3.0/dist/es-module-shims.js"></script>
After including the polyfill, you may get a JavaScript TypeError in your console. This error can be safely ignored as it has no user-facing consequences.
Summarize
The import map provides a more sane way to use ES modules in the browser, not limited to importing from relative or absolute URLs. This allows us to easily move code without having to adjust import statements, and makes updating individual modules more seamless without affecting the cacheability of scripts that depend on those modules. Overall, import maps bring equality to the way ES modules are used in servers and browsers.
The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool , Fundebug .
Author: romaopedro199 Translator: Front-end Xiaozhi Source: dev Original text: https://www.honeybadger.io/blog/import-maps/
comminicate
If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。