当前位置: 首页 > news >正文

一文带你了解,前端模块化那些事儿

文章目录

  • 前端模块化
    • 省流:chatGPT 总结
    • 一、参考资料
    • 二、发展历史
      • 1.无模块化
        • 引出的问题:
        • 横向拓展
      • 2.IIFE
      • 3.Commonjs(cjs)
      • 4.AMD
        • 引出的问题:
      • 5.CMD
      • 6.UMD
      • 7.ESM
    • 往期精彩文章

前端模块化

省流:chatGPT 总结

该文章主要讲述了前端模块化的发展历史和各个阶段的技术方案,包括无模块化(IIFE)、CommonJS、AMD、CMD、ESModule、UMD。

其中,无模块化时期的文件拆分是最基础的模块化,但也存在函数命名冲突的问题;

IIFE 是现代模块化的基石,利用函数的块级作用域进行隔离,可以控制作用域;

CommonJS 文件即模块,模块加载同步,适用于服务器端 node,浏览器端使用 webpack 或 browserfy。

最后,各种模块化技术方案都是为了更好地满足前端代码管理、组织、通信的需求,模块已经成为了代码管理/编译、业务分离的基本单元。

一、参考资料

  • es-module-history
  • 网页性能管理详解
  • defer 和 async 的区别
  • 可能是最详细的 UMD 模块入门指南
  • 在浏览器中使用 ECMAScript Modules

二、发展历史

  • js 的设计之初就是为了满足简单的页面设计+表单提交,并无模块化 or 命名空间的概念
  • 而是实实在在的需求推进了所有技术的演进,模块化也是。
  • 站在前端发展的上帝视角来看,随着前端的能力在纵深都得到增强之后,迫切的需要更好的代码管理、组织、通信的模式,各种模块化的技术方案开始出现。
  • 现如今模块已经成为了代码管理/编译,业务分离的基本单元。

总的发展历史:

  • 无模块化(IIFE) -> CommonJS -> AMD -> CMD -> ESModule、UMD

1.无模块化

需求:

  1. 开始需要在页面中加载不同的 js:动画、组件、格式化
  2. 多种 js 分布在不同的文件中
  3. 不同的文件又被同一个模块中引用

文件拆分是最基础的模块化

<script src='jq.js'></script>
<script src='main.js'></script>
<script src='dep1.js'></script>
// ...

问题:这个时期函数命名可能会冲突,影响到其他人写的代码

引出的问题:

  • script 标签的参数 - async & defer 的区别?

async & defer 的区别

总结:
主要是对标签下载和执行时机的控制

  • 普通标签 - 遇到标签就去下载,下载完毕之后立刻去解析代码并执行,这个时候会阻塞 GUI 线程渲染
  • defer - 遇到标签之后异步下载,下载完成之后等待其他标签解析完成之后开始执行(在主线程解析完成之后才执行,降低脚本的优先级,保持用户体验,使用相对较多)
  • async - 遇到标签之后异步下载,下载完成之后立即执行并阻塞渲染,执行完成之后继续渲染(异步下载结束之后立即执行,不保证脚本执行顺序,一般用来给那些不需要任何依赖的脚本使用)
  • 拓展
  • ESM 默认是通过 defer 的方式加载的,所以是不需要在 script 标签上加 defer 属性的

横向拓展

  1. 兼容性如何? > IE9
  2. 引导内容
    1. 浏览器渲染原理
    2. 同步异步的原理(Promise,任务队列)
    3. 模块化加载原理
  3. 产生的问题
    1. 污染全局作用域 => 不利于大型项目的开发以及多人团队的共建

2.IIFE

IIFE 主要是开始对作用域的把控
利用函数的块级作用域进行隔离
可以说 IIFE 是现代模块化的基石

(function ($) {console.log($);return {data: [],};
})(jQuery); //注入对象

3.Commonjs(cjs)

  • 服务器端 node,浏览器端 webpack|browserfy
  • 文件即模块
    • 模块加载同步
    • 服务器模块加载是运行时同步加载
    • 浏览器模块加载是提前编译打包处理
  • exports = module.exports
    • 注意:不能直接给 exports 赋值,会导致与 module 断开引用
    • 使用 require 进行引入
  • 缓存
    • cjs 在引用文件的时候,会将文件执行一遍,然后将结果通过浅拷贝的方式写入全局缓存中
    • 后续再次 require 同一个文件时,直接从缓存中读取,不会重新执行模块文件
// a.js
var name = 'morrain';
var age = 18;
exports.name = name;
exports.getAge = function () {return age;
};
// b.js
var a = require('a.js');
console.log(a.name); // 'morrain'
a.name = 'rename';
var b = require('a.js');
console.log(b.name); // 'rename'
  • 模块输出的结果是值的拷贝,一但输出,模块内部变化后,无法影响之前的引用,而ESModule 是引用拷贝
// a.js
var name = 'morrain';
var age = 18;
exports.name = name;
exports.age = age;
exports.setAge = function (a) {age = a;
};
// b.js
var a = require('a.js');
console.log(a.age); // 18
a.setAge(19);
console.log(a.age); // 18
  • cjs 在运行时加载,ESM 是编译时加载
  • 缺点:不支持异步
    • cjs 更偏向于服务端,因为服务端 I/O 能力强,所以 CMJ 是同步的方法
    • ESM 时机遇编译时的,所以支持异步能力

4.AMD

AMD(Asynchronous module definition)异步的模块定义
解决了 Commonjs 不支持异步的缺点,可以在浏览器端运行

经典代表:require.js

使用方法:

// define来定义模块
define(id, [depends], callback);
// require进行加载
require([module], callback);

示例:

//提前加载执行顺序
// RequireJS
define('a', function () {console.log('a load');return {run: function () {console.log('a run');},};
});define('b', function () {console.log('b load');return {run: function () {console.log('b run');},};
});require(['a', 'b'], function (a, b) {console.log('main run'); // 🔥a.run();b.run();
});// a load
// b load
// main run
// a run
// b run

缺点:

  • 在代码运行时,会先递归的找出所有的依赖,然后将依赖放到前面加载
  • 如果依赖过多,项目可能会变慢,引入成本升高

引出的问题:

  • 如果现在 AMD 中兼容 CJS 的代码怎么办?
define('amdModule', [], (require) => {const dep1 = require('./dep1');const dep2 = require('./dep2');// 业务逻辑……
});

5.CMD

CMD(Common Module Definition-通用模块定义)推崇依赖后置,也就是按需执行
CMD 解决了 AMD依赖前置导致的引入成本过高的问题
整合了 CJS 和 AMD 的特点,浏览器端运行

经典代表:Sea.js

// 引入require
var fs = require('fs'); //同步
require.async('./module3', function (m3) {}); //异步// sea.js,按需引入
define('a', function (require, exports, module) {console.log('a load');exports.run = function () {console.log('a run');};
});define('b', function (require, exports, module) {console.log('b load');exports.run = function () {console.log('b run');};
});define('main', function (require, exports, module) {console.log('main run');var a = require('a');a.run();var b = require('b');b.run();
});seajs.use('main');// main run
// a load
// a run
// b load
// b run

缺点:

  • 依赖打包,加载逻辑存在于每个模块中
  • 扩大了模块体积,同时功能上依赖编译

6.UMD

UMD (Universal Module Definition)就是一种通用模块定义规范,让你的模块能在所有运行环境中使用,如CommonJS, AMD, CMD

(function (root, factory) {if (typeof module === 'object' && typeof module.exports === 'object') {console.log('是commonjs模块规范,nodejs环境');module.exports = factory();} else if (typeof define === 'function' && define.amd) {console.log('是AMD模块规范,如require.js');define(factory);} else if (typeof define === 'function' && define.cmd) {console.log('是CMD模块规范,如sea.js');define(function (require, exports, module) {module.exports = factory();});} else {console.log('没有模块环境,直接挂载在全局对象上');root.umdModule = factory();}
})(this, function () {return {name: '我是一个umd模块',};
});

7.ESM

ESModule 是伴随着 ES6 推出的原生模块化解决方案
import 输入、export 输出

  • 支持异步加载
  • 编译时加载,支持静态分析
  • 更好的支持chunktree shaking
  • 支持动态导入(按需加载)import().then()
  • 支持import.meta获取模块元数据

往期精彩文章

  • leetcode-js刷题记录&数据结构
  • docker下YApi部署教程-支持swagger数据导入
  • 带你深入理解什么叫js闭包
  • 使用Object.defineProperty进行数据劫持,实现响应式原理-剖析vue2.0
  • 前端性能优化之rel=“prefetch“预/懒加载功能
  • 前端唤起相机的方法H5+JS

相关文章:

一文带你了解,前端模块化那些事儿

文章目录前端模块化省流&#xff1a;chatGPT 总结一、参考资料二、发展历史1.无模块化引出的问题:横向拓展2.IIFE3.Commonjs(cjs)4.AMD引出的问题&#xff1a;5.CMD6.UMD7.ESM往期精彩文章前端模块化 省流&#xff1a;chatGPT 总结 该文章主要讲述了前端模块化的发展历史和各个…...

(六十五)大白话设计索引的时候,我们一般要考虑哪些因素呢?(中)

今天我们继续来说一下&#xff0c;在设计索引的时候要考虑哪些因素。之前已经说了&#xff0c;你设计的索引最好是让你的各个where、order by和group by后面跟的字段都是联合索引的最左侧开始的部分字段&#xff0c;这样他们都能用上索引。 但是在设计索引的时候还得考虑其他的…...

Spring事务管理

文章目录1 事务1.1 需求1.2 原因分析1.3 错误解决1.4 yml配置文件中开启事务管理日志1 事务 1.1 需求 当部门解散了不仅需要把部门信息删除了&#xff0c;还需要把该部门下的员工数据也删除了。可当在删除员工数据出现异常时&#xff0c;就不会执行删除员工操作&#xff0c;出…...

数字化工厂装配线生产管理看板系统

电力企业业务复杂&#xff0c;组织结构复杂&#xff0c;不同的业务数据&#xff0c;管理要求也不尽相同。生产管理看板系统针对制造企业的生产应用而开发&#xff0c;能够帮助企业建立一个规范准确即时的生产数据库。企业现状&#xff1a;1、计划不清晰&#xff1a;生产计划不能…...

vxe-grid 全局自定义filter过滤器,支持字典过滤

一、vxe-table的全局筛选器filters的实现 官网例子&#xff1a;https://vxetable.cn/#/table/renderer/filter 进入之后&#xff1a;我们可以参照例子自行实现&#xff0c;也可以下载它的源码&#xff0c;进行调整 下载好后并解压&#xff0c;用vscode将解压后的文件打开。全局…...

ECharts 环形图组件封装

一、ECharts引入1.安装echarts包npm install echarts --save2.引入echarts这里就演示全局引入了&#xff0c;挂载到vue全局&#xff0c;后面使用时&#xff0c;直接使用 $echartsimport * as echarts from echarts Vue.prototype.$echarts echarts二、写echarts组件这里演示环…...

c++ 怎么调用python 提供的函数接口

在 C 中调用 Python 函数有多种方法&#xff0c;以下是其中的两种常见方法&#xff1a;使用 Python/C APIPython 提供了 C/C API&#xff0c;可以通过该 API 在 C 中调用 Python 函数。使用这种方法&#xff0c;需要先将 Python 解释器嵌入到 C 代码中&#xff0c;然后可以通过…...

【动态规划】背包问题(01背包,完全背包)

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

记录 UE5 完全重新构建 UE C++项目

不知道搞了什么&#xff0c;C项目的实时代码编译罢工了&#xff0c;搞了半天都修不好&#xff0c;只能又重建了 UE5 版本为 v5.1.1 删除以下文件夹 /Binaries /Intermediate /SavedBinaries 文件夹是编译后的模块 Intermediate 文件夹里是中间层的C代码&#xff0c;完全由ue…...

java版云HIS系统源码 微服务架构支持VUE

云his系统源码 一个好的HIS系统&#xff0c;要具有开放性&#xff0c;便于扩展升级&#xff0c;增加新的功能模块&#xff0c;支撑好医院的业务的拓展&#xff0c;而且可以反过来给医院赋能&#xff0c;最终向更多的患者提供更好地服务。 私信了解更多&#xff01; 本套基于…...

苹果内购支付检验错误码

21000 The request to the App Store didn’t use the HTTP POST request method. 对App Store的请求没有使用HTTP POST请求方法。 21001 The App Store no longer sends this status code. App Store不再发送此状态代码。 21002 The data in the receipt-data property…...

day27_css

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、CSS 零、 复习昨日 见代码 一 、引言 1.1CSS概念 ​ 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通…...

智慧赋能,聚力开源——第四届OpenI/O 启智开发者大会开源治理专场顺利举办!

为汇聚国内外知名开源组织共同探讨中国开源生态建设及开源治理相关议题&#xff0c;推进产学研用开源合作&#xff0c;2月24日下午&#xff0c;第四届OpenI/O启智开发者大会在深圳人才研修院智汇中心举办以“构建开源联合体&#xff0c;共建开源生态”为主题的开源治理专场分论…...

Java工程师应该如何成长?

近几年&#xff0c;不少开发者会抱怨“面试造火箭&#xff0c;天天拧螺丝”&#xff0c;每天进行重复业务开发&#xff0c;似乎能力被日常工作限制&#xff0c;无法突破提高。 极客时间《Java 核心技术 36 讲》专栏作者杨晓峰认为&#xff0c;如果处于新手阶段&#xff0c;全面…...

【数据分析师求职面试指南】必备编程技能整理之Hive SQL必备用法

文章目录熟悉Python懂R语言掌握SQL大数据基础数据库常用类型多表查询更多聚合函数distinctcase when窗口函数动态更新一行变多行调优内容整理自《拿下offer 数据分析师求职面试指南》—徐粼著 第四章编程技能考查其他内容&#xff1a;【数据分析师求职面试指南】必备基础知识整…...

Maven - Linux 服务器 Maven 环境安装与测试

目录 一.引言 二.安装流程 1.获取安装包 2.解压并安装 3.配置环境 4.mvn 验证 三.测试踩坑 1.Permission denied 2.Plugin or dependencies Error 一.引言 通道机上的 java 项目需要 mvn package 提示没有 mvn 命令&#xff0c;下面记录下安装 maven 的全过程。 二.安…...

5G模块可以注册到4G,不能注册到5G;SIM卡接到5G手机是可以注册到5G网络的?

5G网络覆盖范围较小或者信号质量不佳。在这种情况下&#xff0c;您可以尝试移动到不同的位置&#xff0c;以获得更好的信号质量和覆盖范围。 目前&#xff0c;5G网络已经在全球多个国家和地区推出&#xff0c;并且在不断扩大覆盖范围。以下是一些已经拥有5G覆盖的主要地区&…...

宝塔webhook自动化打包vue项目时,npm不生效问题

文章目录&#x1f4cb;前言&#x1f3af;查看webhook配置的代码&#x1f3af;测试代码&#xff0c;检查输出内容&#x1f3af;解决方法&#x1f4cb;前言 这篇文章主要是记录和解决在宝塔面板中&#xff0c;webhook自动化打包vue项目时&#xff0c;npm不生效问题。说来奇怪&am…...

嵌入式 Linux进程间通信之信号量

目录 一、信号量 1、信号量概述 2、什么是信号量 3、信号量的分类 4、进程获取共享资源要执行的操作 5、System V IPC 机制&#xff1a;信号量 5.1 semget函数 5.2 semop函数 5.3 semctl函数 一、信号量 1、信号量概述 信号量集&#xff1a;由若干个信号组成的集合&a…...

谷粒学院开发(一):基础准备

商业模式 常见商业模式 B2C模式&#xff1a; 两个角色&#xff1a; 管理员&#xff1a;增加&#xff0c;修改&#xff0c;删除普通用户&#xff1a;查询 商家到用户&#xff0c;自己制作大量自有版权的视频&#xff0c;放在自有平台上&#xff0c;让用户付费。 这是这个项目使…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...