前端模块化CommonJs、ESM、AMD总结

前端开发模式进化史

前端工程化正是为了应对这些演化中出现的挑战和需求而发展起来的:

  1. 前后端混合:服务端渲染,javascript仅实现交互
  2. 前后端分离:借助 ajax 实现前后端分离、单页应用(SPA)等新模式
  3. 模块化开发:npm 管理模块、Webpack 编译打包资源
  4. 模块化 + MVVM:基于 React 或 Vue 等框架进行组件化开发,不再手动操作 html 元素

模块化思想

模块化就是把逻辑代码拆分成独立的块,各自封装、互相独立,每个块自行决定对外暴露什么,同时自行决定引入执行哪些外部代码。前端工程化工具和模块化开发使前端项目更易于管理,避免依赖混乱,促进代码的重用和维护
前端模块化是前端工程化的一个重要组成部分,前者关注代码的组织和结构,而后者关注整个前端开发过程的自动化和最佳实践。前端工程化借助前端模块化来提高代码的组织和可维护性,从而解决前端开发中的一系列问题。

CommonJs

Node.js 实现了 CommonJS 规范,如果前端要使用,需要用browserify库 来进行转化。

//a.js 导出
module.exports = {
  name: 'ysl',
  age: '27'
}
//导入
let obj = require('./a.js')
console.log(obj)

或者

//a.js
export.name = 'ysl'
export.age = 27

注意:

  1. require第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。需要清除缓存delete require.cache[require.resolve('./a.js')]再引入。
  2. 引入时拷贝机制,引入输出之后,模块内部的变化影响不了原本已经引入的值。
  3. CommonJs加载是同步加载,如果在浏览器中某个模块加载时间太长,容易出现卡死现象。

AMD

AMD采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行

// moduleA.js
  define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });
// index.js
  require(['moduleA'], function (moduleA){
    console.log(moduleA)
       //moduleA就是moduleA.js模块传入的函数执行后返回的对象{add:function}
 });

UMD

通过对 CommonJs、CMD、AMD 进一步处理,它没有自己专有的规范,是集结了 CommonJs、CMD、AMD 的规范于一身。
它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。
未来同一个 JavaScript 包运行在浏览器端、服务区端都只需要遵守同一个写法就行了。

// UMD简单实现
((global, factory) => {
    //如果 当前的上下文有define函数,并且AMD  说明处于AMD 环境下
    if (typeof define === 'function' && define.amd) {
        define(["moduleA"], factory);
    }
    else if (typeof exports === 'object') {//commonjs
        let moduleA = require("moduleA")
        modules.exports = factory(moduleA)
    }
    else {
        global.moduleA = factory(global.moduleA) //直接挂载成 windows 全局变量 
    }
})(this, (moduleA) => {
    //本模块的定义
    return {
    }
})

ESM(ECMAScript Moudules)

历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。
es6模块的语法分为两部分:export 模块导出、 import模块导入

//export 导出
// profile.js 
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
//import 引入
// main.js 
import { firstName, lastName, year } from './profile.js';
function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

//或者用*指定一个对象
// main.js 
import * as total from './profile.js';
function setName(element) {
  element.textContent = total.firstName + ' ' + total.lastName;
}

用到export default命令,为模块指定默认输出。一个模块只能有一个默认输出,因此export default命令只能使用一次。

// profile.js 
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export default { firstName, lastName, year };

// main.js 
import total from './profile.js';
function setName(element) {
  element.textContent = total.firstName + ' ' + total.lastName;
}

注意:
export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

CommonsJs与ES6之间的差别

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • CommonJS 模块的require()同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。

node和浏览器分别加载es6与commonJs的方式

node加载es6模块的方式

1、 ES6 模块采用.mjs后缀文件名。
2、 项目的package.json文件中,指定type字段为module

(注意:如果没有type字段,或者type字段为commonjs,则.js脚本会被解释成 CommonJS 模块。)

总结为一句话:.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。

node默认采用commonJs模块模块的方式
// a.js
module.exports = {name:'ysl}
// main.js
let obj = require('./a.js')
// node环境可以直接使用
浏览器加载es6模块方式

浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。

<script type\="module" src\="./foo.js"\></script\>
// 浏览器对于带有\`type="module"\`的\`<script\>\`,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了\`<script\>\`标签的\`defer\`属性。
<script type\="module" src\="./foo.js" defer\></script\>
// 效果一致

通过<script>标签加载,可能会出现跨域的现象,可以使用express解决

浏览器加载CommonJs

浏览器直接加载CommonJs会报错,因为浏览器不存在module、exports、require这些环境变量,可以使用Browserify,对模块进行转换

参考
https://segmentfault.com/a/1190000039346572?sort=newest
https://juejin.cn/post/7291186181157535800

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886975.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot投稿和稿件处理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据量&#xff1a;3k 想要进一步了解&#xff0c;请联系。 DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种…

订阅ROS2中相机的相关话题并保存RGB、深度和点云图

系统&#xff1a;Ubuntu22.04 ROS2版本&#xff1a;ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…

建筑资质的未来发展趋势

&#x1f3d7;️建筑资质是建筑企业进入市场的通行证&#xff0c;它不仅关系到企业的竞争力&#xff0c;也影响着整个建筑行业的健康发展。随着政策的调整和技术的进步&#xff0c;建筑资质管理正面临着新的变革。 1. 资质管理的数字化转型&#xff1a;&#x1f310; 随着信息技…

Gaussian-splatting 项目环境配置笔记(Win11)

如果你是配置别的项目的过程中用到了3D GS相关的内容&#xff0c;然后这部分内容环境一直配不好&#xff0c;也可以跟随这个博客配一下环境&#xff0c;配完后起码3D GS部分就搞定了。 文章目录 概述项目链接&#xff1a;VS2019直接下载链接CUDA不同版本下载链接安装Condasetup…

63.5 注意力提示_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录注意力提示生物学中的注意力提示查询、键和值注意力的可视化使用 show_heatmaps 显示注意力权重代码示例 代码解析结果 小结练习 注意力提示 &#x1f3f7;sec_attention-cues 感谢读者对本书的关注&#xff0c;因为读者的注意力是一种稀缺…

【MATLAB2024b】安装离线帮助文档(windows)

文章目录 一、在 MATLAB 设置中安装二、从math works 网站下载ISO&#xff1a;给无法联网的电脑安装三、重要说明 版本&#xff1a;matlab 2024b&#xff08;或者大于等于2023a&#xff09; 所需空间&#xff1a;10~15 GB 平台&#xff1a;Windows 需要注册math works账号。 一…

深度学习-19-深入理解并训练自己的Tokenizer分词器

文章目录 1 tokenization是什么2 Tokenization方法简介2.1 单词级的Tokenization2.2 子词Tokenization技术2.3 举例说明2.3.1 字符级别2.3.2 词语级别2.3.3 子词级别3 训练自己的Tokenizer3.1 下载数据集3.2 huggingface的Tokenizer实现3.3 my-tokenizer.json字段说明3.4 验证一…

鸿蒙harmonyos next flutter混合开发之开发package

​​​​​​ 创建 package flutter create --templatepackage mypackage package代码如下&#xff1a; 创建hello_world.dart ///HelloWorld返回hello world 拼接param class HelloWorld {String helloWorld(String param) > "hello world ${param}"…

【视频目标分割-2024CVPR】Putting the Object Back into Video Object Segmentation

Cutie 系列文章目录1 摘要2 引言2.1背景和难点2.2 解决方案2.3 成果 3 相关方法3.1 基于记忆的VOS3.2对象级推理3.3 自动视频分割 4 工作方法4.1 overview4.2 对象变换器4.2.1 overview4.2.2 Foreground-Background Masked Attention4.2.3 Positional Embeddings 4.3 Object Me…

CSS实现服务卡片

CSS实现服务卡片 效果展示 CSS 知识点 回顾整体CSS知识点灵活运用CSS知识点 页面整体布局 <div class"container"><div class"card"><div class"box"><div class"icon"><ion-icon name"color-pal…

Mac 卸载 IDEA 流程

1、现在应用程序中删除Idea 2、进入Library目录 cd /Users/zhengzhaoxiang/Library 3、删除IntelliJIdea2023.3&#xff08;根据自己的版本而定&#xff09;记得进去看下是否删除干净了 rm -rf Logs/JetBrains/IntelliJIdea2023.3 rm -rf Preferences/com.jetbrains.intel…

蘑菇分类检测数据集 21类蘑菇 8800张 带标注 voc yolo

蘑菇分类检测数据集 21类蘑菇 8800张 带标注 v 蘑菇分类检测数据集 21类蘑菇 8800张 带标注 voc yolo 蘑菇分类检测数据集介绍 数据集名称 蘑菇分类检测数据集 (Mushroom Classification and Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型…

python爬虫 - 初识爬虫

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、爬虫的关键概念 &#xff08;一&#xff09;HTTP请求与响应 &#xff0…

uni-app在线预览pdf

这里推荐下载pdf.js 插件 PDF.js - Browse Files at SourceForge.net 特此注意 如果报 Promise.withResolvers is not a function 请去查看版本兼容问题 降低pdf.js版本提高node版本 下载完成后 在 static 文件夹下新建 pdf 文件夹&#xff0c;将解压文件放进 pdf 文件…

基于SpringBoot+Vue的摄影社团管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

API接口开发系列文章:构建高效、安全与可扩展的API服务

前言 在当今的数字化时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为连接不同系统、服务和应用的核心桥梁。无论是企业内部的数据交互&#xff0c;还是面向第三方的服务开放&#xff0c;API都扮演着至关重要的角色。本系列文章将深入探讨API接口开发的各个…

【nlp自然语言】知识图谱,全文检索,自然语言nlp,数据资产标签,集成管理平台

一、项目介绍 一款全源码&#xff0c;可二开&#xff0c;可基于云部署、私有部署的企业级知识库云平台&#xff0c;一款让企业知识变为实打实的数字财富的系统&#xff0c;应用在需要进行文档整理、分类、归集、检索、分析的场景。 为什么建立知识库平台&#xff1f; 助力企业…

雷池 WAF 如何配置才能正确获取到源 IP

经常有大哥反馈说雷池攻击日志里显示的 IP 有问题。 这里我来讲一下为什么一些情况下雷池显示的攻击 IP 会有问题。 问题说明 默认情况下&#xff0c;雷池会通过 HTTP 连接的 Socket 套接字读取客户端 IP。在雷池作为最外层网管设备的时候这没有问题&#xff0c;雷池获取到的…

【Linux】进程地址空间(初步了解)

文章目录 1. 奇怪的现象2. 虚拟地址空间3. 关于页表4. 为什么要有虚拟地址 1. 奇怪的现象 我们先看一个现象&#xff1a; 为什么父子进程从“同一块地址中”读取到的值不一样呢&#xff1f; 因为这个地址不是物理内存的地址 &#xff0c;如果是物理内存的地址是绝对不可能出…