赞
踩
git rebase
和 git merge
都是用于合并分支的 Git
命令,这两个命令都能将一个分支合并到另一个分支,但两者合并方式有很大不同
merge commit
,将两个分支的历史合并在一起,这个merge commit
会在分支历史中保留,可以清晰的看到那些分支合并到了柱分枝,合并后形成分叉结构。 commit
记录,然后提取之后所有的commit
,然后将这个commit
记录添加到另一个分支的最前面,两个分支合并后的commit
记录就变成线性记录 image-loader
: 加载并且压缩图片文件css-loader
: 加载 CSS
,支持模块化、压缩、文件导入等特性style-loader
: 把 CSS
代码注入到 JavaScript
中,通过 DOM
操作去加载 CSS
eslint-loader
: 通过 ESLint
检查 JavaScript
代码tslint-loader
: 通过 TSLint
检查 TypeScript
代码babel-loader
: 把 ES6
转换成 ES5
define-plugin
: 定义环境变量html-webpack-plugin
: 简化 HTML
文件创建webpack-parallel-uglify-plugin
: 多进程执行代码压缩,提升构建速度webpack-bundle-analyzer
: 可视化 Webpack
输出文件的体积speed-measure-webpack-plugin
: 可以看到每个 Loader
和 Plugin
执行耗时 (整个打包耗时、每个 Plugin
和 Loader
耗时)mini-css-extract-plugin
: 分离样式文件,CSS
提取为独立文件,支持按需加载功能不同:
webpack
只能解析原生js
文件,对于其他类型文件就需要用loader
进行转换。webpack
功能。webpack
在运行的生命周期中会广播出许多事件,Plugin
可以监听这些事件,在合适的时机通过 webpack
提供的 API 改变输出结果
。用法不同:
module.rules
下进行。类型为数组,每⼀项都是⼀个 Object
,⾥⾯描述了对于什么类型的⽂件( test
),使⽤什么加载( loader
)和使⽤的参数( options
)plugins
下。类型为数组,每一项是一个 Plugin
的实例,参数都通过构造函数传入。Compiler
对象,加载所有配置的插件,执行run方法。entry
参数找到入口文件Loader
对模块进⾏翻译,再找出该模块依赖的模块,再递归本步骤直到所有⼊⼝依赖的⽂件都经过了本步骤的处理;Loader
翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;Chunk
,再把每个 Chunk
转换成⼀个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会;总结就是三个阶段:
Plugin
,实例化 Compiler
Entry
出发,针对每个 Module
串行调用对应的 Loader
去翻译文件的内容,再找到该 Module
依赖的 Module
,递归地进行编译处理Module
组合成 Chunk
,将 Chunk
转换成文件,输出到文件系统中Webpack的热更新(Hot Module Replacement,简称HMR),在不刷新页面的前提下,将新代码替换掉旧代码。
HRM的
原理实际上是 webpack-dev-server(WDS)
和浏览器之间维护了一个websocket
服务。当本地资源发生变化后,webpack
会先将打包生成新的模块代码放入内存中,然后WDS
向浏览器推送更新,并附带上构建时的hash,让客户端和上一次资源进行对比。客户端对比出差异后会向WDS
发起Ajax
请求获取到更改后的内容(文件列表、hash),通过这些信息再向WDS
发起jsonp
请求获取到最新的模块代码。
chunk
和module
组成。chunk
由多个模块组合而成,用于代码的合并和分割,在构建过程中一起被打包到一个文件中。entry
中递归寻找出所有依赖的模块。Code Splitting
代码分割,是一种优化技术。它允许将一个大的chunk
拆分成多个小的chunk
,从而实现按需加载,减少初始加载时间,并提高应用程序的性能。
通常Webopack
会将所有代码打包到一个单独的bundle
中,然后在页面加载时一次性加载整个bundle
。这样的做法可能导致初始加载时间过长,尤其是在大型应用程序中,因为用户需要等待所有代码加载完成才能访问应用程序。
Code Splitting
解决了这个问题,它将应用程序的代码划分为多个代码块,每个代码块代表不同的功能或路由。这些代码块可以在需要时被动态加载,使得页面只加载当前所需的功能,而不必等待整个应用程序的所有代码加载完毕。
在Webpack
中通过optimization.splitChunks
配置项来开启代码分割。
Source Map
是一种文件,它建立了构建后的代码与原始源代码之间的映射关系。通常在开发阶段开启,用来调试代码,帮助找到代码问题所在。
可以在Webpack
配置文件中的devtool
选项中指定devtool: 'source-map'
来开启。
Tree Shaking
也叫摇树优化,是一种通过移除多于代码,从而减小最终生成的代码体积,生产环境默认开启。
原理:
Tree Shaking
的基础是ES6模块系统,它具有静态特性,意味着模块的导入和导出关系在编译时就已经确定,不会受到程序运行时的影响。Webpack
构建过程中,Webpack
会通过静态分析依赖图,从入口文件开始,逐级追踪每个模块的依赖关系,以及模块之间的导入和导出关系。Webpack
会标记每个变量、函数、类和导入,以确定它们是否被实际使用。如果一个导入的模块只是被导入而没有被使用,或者某个模块的部分代码没有被使用,Webpack
会将这些未使用的部分标记为"unused"
。Webpack
会在最终的代码生成阶段,通过工具(如UglifyJS
等)删除这些未使用的代码。这包括未使用的模块、函数、变量和导入。Webpack
的持久缓存功能,避免重复构建没有变化的代码。可以使用cache: true选项启用缓存。thread-loader
、happypack
等插件可以将构建过程分解为多个进程或线程,从而利用多核处理器加速构建。DllPlugin
可以将第三方库预先打包成单独的文件,减少构建时间。HardSourceWebpackPlugin
可以缓存中间文件,加速后续构建过程。Webpack
的Tree Shaking
机制,去除未使用的代码,减小生成的文件体积Webpack
的Tree Shaking
机制,去除未使用的代码。这可以从模块中移除那些在项目中没有被引用到的部分。UglifyJS
或Terser
来压缩JavaScript
代码。这会删除空格、注释和不必要的代码,减小文件体积。Webpack
中使用生产模式,通过设置mode: 'production'
来启用优化。这会自动应用一系列性能优化策略,包括代码压缩和Tree Shaking
。Brotli
和Gzip
,来对静态资源进行压缩,从而减小传输体积。他们都是前端构建工具,但vite
构建速度相对于webpack
还是有一些速度优势
vite
是利用浏览器的原生ES moudle
,采用按需加载的当时,而不是将整个项目打包。而webpack
是将整个项目打包成一个或多个bundle
,构建过程复杂。vite
使用浏览器内置的ES
模块功能,使得在开发模式下的热模块替换更加高效,那个文件更新就加载那个文件。它通过WebSocket
在模块级别上进行实时更新,而不是像Webpack
那样在热更新时重新加载整个包。Vite
的构建速度也通常比Webpack
快,因为Vite
的按需加载策略避免了将所有代码打包到一个大文件中。而且,Vite
对于缓存、预构建等方面的优化也有助于减少构建时间。Vite
利用浏览器的缓存机制,将依赖的模块存储在浏览器中,避免重复加载。这使得页面之间的切换更加迅速。Vite
不需要预编译或生成中间文件,因此不会产生大量的临时文件,减少了文件IO操作,进一步提升了速度。Monorepo
是一种将多个项目代码存储在一个仓库的代码管理方式,将不同的项目代码放在一个仓库中,优缺点如下: 优点:
缺点:
常见的Monorepo
实现:
yarn/pnpm/npm
包管理工具下使用workspace
功能,在package.josn
下声明workspace
lerna
具备基本的任务调度能力,支持一键构建、发布等,但是不支持按需构建、不支持离线缓存rush stack
:微软开源的 monorepo
管理工具在npm@3
之前安装依赖时会出现依赖之间互相嵌套,就像树结构一样一层一层,过深的层级嵌套会带来大量重复的文件,有些依赖会重复安装,占用磁盘空间。
json复制代码node_modules
└─ a
├─ index.js
├─ package.json
└─ node_modules
└─ b
├─ index.js
└─ package.json
而在npm@3
时出现了yarn
,它们的出现是为了解决2之前的问题,这时候开始引入扁平化处理依赖嵌套,也就是将所有的依赖都放在一个node_modules
下,依赖在统一层级下互相引用,这样是解决了之前的一些问题,但也导致了新的问题出现就是幽灵依赖。
json复制代码node_modules
├─ a
| ├─ index.js
| └─ package.json
└─ b
├─ index.js
└─ package.json
幽灵依赖是指项目中使用了一些没有在package.json
中定义的包。比如A库依赖B库,那么这两个库都会平铺到node_modules
下。如果项目中使用了B库,然后在package.json
定义了进行安装,所以可以直接访问。假如某天项目不需要A库或者将A库删除,此时B库就会因为找不到A库而跑不起来。
pnpm
是一种替代 npm
和 Yarn
的包管理器,用于管理 JavaScript
项目中的依赖关系。与传统的 npm
和 Yarn
不同,pnpm
提供了一种更为创新的方式来管理依赖项。
在项目安装依赖时,pnpm会将所有的依赖包存储在磁盘的某一个位置简称pnpm store
【查看存储位置】,下次遇到相同的包时会,如果pnpm store
中已经存在这个包,就会从pnpm store
创建一个硬连接到node_modules/.pnpm
下对应的依赖。这样即使多个项目都依赖一个包,也只会在本地存一份代码,不会占用额外的磁盘空间。
而且pnpm
的node_module
并不是平铺的,通过package.json
安装的依赖通过软连接到./.pnpm
中,并且在安装时会判断pnpm store
中是否有相对应的包,如果有就创建硬连接到./.pnpm
json复制代码node_modules
├── a -> ./.pnpm/a@1.0.0/node_modules/a
└── .pnpm
├── b@1.0.0
│ └── node_modules
│ └── b -> <store>/b
└── a@1.0.0
└── node_modules
├── a -> <store>/foo
└── b -> ../../bar@1.0.0/node_modules/bar
这样做带来的好处就是:
pnpm
的链接依赖方式可以减少磁盘占用。相同的依赖包在不同项目中共享,不会造成重复存储。pnpm store
中,所以相同依赖不需要重复下载,这样使得pnpm
的安装和构建速度相对更快,特别是在项目中存在大量依赖项时。
这样做带来的好处就是:
- **节约磁盘空间**: `pnpm` 的链接依赖方式可以减少磁盘占用。相同的依赖包在不同项目中共享,不会造成重复存储。
- **提升安装速度**:由于依赖都是同一管理在`pnpm store`中,所以相同依赖不需要重复下载,这样使得`pnpm` 的安装和构建速度相对更快,特别是在项目中存在大量依赖项时。
- **创建非扁平的node_modules目录**:由于`npm`和`yarn`安装依赖时所有包都会提升到根目录下,会造成幽灵依赖和依赖安全问题,而`pnpm`采用非扁平的形式,有效解决。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。