动态 import()

https://v8.dev/features/dynamic-import

Dynamic import() 引入了一个新的类似函数的功能,相比静态的 import 提供了新的功能。本文比较这两个特性,并提供了新功能的介绍。

静态 import (回顾)

在 Chrome 61 中提供了对于 ES2015 的 modulesimport 语句的支持。

考虑如下 module,它位于地址 ./utils.mjs

// Default export
export default () => {
console.log('Hi from the default export!');
}; // Named export `doStuff`
export const doStuff = () => {
console.log('Doing stuff…');
};

如下代码演示如何使用静态导入,并使用 ./util.mjs 模块。

<script type="module">
import * as module from './utils.mjs';
module.default();
// → logs 'Hi from the default export!'
module.doStuff();
// → logs 'Doing stuff…'
</script>

注意

在上述示例中,使用了 .mjs 扩展名来表示这个一个模块,而不是常规的脚本。

在 Web 中,文件的扩展名并不重要,只要在 Content-Type 响应头中使用了正确的 MIME 类型即可 ( 例如,对于 JavaScript 文件来说,为 text/javascript) 。

.mjs 扩展名对于其它平台特别有用,比如 Node.js 和 d8,因为在这些环境中,没有 MIME 的支持或者其它强制的要求,例如 type="module" 来检测它到底是模块还是常规的脚本。我们这里使用 .mjs 扩展名来实现跨平台的一致性,并清楚地区分模块和常规脚本。

这里使用的导入模块方式就是 静态 定义:它只接受一个字面字符串作为模块的指示器,通过链接过程将绑定引入到本地范围。静态的 import 语法只能用于文件的顶级。

静态 import 支持重要的使用场景,例如静态分析,打包工具以及摇树操作。

对于有些场景,需要支持:

  • 按需加载模块 ( 或者有条件 )
  • 在运行时得到模块的指示符
  • 从常规的脚本 ( 不是模块) 中加载模块

这些需求都不能通过静态 import 得到。

动态 import()

Dynamic import() 引入了 import 的新特性来处理这些场景。import(moduleSpecifier) 返回请求模块的模块对象的一个 Promise。它将在获取之后创建,并检查该模块所有的依赖,以及该模块本身。

这里是如何使用动态 import() 来加载 ./utils.mjs 模块。

<script type="module">
const moduleSpecifier = './utils.mjs';
import(moduleSpecifier)
.then((module) => {
module.default();
// → logs 'Hi from the default export!'
module.doStuff();
// → logs 'Doing stuff…'
});
</script>

由于 import() 返回一个 Promise,就可以使用 async/await 来代替 Promise 的 then() 调用风格。

<script type="module">
(async () => {
const moduleSpecifier = './utils.mjs';
const module = await import(moduleSpecifier)
module.default();
// → logs 'Hi from the default export!'
module.doStuff();
// → logs 'Doing stuff…'
})();
</script>

注意

尽管 import() 看起来类似一个函数调用,实际上它是一个语法,只是使用了圆括号而已,类似 super()。这意味着 import() 的原型并不是 Function.prototype,所以你也不能对它使用 call() 或者 apply()

类似语法也不能工作 const importAlias = import,甚至,import 都不是一个对象!尽管在实践中并不重要。

这里是一个使用动态 import() 来实现延迟加载模块的示例,基于一个小型的 SPA 应用的导航。

<!DOCTYPE html>
<meta charset="utf-8">
<title>My library</title>
<nav>
<a href="books.html" data-entry-module="books">Books</a>
<a href="movies.html" data-entry-module="movies">Movies</a>
<a href="video-games.html" data-entry-module="video-games">Video Games</a>
</nav>
<main>This is a placeholder for the content that will be loaded on-demand.</main>
<script>
const main = document.querySelector('main');
const links = document.querySelectorAll('nav > a');
for (const link of links) {
link.addEventListener('click', async (event) => {
event.preventDefault();
try {
const module = await import(`/${link.dataset.entryModule}.mjs`);
// The module exports a function named `loadPageInto`.
module.loadPageInto(main);
} catch (error) {
main.textContent = error.message;
}
});
}
</script>

当正确使用的时候,使用动态 import() 来实现延迟加载可以非常强大,为了演示目的,Addy 创建了 an example Hacker News PWA,其中使用静态导入所有依赖的模块,在第一次加载的时候加载留言。更新后的版本 使用动态 import() 来延迟加载留言,避免了加载、解析和编译的代价,直到用户需要才会处理。

参考资料

动态 import()的更多相关文章

  1. React动态import()

    React动态import() react-router@v4代码分离,推荐的import().这里分享webpack配置和使用方法. 首先安装两个必须的包 cnpm i react-loadable ...

  2. python3 动态import

    有些情况下,需要动态的替换引入的包 1.常用的import方法 import platform import os 2.__import__ 动态引用 loop_manager = __import_ ...

  3. Element + Vue I18n动态import加载国际化语言包翻译文件

    需求 项目为多页应用,包含产品a.b.c.d.e,每个产品都有自己的翻译文件.一次加载所有翻译文件是极度不合理的.于是考虑动态加载. 实现 参考官方文档:延迟加载翻译 项目结构 │ ├── dist ...

  4. vite 动态 import 引入打包报错解决方案

    关注公众号: 微信搜索 前端工具人 ; 收货更多的干货 原文链接: 自己掘金文章 https://juejin.cn/post/6951557699079569422/ 关注公众号: 微信搜索 前端工 ...

  5. vue 动态路由按需加载的三种方式

    在Vue项目中,一般使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,如: import Hello from '@/components/Hell ...

  6. 如何实现 React 模块动态导入

    如何实现 React 模块动态导入 React 模块动态导入 代码分割 webpack & code splitting https://reactjs.org/docs/code-split ...

  7. Angular中懒加载一个模块并动态创建显示该模块下声明的组件

    angular中支持可以通过路由来懒加载某些页面模块已达到减少首屏尺寸, 提高首屏加载速度的目的. 但是这种通过路由的方式有时候是无法满足需求的. 比如, 点击一个按钮后显示一行工具栏, 这个工具栏组 ...

  8. Spring Boot中@Import三种使用方式!

    需要注意的是:ImportSelector.ImportBeanDefinitionRegistrar这两个接口都必须依赖于@Import一起使用,而@Import可以单独使用. @Import是一个 ...

  9. python 学习笔记十五 web框架

    python Web程序 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. Python的WEB框架分为两类: 自己写socket,自 ...

  10. Vue路由vue-router

    前面的话 在Web开发中,路由是指根据URL分配到对应的处理程序.对于大多数单页面应用,都推荐使用官方支持的vue-router.Vue-router通过管理URL,实现URL和组件的对应,以及通过U ...

随机推荐

  1. SXYZ-7.4训练赛

    今天这场比赛把人心态考崩溃了,只考100分钟,四道思考和算法题,旁边大佬开局5分钟秒T1,我30分钟打了个T1暴力.┭┮﹏┭┮,呜呜~.T2,T4根据题意暴力.T3人手模拟了一下,完全没有任何思路,放 ...

  2. Python技术书示例代码相关内容

    二维码用微信扫,按提示填写你的邮箱,转到电脑上打开邮箱下载.清华国企网盘,比较快速.安全.放心下载. 百度网盘链接 用Edge/Chrome浏览器下载. <Python自动化运维快速入门> ...

  3. Awesome-Visual-Captioning

    目录 Table of Contents Paper Roadmap ACL-2021 CVPR-2021 AAAI-2021 ACMMM-2020 NeurIPS-2020 ECCV-2020 Vi ...

  4. 在Ubuntu小设备上使用VSCode+SSH开发部署nicegui的Web应用,并设置系统开机自动启动应用

    在一些小的设备上跑Ubuntu系统,需要快速的开发和调整项目的时候,往往使用SSH进行远程的开发测试,这样可以避免传统的打包更新处理,能够快速的在实际环境上测试具体的内容.另外由于系统设备往往需要重启 ...

  5. 元类、实现ORM

    阅读目录: 元类 元类实现ORM 元类 1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: >>> class Obj ...

  6. H5移动端字体自适应(也适用于宽高)

    原文地址: https://mp.weixin.qq.com/s/hhmav2sbAgb7w17ipVZiTw 方法一:纯css方法, 精确度高,IOS 和 安卓 字体大小同等比例1.1 以16px为 ...

  7. JS 数组转对象 对象转数组 对象数组互相转换 数组对象互相转换

    JS 数组转对象 对象转数组  对象数组互相转换  数组对象互相转换 声明一个函数,arr_obj ,里面接收一个参数,参数类型只接受对象或者数组 如果没有传递任何参数  或者 传递的参数类型不符合要 ...

  8. [Windows]文件搜索利器Everything(附zip)

    前言 写代码过程中,老大突然发一条信息 老大:这周周报发一下. 我:好的. 然后我就 显示桌面 打开-我的电脑 找到E盘,找到周报文件夹 寻找到所有周报中今天的周报 复制发送 当我用上Everythi ...

  9. 改变mysql默认字符集为utf8

    问题:在使用mysql时,使用php插入数据库.查询数据库信息会出现乱码 解决:修改mysql配置文件,在其配置文件中加入一下代码 init_connect='SET collation_connec ...

  10. RL 基础 | 如何使用 OpenAI Gym 接口,搭建自定义 RL 环境(详细版)

    参考: 官方链接:Gym documentation | Make your own custom environment 腾讯云 | OpenAI Gym 中级教程--环境定制与创建 知乎 | 如何 ...