深入理解Javascript中的import()

113 阅读2分钟

import()

Javascript中的import()语法,也被称作动态导入(dynamic import)。它允许异步地将Javascript模块加载到非模块代码中。

所谓Javascript模块,是指使用export关键字导出的模块。比如以下代码:

export const site = 'runjs.work'
export default function axios() {
  console.log('mock axios')
}

将其保存为es-module.js,方便后面使用。

浏览器运行

在浏览器中,使用<script type="module"></script>语法,可以直接加载Javascript模块。

将上面的es-module.js上传到RunJS静态文件仓库中,得到一个公网访问的地址:

https://s1.qingting.work/runjs/063f7158b7044f04/8adbd4be0620.js

创建一个RunJS项目,并在JS版块粘入以下代码,选择编译类型为Module:

import('https://s1.qingting.work/runjs/063f7158b7044f04/8adbd4be0620.js').then(({default: axios, site}) => {
  axios();
  console.log(site);
})

如下图所示,我们可以看到,浏览器成功地加载了es-module.js中导出的axios和site变量: image

在RunJS中打开示例代码

那么,兼容性如何呢? image

MDN显示,主流新版浏览器,对Javascript模块的支持,都是不错的。至少,在开发阶段使用Javascript模块,能大大缩小编译工具的负担。这也是目前大部分前端框架在开发模式下采用的Js输出格式。

Node.js运行

在Node.js中,有两种方式运行Javascript模块。

第一种,是将所有相关文件以.mjs后缀命名。

准备以下两个文件,放在同一目录: es-module.mjs,内容如下:

export const site = 'runjs.work'
export default function axios() {
  console.log('mock axios')
}

index.mjs,内容如下:

import('./es-module.mjs').then(({default: axios, site}) => {
  console.log(site)
  axios()
})

用node运行:

node ./index.mjs

可以看到正确的输出: image

第二种,是借助babelwebpack之类的编译工具,将其转换为commonjs格式。

准备以下两个文件,放在同一目录(src/): es-module.js,内容如下:

export const site = 'runjs.work'
export default function axios() {
  console.log('mock axios')
}

index.js,内容如下:

import('./es-module.js').then(({default: axios, site}) => {
  console.log(site)
  axios()
})

用node运行:

node ./index.js

不允许直接运行: image

webpack编译一下。

安装webpack,并创建webpack.config.js

npm install --save-dev webpack webpack-cli

webpack.config.js内容如下:

const path = require('path')

module.exports = {
  mode: 'production',
  entry: {
    index: './src/index.js',
  },
  target: 'node',
  optimization: {
    minimizer: [false]
  }
}

webpack中的target默认是web,所以这里我们需要显性声明打包目标平台是Node.js.指定minimizer[false],可以让webpack打包的目标代码不压缩。

package.json中添加打包命令:

{
  "scripts": {
    "build": "webpack"
  }
}

运行打包,会在dist/目录生成index.js

npm run build

运行打包后的代码:

node dist/index.js

也可以看到正确的输出。 image

分析一下。打包后生成了入口文件dist/index.js和chunk文件dist/274.js

dist/index.js引入了dist/274.js。引入的方法由import变成了requireimage

也就是说,webpack默认识别javascript模块,并将其打包成独立的文件。不少前端框架基于路由做代码分割(Code Splitting)的原理,就是将页面的代码通过import()方式导入。

总结

import()在浏览器端的支持,使得web项目在开发阶段的打包效率大大提升。

import()要在Node.js上使用,则需要webpackbabel之类的工具支撑。webpack对于import()的处理,有利于灵活配置Code Splitting的分割点。

引用本文请注明来处。

原文地址:runjs.work/article/128…