起凡Code闲聊
原文
以前的vue-cli是基于webpack,而webpack在开发阶段启动的速度是十分缓慢。原因是webpack会把一整个项目从入口开始(index.html)将涉及的所有的模块打包成一个js文件(图1)。
随着现代浏览器对js模块的支持,现在在浏览器中就可以使用export
和 import
关键字来生命模块和导入模块,这意味着浏览器现在不需要一次性获取所有的模块,可以在需要的时候去请求相应的模块(图2)。
并且当我们修改了代码时,vite只会更新代码涉及到模块进行热模块替换(HMR),使用我们在使用vite进行开发是每次更新都是十分的丝滑,很少出现整个页面都全部重新加载的情况。
需要注意的是,vite在打包时(npm run build)使用的是
rollup
。在开发时npm run dev
使用的是esbuild
。也就是说打包时会打包成几个大的js,而不是像开发时那样划分出很多模块。因为这样会增多浏览器和服务端的http请求,使得服务器压力增大。除此之外rollup
在打包方面更加灵活有丰富的拓展插件。

图1 基于打包器的开发服务器

图2 基于ESM的开发服务器
笔记
1. Webpack 的痛点
-
基于打包器的开发服务器(图1):
-
Webpack 在开发阶段会将整个项目从入口文件(如
index.html
)开始,递归分析所有依赖,并将它们打包成一个或多个大的 JavaScript 文件。 -
这种方式的缺点是:
-
启动速度慢:项目越大,依赖越多,打包时间越长。
-
热更新(HMR)效率低:即使只修改一个小文件,Webpack 也可能需要重新构建整个模块依赖图。
-
-
对于大型项目,开发体验会变得非常卡顿。
-
2. Vite 的优势
-
基于 ESM 的开发服务器(图2):
-
Vite 利用了现代浏览器对原生 ES 模块(ESM)的支持,直接在浏览器中按需加载模块。
-
具体原理:
-
开发阶段,Vite 不会预先打包所有模块,而是将代码拆分成多个小模块。
-
当浏览器请求某个模块时,Vite 会动态编译并返回该模块。
-
这种方式避免了 Webpack 的"全量打包"问题,极大地提升了开发服务器的启动速度。
-
-
热更新(HMR):
-
Vite 只会更新修改的模块,而不是重新加载整个页面。
-
这使得开发体验非常流畅,几乎感觉不到延迟。
-
-
3. Vite 的构建工具
-
开发阶段(
npm run dev
):-
Vite 使用 esbuild 作为开发阶段的构建工具。
-
esbuild 是一个用 Go 语言编写的高性能 JavaScript 打包工具,速度极快,比传统的 JavaScript 打包工具(如 Webpack)快 10-100 倍。
-
esbuild 负责将模块编译成浏览器可以理解的 ESM 格式。
-
-
生产阶段(
npm run build
):-
Vite 使用 Rollup 作为生产阶段的打包工具。
-
Rollup 是一个专注于打包 JavaScript 库的工具,支持 Tree Shaking(移除未使用的代码)和生成更小的包。
-
在生产环境中,Vite 会将代码打包成几个大的 JavaScript 文件,而不是像开发阶段那样划分出很多小模块。
-
这是因为:
-
减少 HTTP 请求数量,降低服务器压力。
-
生产环境不需要动态加载模块,打包成少量文件可以提高加载性能。
-
-
-
4. Vite 的设计哲学
-
开发阶段:
-
利用现代浏览器的 ESM 支持,实现按需加载和快速启动。
-
通过 esbuild 实现极快的模块编译。
-
-
生产阶段:
-
使用 Rollup 进行高效打包,生成优化的生产代码。
-
兼顾性能和开发体验。
-
5. Vite 与 Webpack 的对比
特性 | Vite | Webpack |
---|---|---|
启动速度 | 极快(按需加载) | 慢(全量打包) |
热更新(HMR) | 高效(只更新修改的模块) | 较慢(可能重新构建依赖图) |
开发阶段构建工具 | esbuild(极快) | Webpack(较慢) |
生产阶段构建工具 | Rollup(高效打包) | Webpack(功能强大但较慢) |
模块加载方式 | 基于 ESM 的按需加载 | 全量打包 |
适用场景 | 现代前端项目(支持 Vue、React 等) | 传统前端项目(兼容性更强) |
6. 总结
-
Vite 的出现解决了 Webpack 在开发阶段的性能瓶颈,提供了更快的启动速度和更流畅的热更新体验。
-
它充分利用了现代浏览器的特性(如 ESM),并结合 esbuild 和 Rollup 的优势,实现了开发和生产阶段的高效构建。
-
对于现代前端项目(尤其是使用 Vue、React 等框架的项目),Vite 是一个非常值得尝试的构建工具。
安装
安装 vite
npm i vite -D
在package.json中添加npm script
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
{
"scripts":{
"dev":"vite",
"build":"vite build",
"preview":"vite preview"
},
"dependencies": {
"vite": "^6.2.2"
}
}
1. scripts
部分
-
scripts
是 npm 的脚本命令配置,用于定义一些常用的命令。 -
在你的配置中,定义了三个脚本:
"dev": "vite"
-
运行
npm run dev
时,会启动 Vite 的开发服务器。 -
这个命令会:
-
启动一个本地开发服务器。
-
支持热更新(HMR),修改代码后会自动刷新页面。
-
提供极快的启动速度,因为 Vite 不会预先打包所有模块,而是按需加载。
-
"build": "vite build"
-
运行
npm run build
时,会使用 Vite 进行生产构建。 -
这个命令会:
-
将项目打包成生产环境可用的静态文件(HTML、CSS、JS 等)。
-
使用 Rollup 进行打包,生成优化的代码。
-
支持 Tree Shaking(移除未使用的代码)和代码压缩。
-
"preview": "vite preview"
-
运行
npm run preview
时,会启动一个本地服务器来预览生产构建的结果。 -
这个命令会:
-
在本地启动一个静态文件服务器,预览
npm run build
生成的打包结果。 -
用于在生产部署前检查构建结果是否正确。
-
-
2. devDependencies
部分
-
devDependencies
是开发依赖,表示这些包仅在开发环境中使用,不会被打包到生产环境中。 -
在你的配置中,只有一个开发依赖:
"vite": "^6.2.2"
- 这是 Vite 的版本号。
相比于vue-cli
你会发现vite的项目中,index.html不在public目录下,并且你可以看见index.html中直接引用了js/ts文件。原因是vite
会把index.html视为你源码的一部分。默认index.html是整个项目的入口。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script type="module">
import {showCurrentTime} from './index.js'
setInterval(() => document.querySelector(".time").innerHTML = showCurrentTime() + '', 1000)
</script>
<body>
<div>当前时间:<span class="time"></span></div>
</body>
</html>
一个简单的 HTML 文件,结合了 JavaScript 模块化(ESM)的功能,用于动态显示当前时间。以下是对代码的详细解释和改进建议:
1. HTML 结构
-
这是一个标准的 HTML5 文档结构。
-
关键部分:
-
<div>当前时间:<span class="time"></span></div>
:用于显示当前时间,时间会动态更新到<span>
中。 -
<script type="module">
:表示这是一个 ES 模块脚本,支持import
和export
。
-
2. JavaScript 模块化
-
代码中使用了 ES 模块化语法:
import { showCurrentTime } from './index.js';
-
从
index.js
文件中导入showCurrentTime
函数。 -
需要确保
index.js
文件存在,并且导出了showCurrentTime
函数。
-
-
setInterval
用于每秒更新一次时间:setInterval(() => document.querySelector(".time").innerHTML = showCurrentTime() + '', 1000);
-
每秒调用一次
showCurrentTime
函数,并将返回值插入到<span class="time">
中。 -
+ ''
的作用是将返回值强制转换为字符串(如果showCurrentTime
返回的不是字符串)。
-
1. setInterval
-
setInterval
是一个 JavaScript 定时器函数,用于每隔指定的时间(以毫秒为单位)重复执行某个函数。 -
语法:
setInterval(callback, delay);
-
callback
:要执行的函数。 -
delay
:间隔时间(以毫秒为单位)。
-
-
在代码中:
setInterval(() => document.querySelector(".time").innerHTML = showCurrentTime() + '', 1000);
delay
是1000
毫秒(即 1 秒),所以每秒执行一次回调函数。
2. 箭头函数 () => { ... }
-
这是一个箭头函数,用于定义回调函数。
-
语法:
() => { /* 函数体 */ }
-
在代码中,箭头函数的内容是:
document.querySelector(".time").innerHTML = showCurrentTime() + '';
3. document.querySelector(".time")
-
document.querySelector
是用于选择 DOM 元素的方法。 -
".time"
是一个 CSS 选择器,表示选择类名为time
的元素。 -
在你的 HTML 中,对应的元素是:
<span class="time"></span>
4. innerHTML
-
innerHTML
是 DOM 元素的属性,用于设置或获取元素内部的 HTML 内容。 -
在你的代码中:
document.querySelector(".time").innerHTML = showCurrentTime() + '';
- 将
.time
元素的内容设置为showCurrentTime()
的返回值。
- 将
5. showCurrentTime()
-
这是一个自定义函数,假设它返回当前时间的字符串表示。
-
例如:
function showCurrentTime() { const now = new Date(); return now.toLocaleTimeString(); // 返回当前时间的字符串表示 }
-
返回值可能是
"14:35:22"
这样的格式。
6. + ''
-
+ ''
的作用是将showCurrentTime()
的返回值强制转换为字符串。 -
这是一种常见的技巧,确保即使
showCurrentTime()
返回的不是字符串(例如数字或对象),也能正确显示。
7. 代码的执行流程
-
每秒执行一次箭头函数:
-
调用
showCurrentTime()
获取当前时间。 -
将时间字符串赋值给
.time
元素的innerHTML
。 -
页面中显示的时间会每秒更新一次。
-
index.js
export const showCurrentTime=()=>{
const date=new Date();
return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
}
一个用于返回当前时间的函数 showCurrentTime
,使用了 ES6 的模块化语法(export
)和模板字符串。以下是对代码的详细解析和改进建议:
1. 代码解析
-
export
:-
使用
export
将showCurrentTime
函数导出,使其可以被其他模块导入和使用。 -
例如:
import { showCurrentTime } from './index.js';
-
-
const showCurrentTime = () => { ... }
:- 这是一个箭头函数,用于返回当前时间的格式化字符串。
-
new Date()
:- 创建一个
Date
对象,表示当前时间。
- 创建一个
-
date.getFullYear()
:- 获取当前年份(例如
2023
)。
- 获取当前年份(例如
-
date.getMonth() + 1
:- 获取当前月份(0 到 11),需要加 1 才能得到正确的月份(1 到 12)。
-
date.getDate()
:- 获取当前日期(1 到 31)。
-
date.getHours()
:- 获取当前小时(0 到 23)。
-
date.getMinutes()
:- 获取当前分钟(0 到 59)。
-
date.getSeconds()
:- 获取当前秒数(0 到 59)。
-
模板字符串:
-
使用反引号(`````)【感叹号左边】和
${}
语法,将变量嵌入字符串中。 -
例如:
export const showCurrentTime=()=>{ const date=new Date(); return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` }
-
返回的字符串格式为:
YYYY-MM-DD HH:MM:SS
。
-

图3 目录结构
运行
执行 npm run dev
访问http://localhost:5173

图4 效果