感谢b站up主__付金权的精彩分享!
感谢掘金博主 金色海洋 分享的一篇文章说清 webpack、vite、vue-cli、create-vue 的区别
感谢 jirengu.com 的精彩分享
脚手架
创建项目,选择性安装需要的插件,指定统一的风格,生成demo。
@vue/cli
原名 vue-cli 是 Vue 早期推出的一款脚手架,使用 Webpack 构建 Vue 项目,可以选择安装需要的各种插件,比如 Vuex、VueRouter等。
vue-cli 用于创建 vue2 的项目; @vue/cli 用于创建 vue3 的项目,当然也支持 vue2。
使用起来比较繁琐,首先要安装脚手架,然后使用 vue create hello-world 创建项目。
create-vue
create-vue 是 Vue3 的专用脚手架,使用 vite 创建 Vue3 的项目,也可以选择安装需要的各种插件,使用更简单。
yarn global add create-vite-app@1.18.0
cva gulu-ui-1
cd gulu-ui-1
yarn // 相当于 yarn install
yarn dev
可选插件
| 标题 | 内容 |
|---|---|
| TypeScript | |
| JSX Support | |
| Vue Router | Single Page Application development |
| Pinia | state management |
| ESLint | code quality |
| Prettier | code formating |
| Vitest | Unit testing |
| Cypress | both Unit and End-to-End testing |
构建工具
什么是构建工具
构建工具就是各种转换或编译工具的集合。
| 构建工具 | 内容 |
|---|---|
| 转换 | babel 语法降级:将 ES 新语法转换兼容旧版浏览器 tsc工具: 将 TS 代码转换为 JS 代码 Uglifyjs体积优化: 将代码压缩成体积小,性能更高的文件 vue / react-compiler: 将 jsx 文件或 .vue文件 转换为 render 函数(浏览器能识别) |
| 编译 | less / sass / postcss / component-style 对应的 loader编译工具 |
build 打包 就是将开发者写的浏览器不认识的代码,交给构建工具进行编译处理的过程,打包完成后给浏览器可以识别的文件。
构建工具做了什么
| 功能 | 内容 |
|---|---|
| 模块化开发支持 | 支持直接从node_modules里引入代码 + 多种模块化支持 |
| 处理代码兼容性 | babel语法降级,less、ts语法转换 |
| 提高项目性能 | 压缩文件,代码分割 |
| 热更新 | 构建工具自动监听文件变化,调用对应的集成工具重新打包,浏览器再重新运行 |
| 开发服务器 | 解决跨域的问题 |
构建工具发展
| 标题 | 打包脚本 | 构建工具 |
|---|---|---|
史前 无Node.js之前 | PHP / Python / Java / Ruby / BashScript | make |
| Node.js 问世 (为打包而生) | npm run dev 开发环境 dev 调用 JS 脚本npm run build 生产环境 build 调用 JS 脚本 | Grunt:以 文件 为操作对象,以 任务 为运行单元。Gulp:操作放在内存中 |
| Webpack | 全能选手:支持多场景的模块化,不限于浏览器端。 Vue Cli 是基于 Webpack 的 Vue 工具链 | 缺点是配置复杂,打包随着项目变大,越来越慢 |
| Rollup | 打包性能比Webpack好 | 缺点:功能不如Webpack全 |
| Parcel | 优点是零配置 | 缺点:功能不如Webpack全 |
| Snowpack | ||
| Vite | 优点是远大于Webpack的开发速度 开发时,不打包,充分利用浏览器的 module能力,按需加载发布时,用 Rollup打包 | 缺点是插件不够多 |
| Turbopack |
Webpack (2014年发布)
支持多场景的模块化,不限于浏览器端。
对于浏览器端的Webpack工作机制:提供import、export、ES6模块化的语法支持,把Nodejs模块化的代码转换为浏览器执行的代码。
loader与plugin区别
loader用于加载文件:任何文件都可以通过import导入进来,要有对应loader
module.exports = {
module:{
rules:[{
test:/\.css$/i,
use:["style-loader","css-loader"]
}]
}
}
plugin用于扩展功能,插件参与打包过程(去除不必要代码)
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins:[new HtmlWebpackPlugin()]
}
常用功能
yarn add webpack@4.41.2 webpack-cli@3.3.10
yarn add webpack-dev-server@3.9.0
webpack-dev-server // 本地预览
yarn init -y // 初始化工程
懒加载
对于某个JS文件很大,存在很多的模块,不想一开始就加载,当用户开启某个功能时,再去加载某个模块。
export default function lazy(){
console.log('我是一个懒加载的模块')
}
const promise = import('./lazy')
promise.then((module)=>{ // 成功执行的函数
const fn = module.default
fn()
},()=>{ // 失败执行的函数
console.log('模块加载错误')
})
Rollup(2015年发布)
- 面向
ES Modules(最新的JS模块语法)而不是AMD/CommonJS(Webpack支持的旧标准),支持Tree-shaking - 不提供
dev server,只做生产环境打包
Parcel(2017年发布)
优点:零配置,缺点:功能不如Webpack全
Snowpack(2019年发布)
Vite(并不只是打包)
- 官方文档:Vitejs.dev
- 继承Snowpack的核心思想:开发时,不打包,充分利用浏览器的
module能力,按需加载 - 发布时,用Rollup打包。
- 搭建项目:Vite 需要Node.js版本 14.18+,16+
create-vite(vite脚手架)
create-vite和vite的关系是:
create-vite内置了vite,就像vue-cli会内置webpack
Vite周边
-
VitePress:用于建立文档类型的网站
-
Slidev:用Markdown做PPT的工具
-
Vitest:类似Jest的前端测试框架
Turbopack
Webpack的后继打包工具,由维护Nextjs的Vercel公司开发。底层用Rust编写
打包过程在开发时期,不同于Vite的利用浏览器自身的模块化,不会对开发时对依赖打包.
包管理工具
为什么需要包管理
随着一个网站依赖的代码越来越多,下载资源要逛很多个站点,操作起来很麻烦,一个靠谱程序员因为实在受不了,自己就用 JS (运行在 Node.js 上)开发了一个工具把下载资源的这些代码集中到一起管理。
这个工具的全称为:Node Package Manager
。这些代码就称为:包(package),后来npm内置于Node.js中,即npm会随着node.js自动安装。
这个靠谱的程序员是:Isaac Z. Schlueter
包管理能做什么
npm可以管理本地项目的所需模块并自动维护依赖情况,也可以管理全局安装的 JS 工具;
如果一个项目中存在package.json文件,那么用户可以直接使用npm install命令自动安装和维护当前项目所需的所有模块。
常用工具
| 包管理 | 内容 | 备注 |
|---|---|---|
| npm | 下载工具 | 串行下载依赖 |
| yarn (facebook) | 包管理工具 | 并行下载依赖、支持从缓存安装、引入yarn.lock机制 |
| pnpm | 包管理工具 | 全局安装所有依赖,安装速度极快、磁盘空间利用效率高 |
node_modules 结构历史
| 标题 | 内容 |
|---|---|
| npm@3 之前版本 (第一阶段) | 依赖树层级深,目录路径长 |
| npm@3 版本 (第二阶段) | 依赖结构不确定,扁平化算法复杂,耗时长 |
| pnpm (第三阶段) | 硬链+软链 根目录中的包只是一个符号链接 |
// (第一阶段)npm@3 之前版本
node_modules
└─ foo
├─ index.js
├─ package.json
└─ node_modules
└─ bar
├─ index.js
└─ package.json
// (第二阶段)npm@3 版本 扁平化处理
node_modules
├─ foo
| ├─ index.js
| └─ package.json
└─ bar
├─ index.js
└─ package.json
// (第三阶段)pnpm 版本
node_modules
├─ .pnpm
| ├─ foo@1.0.0/node_modules/foo
| | └─ index.js
| └─ bar@2.0.0/node_modules/bar
├─ foo -> .pnpm/foo@1.0.0/node_modules/foo
└─ bar -> .pnpm/bar@2.0.0/node_modules/bar
第三阶段:pnpm
node_modules 根目录中的包只是一个符号链接。require('foo') 将执行 node_modules/.pnpm/foo@1.0.0/node_modules/foo/indexjs 中的文件(这里是硬链接),而不是 node_modules/foo/index.js 中的文件。
这种布局结构的一大好处是只有真正在依赖项中(package.json dependences)的包才能访问