作用
它允许将模块异步和动态地加载到可能的非模块环境中,实现代码分割使代码更加模块化,从而提高网页性能。
与import语句的区别
静态导入在代码编译阶段就解析和执行模块 import { add } from './math'; Tree Shaking就利用了ES6模块的静态结构特性 import和export。import
语句在代码执行前被解析,因此只能在模块的顶部使用。import
是同步的,这意味着它会阻塞代码的执行,直到模块被加载完毕。
import()动态导入在需要时(运行时)才动态地加载和执行模块,并允许更高的语法灵活性。
原理
当使用import()函数时,它会在运行时解析和执行模块代码,并返回一个Promise对象。这个Promise对象会在模块异步加载和执行完成后解析为模块的导出值。
工作流程
- 解析模块URL:首先,import()函数需要一个模块的URL或路径来确定要加载的模块。这个URL可以是相对路径,也可以是绝对路径。
- 创建ScriptLoader:浏览器会为每个import
()
调用创建一个新的ScriptLoader。ScriptLoader是一个负责加载和执行模块的单独线程。 - 发送HTTP请求:ScriptLoader使用HTTP或HTTPS协议,从提供的URL发送一个GET请求来获取模块的源代码。
- 解析模块源代码:当模块的源代码被成功获取后,浏览器开始解析源代码。如果源代码包含任何语法错误,那么ScriptLoader将抛出一个错误,并且Promise被拒绝。
- 执行模块代码并返回结果:一旦源代码被成功解析,它会被执行。执行的结果(即模块的导出值)会被返回给Promise的resolve回调。如果模块抛出任何错误,Promise会被拒绝,并且错误会被传递给Promise的reject回调。
- 返回Promise对象:无论模块是否成功加载和执行,
import()
函数都会返回一个Promise对象。如果模块加载和执行成功,Promise会被解析为模块的导出值;如果加载或执行失败,Promise会被拒绝并传递错误信息。
使用场景
// 异步加载模块
import('module.js')
.then((module) => {
// 使用模块
})
.catch((error) => {
// 处理加载错误
});
// 按需加载模块
button.addEventListener('click', () => {
import('./module.js')
.then((module) => {
// 使用模块
})
.catch((error) => {
// 处理加载错误
});
});
// 件加载模块
if (condition) {
import('./module.js')
.then((module) => {
// 使用模块
})
.catch((error) => {
// 处理加载错误
});
} else {
// 执行其他逻辑
}
VUE中使用
// 在一个路由配置中,你可以像这样使用动态
// webpackChunkName把 @/views/Forecast.vue 单独打包成一个名为 forecast.[hash].js 的代码块,并且只有当用户导航到 /forecast 路由时才会下载这个代码块
const Forecast = () => import(/* webpackChunkName: "forecast" */ '@/views/Forecast.vue')
// Webpack 魔术注释以方便 Webpack 在编译过程中进行优化和分割。
// 此外,除了 webpackChunkName,Webpack 还支持其他的魔术注释,比如 webpackPrefetch 和 webpackPreload,分别用于标记一个模块是否应该被预加载或预读取。
// 在组件中使用动态导入来加载其他模块或组件,保证只有在需要的时候才被加载和渲染
export default {
components: {
'child-component': () => import('@/components/ChildComponent.vue'),
},
}
注意
可以用于加载任何类型的模块,包括JavaScript模块、JSON模块、CSS模块等。
由于import()
是异步的,因此不能直接使用import()
来同步加载模块。
需要使用.then()
方法或async/await
语法来处理异步加载和执行结果
需要注意的是,动态导入并不意味着可以忽略静态类型检查。在TypeScript中,你可以使用any类型来规避静态类型检查,但这样会失去TypeScript的类型安全保障。因此,在使用动态导入时,建议结合TypeScript的类型定义来确保代码的类型安全。
与reqiure的区别
- 语法:
import()
是 ES6 中的模块加载语法,是异步的。require
()则是在 Node.js (CommonJS 规范)中使用的模块加载语法,用于从其他文件中引入并运行模块,它是同步的,即在加载过程中会阻塞脚本的执行。 - 导入内容:
import()
只能导入模块中export
的成员,而require
可以引用模块中的任意一个成员。 - 缓存:
require
在加载模块时会缓存模块,如果多次require
同一个模块,则只会执行一次该模块的代码(缓存的是结果)。而import()
则不会缓存模块,每次import()
都会重新解析模块代码。 总的来说,import()
更适合在前端开发中使用,因为它具有更好的性能和更简洁的语法。而require
则更适合在后端开发中使用,因为它支持更多的功能和更加灵活。