模块化 手写实现webpack

embedded/2024/12/22 14:56:27/

模块化

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_67">手写实现webpack

webpack_68">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__99">手写实现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)

webpack50_211">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 的命令

控制并发请求数量

javascript">// 并发控制: 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.ppmy.cn/embedded/16276.html

相关文章

详解Qt中的鼠标事件

在Qt中&#xff0c;处理鼠标事件是构建交互式界面的关键。Qt提供了一系列与鼠标相关的事件处理函数&#xff0c;允许开发者捕获鼠标的各种动作&#xff0c;如按下、释放、移动、双击等。以下是鼠标事件的使用方法、技巧以及注意事项&#xff0c;并附带C代码示例。 基础使用方法…

揭秘神器:智能私信破局获客难!

在数字营销的海洋中&#xff0c;每个企业都如同一艘努力航行的船&#xff0c;希望能在广阔的客户蓝海中获得丰收。然而&#xff0c;现实却往往充满挑战&#xff0c;尤其是当面对如何吸引并维系客户这一核心难题时。传统的获客手段逐渐显得力不从心&#xff0c;而智能科技的介入…

微信浏览器input[file]拍照点确认后强刷新解决

描述 公众号h5做的点击拍照选择照片&#xff0c;调用相机拍完照点确认时强制回退到登录页面。而且刷新是不固定的&#xff0c;调试了N久&#xff0c;直到现在&#xff0c;还会有这个情况发生。上网查找也没有具体答案。最靠谱的说法就是手机内存不足。 iOS手机经常出现 安卓…

MySQL主从的应用

说明&#xff1a;本文介绍MySQL主从在实际中的应用。主从搭建和问题参考下面两篇文章&#xff1a; MySQL主从结构搭建 搭建MySQL主从结构时的问题 数据迁移 当我们搭建完MySQL主从&#xff0c;第一步当然是把历史数据导入到主从结构中。有以下两种方式&#xff1a; 开启主从…

【注解和反射】通过反射动态创建对象、调用普通方法、操作属性

继上一篇博客【注解和反射】获取类运行时结构-CSDN博客 目录 八、通过反射动态创建对象 测试&#xff1a;通过反射动态创建对象 思考&#xff1a;难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器并将参数传递进去之后&#xff0c;才可以实…

【Qt常用控件】—— QWidget 核心属性

目录 &#xff08;一&#xff09;控件概述 1.1 关于控件体系的发展 &#xff08;二&#xff09;QWidget 核心属性 2.1 核心属性概览 2.2 enabled 2.3 geometry 2.4 windowTitle 2.5 windowIcon 2.6 windowOpacity 2.7 cursor 2.8 font 2.9 toolTip 2.10 focus…

读书笔记|怎样把书读活 ,毛教员的读书方法

哈喽,你好,我是雷工。 我们都希望自己能够把书读活,而不是读死书。 那么如何才能够不读死书,把读到的知识转化为自己的认识呢? 我想毛教员别具一格的读书方法,值得我们反复学习,并加以实践。 01 把读书看做调查研究 我们的知识和认知,大都来自三个方面:亲身经历带来…

Day22 SSH远程管理服务

sshd服务&#xff0c;系统自带&#xff0c;默认开机自启运行 云/物理服务器的安全组和防火墙默认放行该端口 软件包&#xff1a;openssh-server&#xff08;服务端&#xff09;&#xff1b;openssh-client&#xff08;客户端&#xff09;&#xff1b; 格式&#xff1a;ssh I…