模块化 手写实现webpack

news/2024/5/19 6:45:25

模块化

common.js 的导入导出方法: require \ export 和 module.exports
export 和 module.export
nodejs 内存1.4G -> 2.8G

cjs

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

ESModule

主要区别: require属于动态类型:加载执行 同步
esmodul是静态类型:引入时并不会真的去执行文件 而是先分析依赖关系 再再实例化 最后执行 异步
import 是promise的语法糖 沙箱机制
外链 软链 link
在这里插入图片描述
在这里插入图片描述
python php 解释型语言
js 编译型语言

前端三件事:

  1. 设计:
    webpack的设计:
    文件加载:
    1)从什么地方加载,入口文件,以参数形式写入 ’./index.js‘
    2) 文件加载方法名:getFileInfo(file) - file 文件路径 index.js
    分析方法名 parseFile(Filecontent) - Filecontent 文件内容
    加载完成文件,文件上下文,require,import, 写入dist、bundle.js
    3) 收集依赖
    npm install @babel/traverse
    4)收集完依赖,加载所有⽂件
    内部的文件加载情况,依赖关系
    根据依赖关系加载文件
    - parseModules⽅法:
    - 1. 我们⾸先传⼊主模块路径
    - 2. 将获得的模块信息放到temp数组⾥。
    - 3. 外⾯的循坏遍历temp数组,此时的temp数组只有主模块
    - 4. 循环⾥⾯再获得主模块的依赖deps
    - 5. 遍历deps,通过调⽤getModuleInfo将获得的依赖模块信息push到 temp数组⾥。`
    5) 使得引⼊的代码可以被执⾏最终需要处理require和exports
  2. 注释
  3. 测试

npm init 初始化项目得到package.json 和 package-lock.json文件
npm install 安装依赖
npm install @babel/parser 安装解析器babel
npm install @babel/traverse 收集完依赖,怎么加载所有⽂件
@babel/preset-env es6的代码转成es5的(import es7的语法 浏览器不认识 转成es5)
在这里插入图片描述

引⼊的代码可以被执⾏最终需要处理require和exports

babel里的每个stage代表什么内容: 核心原理是什么
能转义和兼容的范围
低阶段兼容范围更广
高阶段能兼容最新的语法
低阶段包含高阶段

use strict: 严格模式
作用:避免js灵活性造成的问题
用法:文件开头标识 use strict
不能干的事:严格使用js的语法

  1. 全局this
  2. 变量重复定义:为了避免掉js的灵活性造成的问题 避免歧义
  3. eval函数 string变成函数去执行的情况
    在这里插入图片描述

webpack 原生加载器能加载哪些文件: js 和 json
webpack不具备这些功能 通过插件完成

手写实现webpack

webpack的核心概念

1. sourcemap 
2. 文件指纹技术
3. babel 与 AST
4. TreeShaking 
5. 优化- 构建速度- 提高页面性能
6. 原理- webpack- plugin- loader
7. 核心配置- entry: 编译入口,webpack编译的起点- Compiler: 编译管理器, webpack启动后会创建compiler对象,知道结束退出- compilation: 单次编辑过程的管理器 - dependence: 依赖对象 webpack基于该类型记录模块间依赖关系 - Module: 内部资源都以module形式存在 所有关于资源的操作,转译,合并都是以module为单位进行的- Chunk:百年已完成准备输出是 webpack会将module按照特定的规则组织称一个个chunk 跟最终输出一一对应 - Loader: 资源内容转换器 - Plugin: webpack构建过程中,会在特定的时机⼴播对应的事件,插件监听这些事件,在特定时间点介⼊编译过程

在这里插入图片描述
在代码里debug
在这里插入图片描述
vscode里debug

  1. 执行完 按语句执行 单步调试:进入到语句里去 单步跳出 刷新 暂停
  2. 代码里写 debugger然后启动
    在这里插入图片描述

手写实现webpack 理解原理完整代码

//  src下创建 add.js⽂件和minus.js⽂件, 在index.js中引⼊,再将index.js⽂件引⼊index.html
// add.js
export default ( a, b ) => {return a + b
}
// minus.js
export const minus = ( a, b ) => {return a - b
}
// index.js
import add from './add.js'
import { minus } from './minus.js'
// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><script src="./src/index.js" type="module"></script>
</body>
</html>// 创建bundle.js文件
// 获取主入口文件
// 解决内部文件循环引用的问题  npm install @babel/parser 解析器
// 收集依赖
// 根据收集的依赖关系 加载所有文件
// 执行加载的文件:浏览器处理不了es67的语法 require、import需要被处理const fs = require('fs')
const path = require('path')
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const babel = require('@babel/core')
const getmoduleInfo = (file) => {// 读取文件const body = fs.readFileSync(file, 'UTF-8')const ast = parsesr.parse(body, {sourceType: 'module' // 表示我们要解析的是ES模块})const deps = {} // traverse(ast, {// 处理路径ImportDeclaration({node}){const dirname = path.dirname(file)const abspath = "./" + path.join(dirname, node.source.value)}})// 转成ast树const { code } = babel.transformFromAst(ast, null,{presets: ["@babel/preset-env"]})const moduleInfo = { file, deps, code}return moduleInfo
}// 解析模块
const parseModules = (file) => {// 入口文件const entry = getModuleInfo(file)const temp = [entry]const depsGraph = {}for(let i=0;i<temp.length;i++>){const deps = temp[i].depsif(deps){for(const key in deps){if(deps.hasOwnProperty(key)){temp.push(getModuleInfo(deps[key]))}}}}temp.forEach(moduleInfo => {depsGraph[moduleInfo.file] = {deps: moduleInfo.deps,code: moduleInfo.code,}})
}// 生成最终bundle文件
const bundle = (file) => {const depswGraph = JSON.stringify(parseModules(file))return `(function(graph){function require(file) {function absRequire(relPath){return require(graph[file].deps[realPath])}var exports = {}(function (require,exports,code){eval(code)})(absRequire, exportsgraph[file].code)return exports}require('$file')})($depsGraph)`
}const content = bundle('./src/index.js')
// 写入到dist目录下
fs.mkdirSync('./dist')
fs.writeFileSync('./dist/bundle.js',content)

webpack5.0优化

  1. 增加持久化存储能力,提升构建性能(核心)
  2. 提升算法能力来改进长期缓存(降低产物缓存资源的失效率)
  3. 提升treeshaking的能力未降低产物大小和代码生成逻辑
  4. 提升web平台的兼容性能力
  5. 清除了内部结构中在webpack4没有重大更新二引入的一些新特性时留下来的一些奇怪的state
  6. 引入一些重大的变更为未来的一些特性做准备,使得能长期稳定在webpack版本上
    在这里插入图片描述
    如何优化
    在这里插入图片描述

vite

rollup: 编译工具
esbuilder:go语言
为什么vite在开发时用 esbuild, 生产环境用打包 rollup

  1. esbuild不支持es5 不会降级
  2. 不支持render
  3. 不支持split chunk
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以把一些包放到npm上
    CICD: shell 的命令

控制并发请求数量

// 并发控制: 10条数据 控制请求的数量不大于三条 request(url, maxNum){return new Promise(resolve,reject=>{if(urls.length){resolve([])return}const result= []let index = 0 // 下一个请求的下标let count = 0 // 当前请求完成的数量// 发送请求async function request(){if(index === urls.length){// 当前下标等于最后一个 结束return }const i = index // 保存序号 使result和urls对应const url = urls[index]index ++ console.log(url)try {const resp = await fetch(url)result[i]=resp} catch (err){result[i] = err} finally {// 判断所有请求是否都完成了if(count === urls.length) {resolve(result)}request()}}// maxNum 和 urls。length去最小进行调用const times = Math.min(maxNum, urls.length)for(let i=0;i<times.length;i++){request()}})},requestSum(){}},

http://www.mrgr.cn/p/03675640

相关文章

ArcGIS无法开始编辑TIN!开始编辑TIN显示灰色

ArcGIS无法开始编辑TIN&#xff01;开始编辑TIN显示灰色&#xff1f; 解决方案&#xff01; 1、确认自定义——扩展模块中空间分析、3D分析模块勾选。 2、确认以上后&#xff0c;还是不能编辑的话&#xff0c;我们可以调出 3D分析分析工具条&#xff0c;你就会发现。TIN编辑工…

# 从浅入深 学习 SpringCloud 微服务架构(二)模拟微服务环境(1)

从浅入深 学习 SpringCloud 微服务架构&#xff08;二&#xff09;模拟微服务环境&#xff08;1&#xff09; 段子手168 1、打开 idea 创建父工程 创建 artifactId 名为 spring_cloud_demo 的 maven 工程。 --> idea --> File --> New --> Project --> Ma…

Unlink原理和一些手法

Unlink原理和一些手法 ✅简单介绍一下unlink相关的知识 unlink是利用glibc malloc 的内存回收机制造成攻击的,核心就在于当两个free的堆块在物理上相邻时,会将他们合并,并将原来free的堆块在原来的链表中解链,加入新的链表中其目的是把一个双向链表中的空闲块拿出来(例如 …

【vue3入门】-【4】插入html

原始html 双大括号,将会将数据插值为纯文本,而不是html,若想要插入html,则需要使用v-html指令 <template><h3>模版语法</h3><p>{{ tthtml }}</p> <!--会直接将html文本展示出来-->><p v-html="tthtml"></p> …

vue中函数使用、class和style属性、条件渲染、列表渲染、数据的双向绑定、input事件、过滤

【事件指令中的函数使用】1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8">5 <title>Title</title>6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">…

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…

边权并查集之奇偶游戏

题目传送门:https://www.acwing.com/problem/content/241/ //懒得手敲题目先给一下题解: #include<iostream> #include<unordered_map> //这个题目有两个点要想明白,一个是点到根的距离标志着这个点的性质,且在路径压缩的过程中此点不会改变 //第二点就是在出现…

【vue3入门】-【2】文本插值

文本插值 最基本的数据绑定形式是文本插值,它使用的是”Mustache“语法(即双大括号) <script> export default{data(){return{msg:"神奇的语法"}} } //以上为文本插值的固定使用格式 </script><template><h3>模版语法</h3><p>…

Redis 面试知识点

1、Redis缓存数据库一致性采用最终一致性,而不是采用强一致性,强一致性会导致系统吞吐量变差;采用双删除的策略,第二次删除,采用延迟删除;推荐采用,先操作数据库,直接删除缓存的方式;删除失败的情况,采用异步方式,重试操作;读取binlog异步删除,使用开源框架canal,…

tcp inflight 守恒算法的几何解释

接上文&#xff1a;tcp inflight 守恒算法背后的哲学 在 tcp inflight 守恒算法正确性 中&#xff0c;E bw / srtt 的公平最优解是算出来的&#xff0c;如果自然可以用数学描述&#xff0c;那能算出来的东西反过来也一定能通过直感看出来&#xff0c;我倾向于用几何和力学描述…

【vue3入门】-【1】Vue介绍与项目结构

Vue是什么? 渐进式javaScript框架,易学易用,性能出色,适用场景丰富的web框架官方文档 地址:https://cn.vuejs.orgVue简介 是渐进式javascript框架,易学易用,性能出色,适用场景丰富的web前端框架 Vue是一款用于构建用户节点的javascript框架。它基于标准html、css、java…

鸿蒙HarmonyOS实战-ArkUI事件(触屏事件)

🚀前言 触屏事件是指通过触摸屏幕来进行操作和交互的事件。常见的触屏事件包括点击(tap)、双击(double tap)、长按(long press)、滑动(swipe)、拖动(drag)等。触屏事件通常用于移动设备和平板电脑等具有触摸屏幕的设备上,用户可以通过触摸屏幕上的不同区域或者以不…

vue快速入门(四十四)自定义组件

注释很详细&#xff0c;直接上代码 上一篇 新增内容 全局注册自定义组件并应用局部注册自定义组件并应用 此篇使用了axios模块没有安装导入的先看这一篇 axios模块下载与导入 源码 main.js import Vue from vue import App from ./App.vue//全局引入axios // 引入axios impor…

FLINKCDC 3.0整库同步MYSQL至DORIS(FLINK1.18): 历程

大数据技术涉及组件较多,各个环境较DEMO又不尽相同,所以参照DEMO进行,任然很多报错信息出现。 如下报错处理,尽供参考: 1.创建同步配置文件 ################################################################################ Description: Sync MySQL all tables to Do…

Jira搭建过程

看到很多小伙伴对jira有兴趣,我们今天就来分享一下jira的搭建吧 首先要明白jira是什么? 看来搭建jira也是我们测试人员需要具备的技能之一了.下面是详细的大家步骤: 1.系统环境准备 Centos 7.5 Mysql 5.6 Java1.8 2.软件安装包 atlassian-jira-software-7.13.0-x64.bin …

万字长文总结与剖析C语言关键字 -- C语言深度解剖

总结与剖析C语言关键字的功能与原理、ANSI C,GNU C、跨平台、多学科角度C总结与剖析:关键字篇 -- <<C语言深度解剖>> 目录C总结与剖析:关键字篇 -- <<C语言深度解剖>>程序的本质:二进制文件变量1.变量:内存上的某个位置开辟的空间2.变量的初始化3.为什…

TCP/IP协议—MQTT

TCP/IP协议—MQTT MQTT协议MQTT协议特点MQTT通信流程MQTT协议概念 MQTT报文固定报头可变报头有效载荷 MQTT协议 消息队列遥测传输&#xff08;Message Queuing Telemetry Transport&#xff0c;MQTT&#xff09;是一个基于客户端-服务器的消息发布/订阅传输协议。它的设计思想…

容器使用之`Array`

容器使用之Array 使用c++当中容器都被定义在以容器为名的头文件当中使用时需要引入头文件关键点:因为容器都有一个适配器去分配内存.所以声明array的时候要告诉编译器array放置的数据类型array的大小示例代码: #pragma#ifndef __ARRAY__#define __ARRAY__​#include <array&…

玩转枚举Enum

背景介绍 为什么要使用枚举呢&#xff0c;我将通过枚举模拟一些使用场景来说明&#xff1a; 枚举类也是一个普通类&#xff0c;可以定义一些变量、常量&#xff0c;同样可以定义构造方法可以实现接口&#xff0c;可以以main函数作为测试类等等&#xff0c;但是它不能继承一个类…