Vite 零基础极速入门前言 作为前端开发者,或多或少都接触过打包工具,如 webpack、Rollup、Parcel等
前言
作为前端开发者,或多或少都接触过打包工具,如 webpack
、Rollup
、Parcel
等打包工具,它们极大地改善了前端开发者的开发体验。
然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript
代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript
开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR
,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
Vite
的出现就是想要解决上述的问题!
本文将分文两个大的部分:
Vite
概念和设计思想Vite
vsCRA
- 使用
Vite + React
开发ToDoList
正文
Vite
概念和设计思想
带着问题去思考:
- 什么是打包呢?
使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。
- 那我们熟悉的常用的前端构建打包工具有哪些呢?:
webpack、rollup、pracel、gulp
- 这些传统的打包工具存在什么问题呢?
- 缓慢的服务启动:当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。
- 缓慢的更新:基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。
Vite
是怎么解决上述的问题?
Vite
通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。- 依赖:Vite 将会使用
esbuild
预构建依赖。Esbuild
使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。 - 源码:通常为JSX、CSS 或者 Vue SFC等,时常会被编辑,需要转换,基于路由拆分。
- 依赖:Vite 将会使用
Vite
以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
- 在
Vite
中,HMR
是在原生ESM
上执行的。当编辑一个文件时,Vite
只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。 Vite
同时利用HTTP
头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据304 Not Modified
进行协商缓存,而依赖模块请求则会通过Cache-Control: max-age=31536000,immutable
进行强缓存,因此一旦被缓存它们将不需要再次请求。
最后再简单介绍一下, Vite
由两部分组成:
- 一个开发服务,服务于开发环境,使用
ESM+HMR
- 一套构建指令,服务于生产环境,使用
Rollup
打包
Vite
vs CRA
你说好就好了?来点数据证明一下?
接下来使用 Vite
和 create-react-app
来构建以及打包,并记录时间来对比一下:
首先使用create-react-app
创建一个空的React
工程:
开始计时
npx create-react-app my-app
cd my-app
npm start
执行以上命令,打开网页为止,停止计时,记录构建时间
使用 Vite
创建一个空的React
工程(Vite
虽然是尤大大写的但是对 React
的支持甚至比 Vue
更好):
使用 NPM:
$ npm init vite@latest
使用 Yarn:
$ yarn create vite
使用 PNPM:
$ pnpm create vite
开始计时
*vanilla
是相当于原生 JS
不使用框架,其他几个应该都是框架,如图选择 react,然后输入以下命令
cd vite-react
yarn
yarn dev
执行以上命令,打开网页为止,停止计时
然后分别执行打包,进入package.json,查看打包命令,并执行:
yarn build
分别记录时间,并查看打包产物的大小:Vite生成的工程,打包产物在dist
目录,CRA的在 build
;
表格记录对比:
Vite | CRA | |
---|---|---|
初始化时间 | 48s | 1min 17s |
打包时间 | 3s | 11s |
产物大小 | 156kb | 565kb |
结论:
以上只是在无业务代码的工程中测试,随着业务代码量级的提升,时间对比会更加的明显。
好了数据说话的过程也结束了,这下能放心了。
不过一学就会,一敲就废的情况我们还是要通过一些实战代码来避免一下。
使用 Vite + React
开发 ToDoList
复习一下刚才使用 Vite
来创建一个 React
工程:
个人的习惯,作者使用 Yarn:
$ yarn create vite
framework
选择 react
,variant
根据个人是否启用 TS
:
推荐的一种目录,这些也因人而异,因项目大小而异:
接下来就是一些常规的 React
开发;
main.tsx
:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import 'antd/dist/antd.css';
import './index.css'
ReactDOM.render(<App />, document.getElementById("root"));
App.tsx
:
import { useState } from "react";
import ToDoItem from "../components/ToDoItem";
import ToDoContainer from '../components/ToDoContainer'
import { TodoItemType } from "../constans";
function App() {
const [todos,setTodos] = useState<TodoItemType[]|[]>([])
const handleSubmit = (todoItem: any)=>{
console.log(todoItem)
setTodos([
...todos,
todoItem
])
}
const handleOpreta =(todoItem:TodoItemType)=>{
const newTodos = todos.filter(todo =>todoItem.id !== todo.id)
newTodos.push(todoItem)
console.log(newTodos)
setTodos(newTodos)
}
return (
<div className="todo-app">
<h2 className="todo-title">代办清单</h2>
<ToDoItem onSubmit={handleSubmit} />
<ToDoContainer onOpreta={handleOpreta} todos={todos}/>
</div>
);
}
export default App;
/components/ToDoContainer/index.tsx
:
import { List, Radio } from "antd";
import { STATUS, TodoItemType } from "../../constans";
import { CheckOutlined, CloseCircleOutlined } from "@ant-design/icons";
import { useState } from "react";
const ToDoContainer = (props: {
todos?: TodoItemType[] | undefined;
onOpreta: (arg: TodoItemType) => void;
}) => {
const { todos = [], onOpreta } = props;
const [optionsValue, setOptionsValue] = useState(STATUS.IS_CREATE);
const options = [
{ label: "全部", value: '' },
{ label: "代办", value: STATUS.IS_CREATE },
{ label: "已办", value: STATUS.IS_DONE },
{ label: "已删除", value: STATUS.IS_DELETE },
];
const handleChangeRadio = (e: any) => {
console.log(e.target.value);
setOptionsValue(e.target.value);
};
const handleOpreta = (opretaType: string, todo: TodoItemType) => {
switch (opretaType) {
case "is-delete":
onOpreta &&
onOpreta({
...todo,
status: STATUS.IS_DELETE,
});
break;
case "is-done":
onOpreta &&
onOpreta({
...todo,
status: STATUS.IS_DONE,
});
break;
default:
break;
}
};
return (
<div>
<Radio.Group
options={options}
onChange={handleChangeRadio}
value={optionsValue}
optionType="button"
buttonStyle="solid"
/>
<List
className="todo"
dataSource={todos}
renderItem={(todo) =>
optionsValue === todo.status && (
<List.Item className="todo-list-item-container">
{todo.content}
<div>
<CloseCircleOutlined
onClick={() => handleOpreta("is-delete", todo)}
/>
<CheckOutlined onClick={() => handleOpreta("is-done", todo)} />
</div>
</List.Item>
)
}
/>
</div>
);
};
export default ToDoContainer;
/components/ToDoItem/index.tsx
:
import { Button, Input } from "antd";
import { useState } from "react";
import { STATUS } from "../../constans";
const ToDoItem = (props: { onSubmit: (todoItem: any) => void }) => {
const { onSubmit } = props;
const [todoItem, setToDoItem] = useState({
id: Math.random(),
content: "",
status: STATUS.IS_CREATE,
});
const handleSubmit = (e: any) => {
onSubmit && onSubmit({ ...todoItem, id: Math.random() });
};
const handleInpurChange = (e: any) => {
setToDoItem({
...todoItem,
content: e.target.value,
});
};
return (
<div className="todo-item-input">
<Input
value={todoItem.content}
onPressEnter={handleSubmit}
onChange={handleInpurChange}
/>
<Button size="large" type="primary" onClick={handleSubmit}>
提交
</Button>
</div>
);
};
export default ToDoItem;
/constans/index.ts
:
export interface TodoItemType{
id:number,
content:string,
status:number
}
export const STATUS = {
/**
* 全部
*/
/**
* 代办
*/
IS_CREATE:0,
/**
* 已解决
*/
IS_DONE:1,
/**
* 假删除
*/
IS_DELETE:2
}
代码也没有完善,大家可以在我基础上进行完善。 ··· 开发完了,当然还有部署,推荐一个免费在线的部署网站:app.netlify.com/ ,使用github就能够直接登录
执行打包命令:
yarn build
域名会出现这这个位置:
结语
以上就是关于Vite快速入门的全部内容,欢迎大佬们指正。
天气转凉了,大家多喝热水,多注意保暖休息。
转载自:https://juejin.cn/post/7029204845802307598