前端模块化 CommonJS 与 ES Modules

什么是模块化

  • 模块化是一种最主流的代码组织方式,它通过把我们的复杂代码按照功能的不同划分为不同的模块,单独维护的方式去提高开发效率降低维护成本
  • 模块化只是思想

模块化历程

  • CommonJS 规范
    模块化的操作都是同步完成的,不适合在浏览器使用。因为在后端运行js模块化加载都是可以直接在磁盘中读取的,速度一般不会受到影响
  • AMD规范
    异步操作的加载规范,提供了 requiredefault 关键字实现模块化的操作
  • CMD规范
    整合了CommonJSAMD规范的特点专门实现浏览器异步模板化的加载(代表cjs)
  • ES modules 规范
    ES6中将模块化纳入标准规范
  • 当下常用的规范是 CommonJSESM,一个用于node平台下的开发,一个用于浏览器平台下的开发

CommonJS(超集,模块化只是里面的一种)

  • CommonJs可以动态加载语句,代码发生在运行时
  • CommonJs混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了
  • CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
    在这里插入图片描述

导出

module属性

在这里插入图片描述
在这里插入图片描述

1. 模块导出

const a = { name:'cx' }
const b = '字符串'
module.exports = {a, b, c:'c'}

我们可以直接在 exports 对象上添加方法,表示对外输出的接口,如同在module.exports上添加一样

exports.callback = done =>{
	console.log('callback task~')
	done()
}

// module.exports 和 exports. 的形式同时导出时,导入该文件对象为module.exports
// 想要module.exportsexports的形式同时导出可以用以下方式👇

exports = module.exports = {a: 'a', b: 'b', c: 'c'} // 默认导出的必须是一个对象(函数)
exports.callback = done => {}

导出共用

exports.callback2 = exports.callback

导入

require属性

在这里插入图片描述

1. 导入系统模块

const fs = require('fs'); 

2. 导入js文件或第三方库

const my = require('./my.js') 

3. 导入 exports 对象

const callback = require('./a.js') // a 是一个空对象

模块加载速度

  • 核心模块:node源码编译时写入到二进制文件中
  • 文件模块:代码运行时,动态加载

文件定位

在这里插入图片描述

缓存优化原则

在这里插入图片描述

ES Modules

通过给 script 添加 type = “module”,就可以以ES Module的标准执行其中的Js代码

特性

  1. ESM自动采用严格模式,忽略 ‘use strict’(不能在全局范围使用this,为undefined)
  2. 每个ES Module 都是运行在单独的私有作用域中
  3. ESM是通过CORS的方式请求外部JS模块的(src,服务端必须支持cors,cors不支持文件的形式访问)
  4. ESM的script标签会延迟执行脚本(等待渲染完后再执行脚本)

注意

  1. 以下这种方式的导入导出并不是以字面量的形式,是一种固定的语法
    export { name , age }; import { name , age } from ‘./modules.js’
  2. export导出不是把值复制一份给你,而是把存放值的地址给你(拿到的值会受内部值修改的影响)
  3. 在外部导入的成员是一个只读的成员
  4. 导入的成员必须要有完整的文件名称,相对路径中的./不能省略,
    可以使用绝对路径或完整的url( /xx/modules.js 或 http:// )

导出

1. 命名导出

export const a = () => {}

2. 默认导出(每个模块只能有一个,可以是一个对象)

const a  = {
	fn(){},
	b:18
}
export default a

导入

1. 导入多个接口(可用as起别名)

import { xx, xx } form ''

2. 默认导入(可用as起别名)

import xx from ''

导入默认模块重命名

import { default as title } from './modules.js'

只执行模块, 不提取它

import './modules.js'

3.混合导入

 import title { name, age } form './modules.js' // 左边是默认,右边是具名

4. 导入css

import 'xx/xx.css'

5. 导入图片

import img form 'xx/xx.png'
<img :src={img} alt="" />

6. 动态导入

if(true){
	import('./modules.js').then((res)=>{}) // 可不在最顶级的地方导入
}

7.直接导出导入成员

引入导出

export { Button } from './Button.js'
export { Avatar } from './Avatar.js'

引入

import { Button, Avatar } from 'index.js'

CommonJS 与 ES Modules交互

以ES Modules方式运行模块

node --experimental-modules esm.mjs

以ES Modules方式实现CommonJS的 filename 和dirname

import { fileURLToPath } from 'url'
import { dirname} from 'path'
const __filename = fileURLToPath(import.meta.url)
console.log(__filename) // \differences\esm.mjs 当前运行文件的路径
const __dirname = dirname(__filename) 
console.log(__dirname) // \differences 当前项目路径
  • ES Modules可以导入CommonJS模块
  • CommonJS不能导入ES Modules模块
  • CommonJS始终只会导出一个默认成员
  • 注意import不是解构导出对象
  • 在package.json中配置{“type”:“module”},在项目下的所有的文件会以ES Modules的方式工作了,就不需要修改为(mjs)👇

  • 在node12版本中,将文件名修改为.cjs就可以使用CommonJS的规范了

如果你使用的是早期的nodejs版本可以使用Babel做es的兼容

Babel将一些使用了新特性的代码编译成当前环境支持的代码

yarn @babel/node @babel/core @babel/preset-env --dev

preset-env是一个插件的集合

yarn babel-node index.js --presets=@babel/preset-env

可配置在.babelrc

{“presets”:[“@babel/preset-env”]}

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值