vite5 的基本使用与自动导入文件

介绍

Vite 和 Webpack 一样,也是个前端工程化构建工具。根据官方文档的描述它由两部分组成:

  • 一个开发服务器,它基于原生 ES 模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR)。
  • 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。

对于生产构建,vite 的目标浏览器是:

支持原生 ES 模块、原生 ESM 动态导入和 import.meta。

现代浏览器大多已经能够支持 ES6+ 的语法,我们只需要在 index.html 使用 <script src> 引入 js 文件时,添加 type 属性为 module,即可以支持 ES Module 的模块化方案:

html 复制代码
<!-- index.html -->
<script src="./index.js" type="module"></script>

所以在开发项目时,没必要再像 webpack 那样将 es6+ 的语法使用 babel 等工具转成 es5。但是 vite 也不是什么都没做就直接把我们编写的 js 代码扔给浏览器了,因为还有一些问题需要处理,比如:

  • import 文件时必须添加后缀名,也就是不能省略 .js
  • 如果导入的文件又依赖其它的文件,那么每个 js 文件都会被依次加载,影响效率;

比如使用了 lodash 库,这里安装的是使用 ES Module 规范的 lodash-es,导入时也是直接去找到导出了 lodash 对象的 lodash.default.js:

javascript 复制代码
// index.js
import _ from './node_modules/lodash-es/lodash.default.js'
const add = (augend, addend) => {
  return _.add(augend, addend)
}
console.log(add(1, 2))

lodash.default.js 里又导入了 array.js、collection.js 等,array.js 里又需要依赖其它文件,这些文件都会被一个个加载:

  • 无法处理 .ts 或 .vue 等文件。

借助 vite,就能帮我们解决上述这些问题。

安装与使用

初体验

先使用 pnpm 直接安装个 vite 来体验下:

powershell 复制代码
pnpm init
pnpm add vite -D

安装成功后可以在 node_modules.bin 目录下看到已经有了名为 vite 的可执行文件:

所以可以直接执行:

powershell 复制代码
npx vite

vite 就会开启开发服务器并构建我们的项目。现在,在导入文件时,就可以去掉后缀名,并且直接从 lodash-es 导入:

javascript 复制代码
import _ from 'lodash-es'
const add = (augend, addend) => {
  return _.add(augend, addend)
}
console.log(add(1, 2))

vite 会将 lodash 相关文件都放到一个文件去,这样无疑减少了 http 请求,提高了效率:

处理 ts 文件

vite 对 ts 是天生支持的,无需像在 webpack 中使用时还要安装 typescript 和 ts-loader。比如项目中有 ts 代码:

typescript 复制代码
// utils\index.ts
export function sayHello(msg: string) {
  console.log(msg)
}
javascript 复制代码
// index.js
import { sayHello } from './utils/index'
const msg = 'hello juejin'
sayHello(msg)

在开发阶段,vite 会使用 ESBuild 将 ts 文件转换成 js 代码,然后通过使用 connect 创建的开发服务器将对 utils/index.ts 的请求进行转发,将转换成 js 的文件返回给浏览器,所以最终浏览器得到的 utils/index.ts 里其实都是 js 代码,可以直接解析:

甚至在 index.html 的 <script> 引入的文件都可以直接是 ts 文件:

html 复制代码
<!-- index.html -->
<script src="./index.ts" type="module"></script>

处理样式文件

vite 不需要额外的配置就能处理 css、sass 和 less 等文件,但是如果使用了 sass 或 less 还是需要安装这些预处理依赖的。比如在 index.js 导入了 css 和 scss 文件:

javascript 复制代码
import './styles/main.css'
import './styles/main.scss'

那么就需要安装好 sass:

powershell 复制代码
npm i sass -D

如果要使用 PostCSS,也是只要安装了 postcss 和其依赖的插件,比如 postcss-preset-env,然后再配置下 postcss.config 即可,而不需要像 webpack 那样还要去 webpack.config 配置什么 loader:

powershell 复制代码
npm i postcss postcss-preset-env -D
javascript 复制代码
// postcss.config.js
module.exports = {
  plugins: [require('postcss-preset-env')]
}

处理 vue 文件

如果我们的项目里有 vue 文件:

vue 复制代码
<!-- vue\App.vue -->
<script setup>
  import { ref } from 'vue'
  const msg = ref('Hello')
</script>

<template>
  <div>{{ msg }}</div>
</template>
javascript 复制代码
// index.js
import { createApp } from 'vue'
import App from './vue/App.vue'

const app = createApp(App)
app.mount(document.querySelector('#app'))

我们需要先安装 vue:

powershell 复制代码
pnpm add vue

并且安装处理 vue 文件的插件 @vitejs/plugin-vue:

powershell 复制代码
pnpm add @vitejs/plugin-vue -D

然后在 vite.config.js 中使用插件,这里直接使用 ES Module 的语法来导出对象,因为 vite5 中 CJS 的 Node API 已经被废弃:

javascript 复制代码
import vue from '@vitejs/plugin-vue'
export default {
  plugins: [vue()]
}

如果是使用脚手架工具 create vite 创建的 vue 项目,即:

powershell 复制代码
pnpm create vite

在生成的 vite.config.ts 中代码如下,可以看到和上面我们自己写的差不多,但是使用了 defineConfig 这个方法,好处在于编写时会有提示,不容易敲错:

typescript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
})

在浏览器查看效果时,可以看到,浏览器获取的 App.vue 文件里的内容其实也是被替换成了 js 代码:

打包与预览

执行如下命令便可对项目打包:

powershell 复制代码
npx vite build

打包完成后可以执行如下命令预览:

powershell 复制代码
npx vite preview

自动导入文件

下面再顺便说一个 vite 如何自动导入文件的功能。

在使用 vite 构建的 vue + ts 项目中,当需要定义路由时,因为我是将各个 route 对象抽离到了 src\router\modules 目录下定义,然后在 src\router\index.ts 通过 router.addRoute 动态添加的:

所以需要在 index 文件自动地去获取 modules 目录下的各个 route 对象。这一功能如果是在原来使用 vue-cli 搭建的项目中,可以使用 webpack 的 require.context(),而在 vite 中,则是使用 import.meta.glob()

typescript 复制代码
const modulesFiles: Record<string, any> = import.meta.glob('./modules/*.ts', {
  eager: true
})

如果单独打印 console.log(import.meta.glob('./modules/*.ts')),会发现其结果为一个对象,里面的 key 都是文件的路径,value 都是函数:

import() 的返回值是一个 promise,需要我们在 .then 里获取导入的结果然后编写后续逻辑,这主要是为了实现懒加载,比如我们在定义 route 的 component 属性时一般也是使用这种语法来实现的路由懒加载。但是此处我们显然希望立即获取到结果,于是我们给 import.meta.glob() 传入了第 2 个参数 { eager: true }

直接打印 modulesFiles,结果如下:

现在对象里的 value 就都是 Module 了,我们可以通过 default 属性来获取各个文件导出的 route 对象了:

typescript 复制代码
for (const key in modulesFiles) {
  const module = modulesFiles[key].default
  router.addRoute(module)
}

相关推荐
Martin -Tang29 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发30 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新6 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_6 小时前
【Linux】多线程(概念,控制)
linux·运维·前端