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)
}

相关推荐
昨天;明天。今天。4 分钟前
案例-任务清单
前端·javascript·css
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己2 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2343 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河3 小时前
CSS总结
前端·css
BigYe程普3 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H3 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍3 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发