JavaScript ES6 importmap详解

编程教程 > WEB > JavaScript (275) 2024-11-26 14:39:04

importmap是一种针对web页面去控制imports行为的新方式,潜在地可以使你摈弃掉你的构建系统。

当Es modules在Ecmascript 2015中第一次被引进并作为标准化js模块系统的一种方式,它是通过在import语句中强制指定相对或绝对路径来实现的。

 

ES6 案例参考:

import dayjs from "https://cdn.skypack.dev/dayjs@1.10.7"; // ES modules
console.log(dayjs("2024-01-25").format("YYYY-MM-DDTHH:mm:ssZ[Z]"));

执行结果:

JavaScript ES6 importmap详解_图示-d76d1b3d72ee4ce5948e0b3e2b67f377.png

 

这与其他的通用模块系统(像是CommonJs)的工作模式有细微的差别,并且在使用类似webpack的模块bunlder时使用了更简单的语法:

const dayjs = require('dayjs') // CommonJS
import dayjs from 'dayjs'; // webpack

在这些系统中,import说明符通过Node.js运行时或相关的构建工具映射到特定(和版本化)文件。用户只需在import语句中应用最简单的说明符(通常是包名),就可以自动解决模块解析问题。

由于开发人员已经熟悉从npm导入包的这种方式,因此需要一个构建步骤来确保以这种方式编写的代码可以在浏览器中运行。import-maps解决了这个问题。本质上,它允许将import说明符映射到相对或绝对URL,这有助于在不应用构建步骤的情况下控制模块。

说人话就:是 importmap 给你创建了一个快捷键地址,或者用Linux的软连接功能相似。

 

importmap的使用方式

<div style="margin-bottom:10px;">
    <label>时间解析结果:</label><span id="time"></span>
</div>

<script type="importmap">
    {
     "imports": {
       "dayjs": "https://cdn.skypack.dev/dayjs@1.10.7"
     }
    }
</script>
<script type="module">
    import dayjs from "https://cdn.skypack.dev/dayjs@1.10.7"; // ES modules
    let result = dayjs("2024-01-25").format("YYYY-MM-DDTHH:mm:ssZ[Z]");
    let $time = document.querySelector('#time');
    $time.innerHTML = result;
</script>
JavaScript ES6 importmap详解_图示-f96e859365d046dd822229547eed7fb5.png

 

importmap是通过HTML文档中的

在script标记中,JSON对象用于为文档中脚本所需的模块指定所有必要的映射。典型importmap的结构如下所示:
<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>
在上面的imports对象中,每个属性都对应于一个映射。映射的左侧是import说明符的名称,而右侧是说明符应映射到的相对或绝对URL。在映射中指定相对URL时,请确保它们始终以/、../、,或./。请注意,importmap中存在的包并不一定意味着它将由浏览器加载。页面上脚本未使用的任何模块都不会被浏览器加载,即使它存在于import map中。
 
您还可以在外部文件中指定映射,然后使用src属性链接到该文件(如上所示)。如果您决定使用这种方法,请确保发送的文件的Content-Type头设置为application/importmap+json。请注意,出于性能原因,建议使用内联方法,即本文剩余部分将如何展示示例的方式。
<script type="importmap" src="importmap.json"></script>

 

指定mapping后,可以在import语句中使用import说明符,如下所示:

<script type="module">
 import { cloneDeep } from 'lodash';
 const objects = [{ a: 1 }, { b: 2 }];
 const deep = cloneDeep(objects);
 console.log(deep[0] === objects[0]);
</script>

 

应该注意,import map中的映射不会影响URL,例如<script>标记的src属性。因此,如果您使用类似

将说明符映射到整个包

除了将说明符映射到模块之外,还可以将一个说明符映射到包含多个模块的包。这是通过使用以斜杠结尾的说明符键和路径来完成的。

<script type="importmap">
{
 "imports": {
   "lodash/": "/node_modules/lodash-es/"
 }
}
</script>

此操作允许您导入指定路径中的任何模块,而不是整个主模块,这将导致浏览器下载所有组件模块。

<script type="module">
 import toUpper from 'lodash/toUpper.js';
 import toLower from 'lodash/toLower.js';
 console.log(toUpper('hello'));
 console.log(toLower('HELLO'));
</script>

动态构建importmap

映射也可以基于任意条件在脚本中动态构建,并且该功能可以用于基于特征检测有条件地导入模块。下面的示例根据IntersectionObserver API是否受支持,选择要在lazyload说明符下导入的正确文件。

<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>

如果要使用此方法,请确保在创建和插入import maps脚本标记之前执行此操作(如上所述),因为修改现有的导入映射对象不会产生任何效果。

通过Hash映射来提高脚本的缓存

实现静态文件长期缓存的一种常见技术是在文件的名称中使用文件内容的哈希值,以便在文件内容发生更改之前,文件仍保留在浏览器缓存中。发生这种情况时,文件将获得一个新名称,以便最近更新立即反映在应用程序中。

对于bundler脚本的传统方式,如果更新几个模块所依赖的依赖项,则此技术可能会失败。这将导致依赖于该依赖项的所有文件被更新,这将迫使浏览器重新下载它们,即使只更改了一个字符的代码。

Import Maps允许通过重新映射技术分别更新每个依赖项,从而解决了这个问题。假设您需要从名为post.bundle8cb615d12a121f6693aa.js的文件中导入一个方法,您可以有一个如下所示的importmap:

<script type="importmap">
 {
   "imports": {
     "post.js": "./static/dist/post.bundle.8cb615d12a121f6693aa.js",
   }
 }
</script>

相较于如下的书写方式:

import { something } from './static/dist/post.bundle.8cb615d12a121f6693aa.js'

你可以像下面这样写:

import { something } from 'post.js'

当更新文件时,只需要更新import map。由于对其导出的引用没有更改,因此由于hash变化而更新的脚本再次下载时,它们将保持缓存在浏览器中。

<script type="importmap">
 {
   "imports": {
     "post.js": "./static/dist/post.bundle.6e2bf7368547b6a85160.js",
   }
 }
</script>

使用同一个模块的不同版本

importmap中使用同一个模块的不同版本是很容易的一件事,你只需要在mapping中申明不同的说明符即可,像这样:

<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>

你同样可以通过不同作用域来设定同一个说明符作为同一个包的不同版本,这允许您在给定范围内更改import说明符的含义。

<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>

通过这个mapping,任何在/static/js路径下面使用了lodash/说明符的引用都会关联到3.10.1的版本,其他的则关联到4.17.21的版本。

NPM包与Import Maps一起使用

正如我在本文中所演示的,使用ES模块的任何NPM包的生产版本都可以通过ESM、Unpkg和Skypack等CDN在Import Maps中使用。即使NPM上的软件包不是为ES模块系统和本地浏览器导入行为而设计的,Skypack和ESM等服务也可以将其转换为可在import map中使用的软件包。您可以使用Skypack主页上的搜索栏来查找浏览器优化的NPM包,这些包可以立即使用,而无需修改构建步骤。

代码检测Import Maps支持

只要判断HTMLScriptElement.supports()方法,就可以在浏览器中检测Import Mpas支持。以下代码段可用于此目的:

if (HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) {
 // import maps is supported
}

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
Import Maps是一种针对web页面去控制imports行为的新方式,潜在地可以使你摈弃掉你的构建系统。当Es modules在Ecmascript 20
Promise 的含义Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了
简单使用创建一个js文件。//Say 模块export function Say(words){ alert(words);}H5调用模块&lt;!DOCTYPE h
在IDEA中对如下标签进行修改:File-&gtl;settings-&gtl;Languages & Frameworks-&gtl;JavaScript 中的参数JavaScript lan...
主流模块规范目前主流模块规范有:规范名称运行环境实现加载方式AMD(异步模块定义)客户端require.js异步CMD(通用模块定义)客户端sea.js异步Co
javascript中onclick事件传递对象参数,javascript,javascript传递对象参数
方式一 spliceJavaScript 中的 splice() 方法可用于在数组中添加或删除元素。如果我们需要删除数组中的元素,可以使用 splice() 方
JavaScript/JS读取文本/JSON文件内容let file = files[0];var reader = new FileReader();read
JavaScript/JS数组清空,删除数组内所有数据。Array=[]与Array.length=0的区别
JavaScript H5原生操作元素class,包括获取元素class值,设置class值修改元素class值操作。示例数据 &lt;head&gtl; &lt;meta cha
前言在其他编程语言中,我们可以通过划分模块,来组织庞大复杂的项目,而JS一开始并没有模块的概念,因为一开始JS的脚本就很简单。后来随着JS的发展,前端要开发的项
​JavaScript 数学小数精确计算&lt;!DOCTYPE html&gtl; &lt;html&gtl; &lt;head&gtl; &lt;title&gtl;&lt;/tit...
简介 使用 JavaScript 改变 URL 参数值并且页面不刷新的方法有两种模式:使用 History replaceState使用 History pus
JavaScript正则加上/去掉cdn域名前缀,文本支持&lt;script&gtl;let $domain="https://static-project.example
&lt;body&gtl; &lt;script type="text/javascript"&gtl;   function test(){     let obj={        ...