JS 模块化- 05 ES Module & 4 大规范总结

1 ES Module 规范

ES Module 是目前使用较多的模块化规范,在 Vue、React 中大量使用,大家应该非常熟悉。TypeScript 中的模块化与 ES 类似。

1.1 导出模块

导出模块有两种方式:按需导出默认导出

按需导出是使用 export 关键字,将需要导出的成员(变量、函数、对象等)依次导出:

export const xxx = '' export const xxx = () => {} 

一个模块中可以有多个按需导出,但只能有一个默认导出。假设默认导出 A 模块,当 B 模块直接导入模块 A 时,其导入的值就是模块 A 默认导出的值。

export default {} 

1.2 导入模块

导入按需导出的模块:

import { xxx } from 'xxx' 

上面语法中,花括号 {} 中的内容必须与导出的名称一致。

如果按需导出的成员较多,可以使用 as 一次性导入:

import * as xxx from 'xxx' 

导入默认导出的模块:

import xxx from 'xxx' 

也可以直接导入一个模块,并直接执行该模块的代码:

import 'xxxxx' 

2 使用 Webpack 编译 ES Module

2.1 初始化项目

创建 modules 目录,里面存放两个模块 module1.jsmodule2.js。入口文件与 modules 目录同级,名为 index.js。文件和目录结构如下:

05_ESM/   |- modules/     |- module1.js     |- module2.js   |- index.js   |- index.html 

2.2 实现两个模块

module1.js 使用按需导出变量 str1 和函数 fun1,默认导出 user 对象:

console.log('in module1')  export const str1 = 'hello module1'  export const fun1 = (msg) => {   return `module1:${msg}` }   const user = {   name: 'zhangsan',   age: 30 }  export default user 

module2.js 使用默认导出,导出一个对象,这个对象包括属性 str2 和方法 fun2

console.log('in module2')  const str2 = 'hello module2'  const fun2 = (msg) => {   return `module2:${msg}` }  export default {   str2,   fun2 } 

2.3 实现入口文件

在入口文件 index.js 中导入两个模块。由于 module1.js 是按需导出,故导入时需要使用 {}module2.js 是默认导出,故此处可以直接导入:

import { str1, fun1 } from './modules/module1' import m2 from './modules/module2'  console.log(str1) console.log(fun1('程序员优雅哥')) console.log(m2.str2) console.log(m2.fun2('youyacoder')) 

2.4 入口 HTML

创建 index.html 文件,使用 script 标签导入 index.js

<script src="./index.js"></script> 

在浏览器中访问 index.html 文件,控制台会提示如下错误:

Uncaught SyntaxError: Cannot use import statement outside a module (at index.js:1:1) 

这是由于浏览器不认识 ESM 语法。可以使用 babel 将 ES6 语法编译为 ES5 的语法,然后使用 browserify 进行打包;也可以使用 webpack 打包。此处我使用 webpack 5

2.5 使用 Webpack 打包

使用 npmyarn 初始化项目:

yarn init -y 

安装 webpackwebpack-cli 为开发依赖:

yarn add webpack webpack-cli -D  

使用 webpack 打包:

npx webpack ./index.js -o ./dist/ --mode development 

上面的打包命令直接在命令中配置参数,省略了额外的配置的文件。该命令指定了打包的入口文件为:index.js;输出的目录为 dist 目录,打包模式为 development。关于 webpack 5 的使用,有兴趣的可以看优雅哥的 webpack 5 系列文章。

执行完打包命令后,会生成 dist 目录,并且在该目录中有个 main.js 文件。

index.html 中删除之前引入的 index.js,替换为 dist/main.js

<script src="./dist/main.js"></script> 

重新在浏览器中访问 index.html, 控制台输出如下:

JS 模块化-  05 ES Module &amp; 4 大规范总结

3 ES Module 总结

导出模块:

  • 默认导出:export default xxx
  • 按需导出 export const xxx

导入模块:

  • 默认导入: import xxx from 'xxx'

  • 按需导入 import { xxx } from 'xxx'

4 JS 模块化 4 大规范总结

前面优雅哥依次写了模块化的发展史,模块化的规范(可进主页查看每个规范详细版本),现进行一个大汇总方便大家查阅和总结:

01- 模块化前传

02 - Common JS 规范

03 - AMD 规范(Require JS 实现)

04 - CMD 规范 (Sea JS 实现)

05 - ESM 规范

模块化相关 demo 源码可以 github 搜索关键词 js-module-demo 或联系 程序员优雅哥 获取。

JS 模块化-  05 ES Module &amp; 4 大规范总结

源码目录如下:

js-module-demo/ |- 01_Histry/			模块化发展史 |- 02_CommonJS/		CommonJS 规范 |- 03_AMD/				ADM 规范 |- 04_CMD/				CMD 规范 |- 05_ESM/				ESM 规范 

各个模块化规范有相似之处,也有差异,模块定义与模块加载的语法如下:

4.1 Common JS 规范

定义模块的语法:

// 暴露函数 module.exports = function () {}  // 暴露对象 module.exports = {   xxx: () => {} }  exports.xxx = {}  exports.xxx = function() {} 

加载模块的语法:

const xxx = require('xxxx') 

4.2 AMD 规范

定义模块的语法:

define(id?, dependencies?, factory) 

加载模块的语法:

require([module], callback) 

4.3 CMD 规范

定义模块的语法:

// 定义模块 define(function(require, exports, module) { 	 	// 使用 exports 导出模块 	exports.xxx = xxx 	 	//也可以使用 return 导出模块 	// return xxx }) 

加载模块的语法:

// 同步加载模块 const m1 = require('../xxx')  // 异步加载模块 require.async('../xxx', function (m2) { }) 

4.4 ESM 规范

导出模块:

// 按需导出 export const xxx = '' export const xxx = () => {}  // 默认导出 export default xxx 

导入模块:

import { xxx, yyy } from 'xxx' import * as xxx from 'xxx' import xxx from 'xxx' import 'xxx' 

感谢你阅读本文,如果本文给了你一点点帮助或者启发,还请三连支持一下,点赞、关注、收藏,作者会持续与大家分享更多干货

发表评论

相关文章