常用的git指令
- git clone:克隆远程仓库到本地,可以是ssh,https
- git init:在当前目录下初始化git仓库
- git add:将文件添加到暂存区,准备提交
- git commit -m "commit message":提交暂存区的改动到本地仓库,同时附带提交信息 feat,fix,chore
- git status:查看工作区、暂存区的状态,显示文件的修改情况
- git diff:显示工作区与暂存区之间的差异
- git log:显示提交日志
- git branch:列出所有的分支,当前分支前面会有个*
- git checkout:切换到指定分支
- git checkout -b:创建并切换到新分支
- git merge:将指定分支合并到当前分支
- git pull:拉去远程仓库的更新并合并到当前的分支
- git push:将本地分支的更新推送到远程仓库
- git fetch:从远程仓库中获取最新的代码提交,确保本地代码仓库和远程代码仓库同步
- git stash:暂存
git rebase 和 git merge 的区别
git rebase 和 git merge 都是用于合并分支的命令,但是这两命令合并的方式不同
- git merge:将一个分支的更改合并到另一个分支,创建一个新的merge commit,将两个分支的历史合并在一起,这个merge commit会在分支历史中保留,可以清晰地看到哪些分支合并到了主分支,合并之后形成分叉结构
- git rebase:两个分支合并的时候,会将整个分支合并到另一个分支的顶端。首先找到两个分支的共同commit记录,然后提取之后的所有commit,将这个commit记录添加到另一个分支的最前面,两个分支合并后的commit记录就变成线性记录
webpack配置有哪些
- entry: 入口文件
- output:输出文件配置
- resolve:用来配置模块的解析方式
- module:用来配置模块如何被解析
- plugins:插件,增强相关功能
- devServer:开发服务器配置
- devtool:调试工具
- optimization:优化的相关配置
- externals:外部扩展的配置
- performance:性能相关配置
- target:构建的目标环境
有哪些常见的Loader和Plugin
Loader
- image-loader:加载并压缩图片文件
- swc-loader:类似babel-loader,编译效率更高
- css-loader:加载css,支持模块化,压缩,文件导入等特性
- style-loader:把css注入到js中,通过dom操作去加载css
- eslint-loader:通过eslint检查js
- tslint-loader:通过tslint检查ts
- babel-loader:把es6转换成es5
Plugin
- define-plugin:定义环境变量
- progress-plugin:设置打包进度
- html-webpack-plugin:简化html文件创建
- webpack-bundle-analyzer:可视化webpack输出文件的体积
- mini-css-extract-plugin:分离样式文件,css提取为独立文件,支持按需加载
- react-refresh-plugin:react支持热更新
Loader和Plugin的区别
功能不同
- Loader本质是一个函数,它是一个转换器。webpack只能解析原生js文件,对于其他类型的文件就需要用loader进行转换。
- Plugin是一个插件,用于增强webpack功能。webpack在运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。
用法不同
- loader的配置是在module.rules下进行。它的类型是数组,每一项都是一个object,里面描述了对于什么类型的文件(test)用什么加载(loader)和使用的参数(options)
- plugin的配置是在plugins下。它的类型也是数组,每一项是一个Plugin的实例,参数通过构造函数传入。
webpack的构建流程
- 初始化参数:从配置文件或者shell语句中读取合并参数
- 开始编译:用参数去初始化Compiler对象,加载所有配置的插件,执行run方法
- 确定入口:根据entry参数找到入口文件
- 编译模块:从入口文件出发,调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
- 完成模块编译:在经过第4步使用Loader翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
总结就是三个阶段:
- 初始化:启动构建,读取与合并配置参数,加载Plugin,实例化Compiler
- 编译:从Entry出发,针对每个Module串行调用对应的Loader去翻译文件的内容,再找到该Module依赖的Module,递归地进行编译处理
- 输出:将编译后的Module组合成Chunk,将Chunk转换成文件,输出到文件列表中
Webpack的热更新原理
在不刷新页面的前提下,将新代码替换旧代码。
HMR的原理实际上是webpack-dev-server和浏览器之间维护了一个websocket服务。当本地资源发生变化后,webpack会先将打包生成的新的模块代码放入内存中,然后wds向浏览器推送更新,并附带上构建时的hash,让客户端和上一次资源进行对比。客户端对比出差异后会向wds发起ajax请求获取到更改后的内容,通过这些信息再向wds发起jsonp请求获取到最新的模块代码。
bundle,chunk和module分别是什么
- bundle:捆绑包,它是构建过程的最终产物
- chunk:一个chunk由多个模块组合而成,用于代码的合并和分割,在构建过程中被打包到一个文件中
- module:代码的基本单位,可以是一个文件,一个组件,一个库等。在编译的时候会从entry中递归寻找出所有依赖的模块
Code Spliting
Code Spliting代码分割,是一种优化技术。它允许将一个大的chunk拆分成多个小的chunk,从而实现按需加载,减少初始加载时间,并提高应用程序的性能。
通常webpack会将所有代码打包到一个单独的bundle中,然后在页面加载时一次性加载这个bundle。这样的做法会导致初始加载时间过长,尤其是大型应用中,很影响用户的体验。
Code Spliting解决了这个问题,它将应用程序的代码划分成多个代码块,每个代码块代表不同的功能或路由。这些代码块可以在需要时被动态加载,使得页面只加载当前所需的功能,而不必等待整个应用程序的所有代码加载完毕。
在Webpack中通过optimization.splitChunks配置项来开启代码分割。
Webpack的Tree Shaking原理
Tree Shaking也叫树摇优化,它是一种通过移除多余的代码,从而减小最终生成的代码体积,生产环境是默认开启的。
原理:
- ES6模块:
Tree Shaking
的基础是ES6模块系统,它具有静态特性,意味着模块的导入和导出关系在编译时就已经确定,不会受到程序运行时的影响。 - 静态分析:在webpack构建过程中,webpack会通过静态分析依赖图,从入口文件开始,逐级追踪每个模块的依赖关系,以及模块之间的导入和导出关系。
- 标记未使用代码:在分析模块依赖时,webpack会标记每个变量、函数、类,以确定它们是否被实际使用。如果一个导入的模块只是被导入而没有被使用,或者某个模块的部分代码没有被使用,webpack会将这些未使用的部分标记为unused。
- 删除未使用代码:在代码标记为未使用后,webpack会在最终的代码生成阶段,通过工具(如uglifyjs)删除这些未使用的代码。这包括未使用的模块,函数,变量和导入。
如何提高webpack的打包速度
- 利用缓存:利用webpack的持久缓存功能,避免重复构建没有变化的代码。可以使用cache:true选项启用缓存。
- 使用多进程/多线程构建:使用thread-loader,happypack等插件可以将构建过程分解为多个进程或线程,从而利用多核处理器加速构建。
- 使用DLLPlugin和HardSourceWebpackPlugin:DllPlugin可以将第三方库预先打包成单独的文件,减少构建时间。HardSourceWebpackPlugin可以缓存中间文件,加速后续构建过程。
- 使用TreeShaking:配置Webpack的Tree Shaking机制,去除未使用的代码,减小生成的文件体积
- 移除不必要的插件:避免不必要的复杂性和性能开销。
如何减少打包后的代码体积
- 代码分割(Code Spliting):将应用程序的代码划分成多个代码块,按需加载。这可以减小初始化加载的体积,使页面更快加载。
- Tree Shaking:配置Webpack的Tree Shaking机制,去除未使用的代码。这可以从模块中移除那些在项目中没有被引用到的部分。
- 压缩代码:使用uglifyjs或teser来压缩js代码,这会删除空格,注释和不必要的代码,减小文件体积
- 使用生产模式:在
Webpack
中使用生产模式,通过设置mode: 'production'
来启用优化。这会自动应用一系列性能优化策略,包括代码压缩和Tree Shaking
。 - 使用压缩工具:使用现代的压缩工具,如
Brotli
和Gzip
,来对静态资源进行压缩,从而减小传输体积。 - 利用CDN加速:将项目中引用的静态资源路径修改为CDN上的路径,减少图片,字体等静态资源的打包。
vite比webpack快在哪里
他们都是前端构建工具,但vite构建速度远远超过webpack的构建速度。
- 冷启动速度:
vite
是利用浏览器的原生ES moudle
,采用按需加载,而不是将整个项目打包。而webpack
是将整个项目打包成一个或多个bundle
,构建过程复杂。 - HMR热更新:
vite
使用浏览器内置的ES
模块功能,使得在开发模式下的热模块替换更加高效,那个文件更新就加载那个文件。它通过WebSocket
在模块级别上进行实时更新,而不是像Webpack
那样在热更新时重新加载整个包。 - 构建速度:在生产环境下,
Vite
的构建速度也通常比Webpack
快,因为Vite
的按需加载策略避免了将所有代码打包到一个大文件中。而且,Vite
对于缓存、预构建等方面的优化也有助于减少构建时间。 - 缓存策略:
Vite
利用浏览器的缓存机制,将依赖的模块存储在浏览器中,避免重复加载。这使得页面之间的切换更加迅速。 - 不需要预编译:
Vite
不需要预编译或生成中间文件,因此不会产生大量的临时文件,减少了文件IO操作,进一步提升了速度。
为什么pnpm快
npm的问题
在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
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
js
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
的安装和构建速度相对更快,特别是在项目中存在大量依赖项时。 - 创建非扁平的node_modules目录 :由于
npm
和yarn
安装依赖时所有包都会提升到根目录下,会造成幽灵依赖和依赖安全问题,而pnpm
采用非扁平的形式,有效解决。