聊一聊 CommonJS 和 ES6 Module

1、为什么使用模块化?

模块化是指将一个复杂的系统分解为多个模块以方便编码。其实对于我们现在实际写的前端项目来说,文件即模块,各种模块(文件)构成我们的项目,然后模块之前通过一定的规则互相引用,然后在打包阶段,打包工具比如webpackrollup等会在打包阶段去处理好我们模块的引用关系。

在以前古老的开发模块中,开发网页要通过命令空间 的方式来组织代码,比如著名的 JQuery 库将它所有的 API 都挂到了 window.$下,这样会存在一些问题:

  • 命令空间冲突,两个库可能会使用同一个名称,例如 Zepto
  • 无法合理地管理项目的依赖和版本。
  • 无法方便地控制依赖的加载顺序。

一旦项目过大,这种方式会变得难以维护,所以后面模块化的思想就诞生了。

2、commonjs

2.1 特点

  • 动态引入,执行时引入。
  • 在运行后才可以得知模块导出内容,编译阶段无法做静态分析。
  • 输出的是值的拷贝。

2.2 commonjs 原理

我们先新建一个a.js文件,内容如下:

js 复制代码
// a.js
module.exports = 'a'

在同一个目录下新建一个b.js文件:

js 复制代码
// b.js
const fs = require('fs')
const path = require('path')
function req(targetPath) {
  const absPath = path.resolve(__dirname, targetPath)
  const content = fs.readFileSync(absPath, 'utf8')
  const module = {
    exports: {}
  }
  const fn = new Function('exports', 'module', 'require', '__dirname', '__filename', content + '\r\n return module.exports;')
  return fn.call(module.exports, module.exports, req, __dirname, __filename)
}
console.log(req('./a.js')) // 打印a

核心原理就是利用node原生的fs模块去读取文件,拿到代码字符串,然后通过new Function包装成一个函数去处理,然后通过自己在函数尾部新加的一行return module.exports将执行后的结果抛出。

3、ES Module

  • 静态引入,编译时引入。
  • 只能作为模块顶层的语句出现,不能出现在 function 里面或者是 if 里面。
  • import 的模块名只能是字符串常量。
  • 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。
  • 输出的是值的引用。

4、commonjs 和 es module 使用场景

  • 浏览器端代码 :使用 es2015 module(也就是ES6 Module),模块化使用灵活,且可充分利用tree shaking减少代码体积
  • 服务端 node :适合动态引入,一般不支持 tree-shakinges module,同时也并不需要考虑代码体积,所以使用 commonjs 模块规范,同时也可以拥有更好的 debug 支持,提高开发效率。

tree-shaking:

  • tree-shaking 可以利用 ES2015(es6) 模块语法静态分析的特性,删除没有使用的代码,对代码体积进行优化
  • webpack tree-shaking 启条件:
  • 使用 es2015 模块语法(import和export), require 不行。
  • 配合JS代码压缩插件插件,如 UglifyJSPlugin,TerserPlugin。
  • 去除 babel-loader模 块转换插件,不让 babel-loader 进行模块转换,以保留 export 和 import 关键字,然后让 webpack 来转换 。

小结

目前前端已经是模块化的天下了,学好ES modulecommonjs就已经基本够用了,上面介绍了它们各自的特点和使用场景,希望能帮助到大家去更好的运用它们!

相关推荐
harrain1 小时前
什么!vue3.4开始,v-model不能用在prop上
前端·javascript·vue.js
fanruitian6 小时前
uniapp android开发 测试板本与发行版本
前端·javascript·uni-app
rayufo6 小时前
【工具】列出指定文件夹下所有的目录和文件
开发语言·前端·python
RANCE_atttackkk6 小时前
[Java]实现使用邮箱找回密码的功能
java·开发语言·前端·spring boot·intellij-idea·idea
2501_944525548 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
jin1233228 小时前
React Native鸿蒙跨平台完成剧本杀组队详情页面,可以复用桌游、团建、赛事等各类组队详情页开发
javascript·react native·react.js·ecmascript·harmonyos
李白你好8 小时前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
刘一说9 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
jin12332210 小时前
基于React Native鸿蒙跨平台移动端表单类 CRUD 应用,涵盖地址列表展示、新增/编辑/删除/设为默认等核心操作
react native·react.js·ecmascript·harmonyos
徐同保10 小时前
React useRef 完全指南:在异步回调中访问最新的 props/state引言
前端·javascript·react.js