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

news2024/9/28 11:18:02

文章目录

  • 前端模块化
    • 省流: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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

css伪类和伪元素的区别

文章目录什么是css伪类和伪元素css伪类和伪元素有什么用&#xff1f;css伪类的具体使用常见的伪类伪元素的具体使用常见的伪元素什么是css伪类和伪元素 伪类和为元素是两个完全不同且重要的概念&#xff0c;它们的作用是给元素添加一些特殊的效果或样式 伪类用于选择某个元素的…

Kalman Filter in SLAM (6) ——Error-state Kalman Filter (EsKF, 误差状态卡尔曼滤波)

文章目录0.前言1. IMU的误差状态空间方程2. 误差状态观测方程3. 误差状态卡尔曼滤波4. 误差状态卡尔曼滤波方程细节问题0.前言 这里先说一句&#xff1a;什么误差状态卡尔曼&#xff1f;完全就是在扯淡&#xff01; 回想上面我们推导的IMU的误差状态空间方程&#xff0c;其实…

乐山持点科技:抖客推广准入及准出管理规则

抖音小店平台新增《抖客推广准入及准出管理规则》&#xff0c;本次抖音规则具体如下&#xff1a;第一章 概述1.1 目的及依据为维护精选联盟平台经营秩序&#xff0c;保障精选联盟抖客、商家、消费者等各方的合法权益;根据《巨量百应平台服务协议》、《“精选联盟”服务协议(推广…

【GNN/深度学习】常用的图数据集(资源包)

【GNN/深度学习】常用的图数据集&#xff08;图结构&#xff09; 文章目录【GNN/深度学习】常用的图数据集&#xff08;图结构&#xff09;1. 介绍2. 图数据集2.1 Cora2.2 Citeseer2.3 Pubmed2.4 DBLP2.5 ACM2.6 AMAP & AMAC2.7 WIKI2.8 COCS2.9 BAT2.10 EAT2.11 UAT2.12 C…

第十三届蓝桥杯省赛Python大学B组复盘

目录 一、试题B&#xff1a;寻找整数 1、题目描述 2、我的想法 3、官方题解 4、另解 二、试题E&#xff1a;蜂巢 1、题目描述 2、我的想法 3、官方题解 三、试题F&#xff1a;消除游戏 1、题目描述 2、我的想法&#xff08;AC掉58.3%&#xff0c;剩下全超时&#x…

Substrate 基础教程(Tutorials) -- 监控节点指标

Substrate 公开有关网络操作的度量。例如&#xff0c;您可以收集有关您的节点连接了多少个对等节点、您的节点使用了多少内存以及正在生成的块数量的信息。为了捕获和可视化Substrate节点公开的度量&#xff0c;您可以配置和使用Prometheus和Grafana等工具。本教程演示如何使用…

C++学习笔记(以供复习查阅)

视频链接 代码讲义 提取密码: 62bb 文章目录1、C基础1.1 C初识&#xff08;1&#xff09; 第一个C程序&#xff08;2&#xff09;注释&#xff08;3&#xff09;变量&#xff08;4&#xff09;常量&#xff08;5&#xff09;关键字&#xff08;6&#xff09;标识符命名规则1.2 …

mysql 导入超大sql文件

mysql -u root -p 登录mysql命令 可以登陆mysql服务器使用source命令导入&#xff0c;会快很多&#xff0c;我这里导入500M&#xff0c;大概用了5分钟。 1. liunx登陆mysql mysql -u 用户名 -p 数据库名 然后输入密码 登陆mysql控制台后&#xff0c;执行source命令&#xf…

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

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

BatchNorm1d的复现以及对参数num_features的理解

0. Intro 以pytorch为例&#xff0c;BatchNorm1d的参数num_features涉及了对什么数据进行处理&#xff0c;但是我总是记不住&#xff0c;写个blog帮助自己理解QAQ 1. 复现nn.BatchNorm1d(num_features1) 假设有一个input tensor&#xff1a; input torch.tensor([[[1.,2.,…

Plsql使用

登录登录system用户&#xff0c;初始有两个用户sys和system&#xff0c;密码是自己安装oracle数据库时写的&#xff0c;数据库选择orcl创建用户点击user,右键新增填写权限关于3个基本去权限介绍&#xff1a; connect : 基本操作表的权限&#xff0c;比如增删改查、视图创建等 r…

Netty channelHandler注意事項——super.channelRead(ctx, msg)

通过nioSocketChannel.pipeline()的addLast添加入站处理器&#xff0c;如果有多个必须显示的唤醒下一个入站处理器&#xff0c;否则执行链中间会断掉。 protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {log.debug(nioSocketChannel.toStrin…

前端优化,webpack打包删除无用文件,并附上批量删除文件脚本!非常好用

前言 大家可能在webpack打包项目过程中&#xff0c;常遇见一些无用的图片&#xff0c;js文件&#xff0c;怎样能够自动检测哪些是无用的文件呢&#xff1f;本文中介绍使用插件useless-files-webpack-plugin查找无用文件&#xff0c;在terminal中删除&#xff0c;附加bat批量删…

Ngnix安装教程(2023.3.8)

Nginx安装教程&#xff08;2023.3.8&#xff09;引言1、Nginx简介2、Nginx安装2.1 下载Nginx安装包2.2 免安装启动Nginx&#xff08;切记解压后将nginx-1.23.3文件夹需要放在英文路径下&#xff0c;实测中文路径不识别且启动不成功&#xff09;2.3 熟悉Nginx文件夹目录结构2.4 …

平安银行LAMBDA实验室负责人崔孝林:提早拿到下一个计算时代入场券

量子前哨重磅推出独家专题《“量子”百人科学家》&#xff0c;我们将遍访全球探索赋能“量子”场景应用的百位优秀科学专家&#xff0c;从商业视角了解当下各行业领域的“量子”最新研究成果&#xff0c;多角度、多维度、多层面讲述该领域的探索历程&#xff0c;为读者解析商业…

Python - Pandas - 数据分析(2)

Pandas数据分析2前言常用的21种统计方法describe()&#xff1a;numeric_only&#xff1a;偏度skewness&#xff1a;功能&#xff1a;含义&#xff1a;计算公式&#xff1a;演示&#xff1a;峰度值&#xff1a;用途&#xff1a;数值&#xff1a;计算公式&#xff1a;演示&#x…

[Java·算法·中等]LeetCode34. 在排序数组中查找元素的第一个和最后一个位置

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1&#x1f449;️ 力扣原文 题目 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1,…

Windows 安装 MongoDB 并内网穿透远程连接

本文目录1.前言2.MongoDB数据库的安装2.1 MongoDB下载安装2.2 MongoDB连接测试2.3 cpolar下载安装3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置4.公网访问测试5.结语1.前言 现代电子技术日新月异&#xff0c;并且快速应用到我们的生活中&#xff0c;与之相应的&…

SAP BTEs的简介及实现

一、认识BTE BTE&#xff08;Business Transaction Event&#xff09;也称之为“业务交易事件”,一般的增强(Tcode:SMOD|CMOD)依旧使用ABAP进行二次开发,然而BTE则提供了RFC调用其它产品的可能(Tcode:FIBF)。BTE的设计思路更加简单&#xff0c;和BADI有点类似。在标准程序中留有…

ssm框架之spring:浅聊IOC

IOC 前面体验了spring&#xff0c;不过其运用了IOC&#xff0c;至于IOC( Inverse Of Controll—控制反转 ) 看一下百度百科解释&#xff1a; 控制反转&#xff08;Inversion of Control&#xff0c;缩写为IoC&#xff09;&#xff0c;是面向对象编程中的一种设计原则&#x…