Vite实战指北

Vite是一个开源的前端构建工具,起初只支持对Vue的打包构建(毕竟由尤雨溪牵头开发),但到了目前的2.0版本,Vite已经实现了所有项目框架的打包构建,Vite以几乎无法察觉的编译速度无须重新刷新页面即可得到结果的优势被誉为下一代的构建工具。

为什么Vite这么快?

Vite做了很多避免重复编译的事情,比如类库缓存、热更新无须刷新页面、多文件束成一个文件节省API请求等,而且相较于传统的打包构建工具(如 Webpack)先打包构建再启动开发服务器,Vite 巧妙地利用了浏览器对 ESM 的支持,先启动开发服务器,当代码执行到模块加载时再请求对应模块的文件,直接砍掉了开发构建这一步(生产环境使用Rollup打包)来看看下面的对比图:

Webpack

通过js入口去扫描这些应用引入的子模块,等模块全部被解析完后,其中包括一些动态模块也会被解析,然后把这些模块注入到index.js中最后启动devserve等待访问。缺点是项目越来越大启动时间就会越来越长。但其实很多时候首屏所使用的js都是比较少的,所以我们其实不需要把全部都打包进来。

在这里插入图片描述

Vite

启动DevServe服务,利用ESModule会以请求的方式加载模块,而因为首屏只有少量的js模块,而且动态的模块是不会被加载进来的(浏览器随取随用),所以这就是比Webpack打包启动要快很多很多的原因。

在这里插入图片描述

如何使用Vite

Vite的极其轻量甚至可以用于老项目,但我们先用Vite构建一个新的项目:

yarn create vite

接下来进行一些自定义配置:

  • Project name: 项目的名称,默认使用vite-project
  • Select a framework: 选择框架
    • vanilla: 一个纯净的js网站项目
    • vue: vue项目(仅支持3.0)
    • react: react项目
    • 也支持一些其他框架供选择,但在这里不多赘述。
  • Select a variant: 选择是否为TS

是的,你没有看错,这样就完成了一个Vite项目的搭建。以下是结构图:

在这里插入图片描述

Vite的入口文件有别于其他,它的入口文件是index.html,这也是因为它不必去重新刷新页面。vite.config.ts就是vite的配置文件了。你可以看到vite的依赖的是一个个的插件,这也是为什么Vite特别轻量级的原因。

CSS处理

vite 原生支持 css variable,并且支持 css module(在 css 文件增加后缀.module 即可),pre-process

配置TSX模板

我们现在安装一个插件使其支持TSX模板,这里不使用React做示范是因为Vue+TSX已经覆盖了React的配置指引。

yarn add @vitejs/plugin-vue-jsx

再配置到文件里:

import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

export default defineConfig({
  plugins: [vue(), vueJsx()]
})

这样我们就可以使用TSX模板了

配置TS文件

Vite原生支持TS,但这里我们有针对Vite的一些配置,React可以略过第一条配置。

  1. "jsx": "preserve":不允许TS代替编译jsx/tsx文件,因为vue的格式不适用于常规jsx/tsx模板,该项将留给后续插件编译
  2. "isolatedModules": true:为了防止使用vite时一些不必要的麻烦。
    • vite在编译文件时,export只会在本文件中查找,而不会在其他文件中查找。
    • 在声明一个常量枚举时,ts会帮你做常量替换然后删除该常量,但是vite不会识别这种语法,编译时就会把常量枚举删除掉,从而导致替换时找不到变量进而报错的问题。
    • vite不会编译没有import也没有export的ts文件。
  3. "types": ["vite/client"]:增加vite内部API的types,比如允许ts文件导入一个图片
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true, // 提供整合能力 例如 import * as react from 'react' -> import react from 'react'
    "lib": ["ESNext", "DOM"],
    "isolatedModules": true,
    "types": ["vite/client"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/main.js"],
}

注意如果你使用的是vue-sfc模板,需要额外安装一个vue-tsc插件,它可以帮你将vue模板中的ts代码得到解析,然后在修改一下脚本:

"build": "vue-tsc -- noEmit && tsc --noEmit && vite build"

静态资源处理

vite做了一系列的静态资源处理,这里介绍一下使用

// 将其视为一个静态资源,而不是作为js/ts文件导入
import testImg from './testImg?url'

// 将其视为一个静态文件,并且将其内部的内容以字符串形式打印
import test from './test?raw'

// 将其视为一个静态文件,并且视为一个Web Worker
import Worker from './worker?worker'
const worker = new Worker()
worker.onmessage = (event) => console.log(event)

配置Eslint

由于vite中没有帮我们引入eslint代码校验,所以我们需要自己手动配置eslint

yarn add eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise  eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

PS:如果你没有打算使用TS,那么不必安装最后两项插件,eslint针对vue语法校验的插件是eslint-plugin-vue,react是eslint-plugin-react,如果使用hooks那么再安装eslint-plugin-react-hooks即可

建立.eslintrc.js

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: ['standard', 'plugin:@typescript-eslint/recommended'],
  plugins: ['@typescript-eslint', 'vue'],
  env: {
    node: true
  }
}

这样 eslint 就会生效了,不使用TS的情况下只需要这样:

module.exports = {
  extends: ['standard']
}

但添加了eslint校验,只会在编辑器中提示,如果我们想要在每次commit时做一遍校验,可以使用husky钩子,具体这里不做详细说明。

Vite的环境变量

我们可以在Vite中非常细粒化的配置环境变量,但在此之前容我先介绍一下Vite的默认变量

import.meta.env.DEV // 是否为开发环境
import.meta.env.PROD // 是否为生产环境
import.meta.env.MODE // 当前的环境,默认只有development和production,后续会介绍如何自定义
import.meta.env.SSR // 是否为服务端渲染
import.meta.env.BASE_URL // 基础路径

自定义环境变量

  1. 创建.env 文件
  • vite 会将.env 文件中的所有环境变量添加进来,前缀需要是 VITE,譬如 VITE_API=‘https://github.com’。
  • 可以根据 mode 创建更多的 env 文件,譬如.env.production 则只有 mode 为 production 时才会使用。在 script 后可以添加–mode 参数来自定义 mode 环境。
  • 可以在不同机器上的相同环境下进行配置,譬如.env.production.local 则只会在本地的 production 环境下生效。
  1. 为自定义环境变量添加类型注释

在 src 目录下创建 vite-env.d.ts

/// <reference types="vite/client" />

interface ImportMetaEnv {
  VITE_API: string
}

Vite热更新

vite 在很多插件中其实已经实现了热更新,但如果是使用原生 js 或其他种种原因没有使用 vite 插件,则需要我们自己配置热更新。或者你需要做某些事情要在热更新时。

export function render() {
  document.querySelector('#app').innerHTML(`
    <div>Hello Vite!</div>
    <a href="#">This is a web project without the modern framework</a>
  `)
}

// 因为线上不支持热更新,所以需要提前判断一下
if (import.meta.hot) {
  // 当监听到热更新钩子时,手动调用一次
  import.meta.hot.accept((newModule) => {
    newModule.render()
  })
}

glob import

也许你已经在之前的项目使用过Webpack的一次性引入所有文件毋须再自己引入router、store文件了,但我在这里介绍一下vite的使用方式,最后还会介绍一个更快的引入方式

// 引入一个文件夹下的所有文件
const moduleFiles = import.meta.glob('./modules/*.ts')

const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // 将 './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles[modulePath]
  modules[moduleName] = value
  return modules
}, {})

直接将代码引入进来,不再需要异步引入

const modulesFiles = import.meta.globEager('./modules/*.ts')

Vite预编译

Vite预编译可谓是在快的基础上更快了一步,它会将所有你用到的类库做一个cache缓存,比如第一次启动时编译会进行缓存,之后再去使用直接从缓存中取就可以,避免了不必要的编译环节。
Vite预编译也做了多文件合并的操作,避免过多的请求次数,例如lodash;同时也会将所有的CommonJS转编译成ESModule。

当然你也可以配置自己是否需要预编译,不过一般不用过于担心,Vite会帮你做好一切。

optimizeDeps: {
  include: ['vue'],
  exclude: ['react']
}

Vite常用配置

别名

resolve: {
  alias: {
    '@': '/src'
  }
}

代理

server: {
	port: 3000, // 默认就是3000
	open: true, // 第一次启动时自动打开浏览器
	proxy: {
		'/api': {
        	target: 'http://jsonplaceholder.typicode.com',
        	changeOrigin: true,
        	rewrite: (path) => path.replace(/^\/api/, '')
      	}
	}
}

详细配置请见官网

Vite SSR渲染

非node.js服务

当后端项目是由非 node.js 服务支持且需要前端项目嵌入到后端项目中(例如 JSP 等模板技术,需要将 index.html 嵌入进去),这里由 pug 模板举例:

开发中

html
    head
        title= title
    body
        h1=message
        div(id="app")
        script(src="http://localhost:3000/@vite/client" type="module")
        script(src="http://localhost:3000/src/main.js" type="module")

生产打包

当到了生产环境打包上线时,需要在 vite 配置文件中允许打包出一个 manifest.json 文件

build: {
  manifest: true
}

这样的话打包完成之后就会生成一个 manifest.json 的描述文件,后端渲染模板需要引入 file, file.imports.vendor, file.css[0] 文件

html
    head
        title= title
        link(href=css rel="stylesheet")
    body
        h1=message
        div(id="app")
        script(src=vendor)
        script(src=index)

node.js服务

这里先展示一个最小demo:

const express = require('express')

const app = express()
const { createServer } = require('vite')

createServer({
  server: {
    middlewareMode: 'html' // 启动vite的dev server
  }
}).then((vite) => {
  app.use(vite.middlewares)
  app.listen(3000)
})

这样就实现了热更新,但这种操作其实只是等于vite在背后为我们做的,真正需要配置的是SSR服务端渲染

使用服务端渲染SSR

这里我们使用React作为实例

const express = require('express')
const fs = require('fs')

const app = express()
const { createServer } = require('vite')

createServer({
  server: {
    middlewareMode: 'ssr'
  }
}).then((vite) => {
  app.use(vite.middlewares)

  app.get('*', async (req, res) => {
    let template = res.send(fs.readFileSync('index.html', 'utf-8'))
    template = await vite.transformIndexHtml(req.url, template) // 需要vite处理一下template模板
    const context = {}
    const { render } = await vite.ssrLoadModule('./server-entry.js')
    const html = await render(req.url, context) // 渲染出html的内容
    // 在<div id="app"></div>中添加注释 然后通过该注释替换真实的模板内容
    const responseHtml = template.replace('<!--APP_HTML-->', html)
    res.set('content-type', 'text/html')
    res.send(responseHtml)
  })

  app.listen(3000)
})

一般来讲,SSR 渲染需要一个入口配置文件来将浏览器渲染模式更改为后端渲染模式,很少有情况会出现不需要这个兼容文件的情况,比如 router 只能在浏览器模式使用,后端渲染模式是不支持的。

server-entry.js

import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router-dom'
import { APP } from './App'

export function render(url, context) {
  return ReactDomServer.renderToString(
    <StaticRouter location={url} context={context}>
      <App />
    </StaticRouter>
  )
}
打包SSR渲染

先配置两条命令:

"build:client": "vite build --outDir dist/client",
"build:server": "vite build --outDir dist/server --ssr server-entry.js",

一条是打包项目命令,一条是打包 server 命令,接下来开始配置 server

const express = require('express')
const fs = require('fs')

const app = express()
const template = fs.readFileSync('dist/client/index.html', 'utf-8')

// 映射静态文件
app.use(express.static('dist/client'))

app.get('*', async (req, res) => {
  const render = require('dist/server/server-entry.js').render()
  const context = {}
  const html = await render(req.url, context)

  // 如果上下文存在url,表示需要重定向
  if (context.url) {
    res.redirect(301, context.url)
    return
  }

  const responseHtml = template.replace('<!--APP_HTML-->', html)
  res.set('content-type', 'text/html')
  res.send(responseHtml)
})

app.listen(3000)
使用SSR实现静态站点导出

我们这里只是举例一个最小demo,真正的配置绝对会比这复杂很多很多倍,Vite在这方面的态度是希望有其他服务来基于Vite开发,如果你真的有这类需求,那么只能暂时自己开发了。

const fs = require('fs')

const template = fs.readFileSync('dist/client/index.html', 'utf-8')
const render = require('dist/server/server-entry').render()

// 拿到page文件夹下的所有文件名称
const routesToRender = fs
  .readdirSync('src/pages')
  .map((file) => file.replace('.jsx', '').toLowerCase())

for (const route of routesToRender) {
  const context = {}
  const html = render(route, context)
  const responseHtml = template.replace('<!--APP_HTML-->', html)
  const filePath = `dist/static/${route}.html`
  fs.writeFileSync(filePath, responseHtml)
}
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于 Vue 3 + Vite + TypeScript 的项目实战,你可以按照以下步骤进行: 1. 创建项目:使用 Vue CLI 创建一个新的 Vue 3 项目,同时选择 TypeScript 作为语言支持。如果你还没有安装 Vue CLI,可以先通过 npm 全局安装它:`npm install -g @vue/cli`。然后运行`vue create my-project`命令创建项目,并选择 TypeScript 作为预设。 2. 构建工具:Vue CLI 默认使用 webpack 作为构建工具,但是对于 Vue 3,你可以尝试使用 ViteVite 是一个基于 ES Modules 的开发服务器,在开发模式下具有非常快的冷启动速度。安装 Vite:`npm install -g create-vite`,然后在项目目录下运行`create-vite`命令创建一个新的 Vite 项目。 3. 配置:根据你的项目需求,配置 Vite 和 TypeScript。你可以编辑 `vite.config.ts` 文件来自定义 Vite 的配置,例如添加插件、配置别名等。此外,还需要编辑 `tsconfig.json` 文件来配置 TypeScript 相关的选项,如指定编译输出目录、允许的模块类型等。 4. 开发:开始编写代码!在 `src` 目录中创建你的组件、页面和其他文件。Vue 3 的语法和 API 与 Vue 2 有一些差异,你可以查阅 Vue 3 的官方文档获取更多信息。同时,由于你选择了 TypeScript,可以利用其类型系统来提供更好的开发体验和代码质量。 5. 运行项目:在项目根目录下运行`npm run dev`命令,启动 Vite 的开发服务器。然后在浏览器中访问 `http://localhost:3000`,即可看到你的项目运行起来。 6. 构建和部署:当你的项目开发完成后,可以使用`npm run build`命令构建生产环境的代码。Vite 会将你的代码打包成优化过的 ES Modules 格式,以提供更好的加载性能。构建完成后,你可以将生成的静态文件部署到你喜欢的服务器或者托管平台上。 希望以上的步骤能够帮助你进行 Vue 3 + Vite + TypeScript 的项目实战!如果有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值