Vite 学习(二) - 基本使用配置

919 阅读6分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

因为 vite 是使用原生浏览器的模块化功能,内部不能使用 node,也就没有了 require 方法。本小节主要介绍 vite 中常见的使用,包括 csstsenv 环境变量,import.meta 等功能。

CSS 处理

基本使用

src 目录下新增 index.css

@import url('@styles/others.css')
// 对于 HTML 来说, :root 表示<html>元素,除了优先级更高之外,与 html 选择器相同
:root {
  --bg-color: pink;
}

body {
  background-color: var(--bg-color);
}

vite 推荐 css variable

配置路径别名

// vite.config.js
export default defineConfig({
  ...
  resolve: {
    alias: {
      '@styles': "/src/styles"
    }
  }
})

使用 postcss

vite 内部已经集成了 postcss,想使用的话直接在根目录下新建 postcss.config.js

module.exports = {
  plugins: [
    require('@postcss-plugins/console') // 使用 postcss 插件
  ]
}

使用(记得修改配置文件,要重新启动项目)

body {
  background-color: var(--main-bg-color);
  @console.warn hello postcss   // 会在命令行打印,不是浏览器控制台
}

css modules

css modules 可以让你的 css 像模块一样使用,内部的类名都变成了对象属性, vite 中使用也很方便,文件命名以 xxx.module.css 形式。css modules学习

// styles/test.module.css
.moduleTest {
  color:  red;
}

vue 文件中使用

<script setup>
import classModule from '@styles/test.module.css'

console.log(classModule) // 对象形式
</script>

变量形式使用
<template>
  <p :class="classModule.moduleTest">ppppppppppp</p>
</template>

预处理器

vite 好处是不用配置 loader,很多已经内置了。这里以 less 为例,yarn add less

// styles/test.less
@bgColor: red;

.root {
  background-color: @bgColor;
}

vitecss 的使用就介绍到这里,有疑问的话欢迎小伙伴留言讨论。

ts 使用

需要全局安装 tsc,需要在根路径下创建 tsconfig.js

vitets 的态度是,只编译,不校验,只是把 ts 处理成 js 供浏览器使用,但是 ts 的语法无法做校验处理。我们更多依赖的是 vscodeVolar 插件,打包校验的话可以配置

"scripts": {
  "build": "tsc --noEmit && vite build"
}

因为 tsvue 文件不生效,增加 tsvue 文件的支持,yarn add vue-tsc,修改配置

"scripts": {
  "build": "vue-tsc --noEmit && tsc --noEmit && vite build"
}

我们可以配置 "isolatedModules": true, 因为 vite 开发环境不能正确校验 ts

isolatedModules 作用

  1. exports of Non-Value Identifiers
// a.ts
export interface Test{}

// b.ts
import { Test } from './a'
export { Test } // 报错   未定义就导出
  1. Non-Modules Files
每个文件必须是个模块,要不 import,要不 export 导出
  1. References to const enum members
const enum Test {
  a = 0,
  b = 1
}
let test = {
  age: Test.a,// 会报错,这里没有 Test 枚举,导致报错
}

我们知道 vite 中无法使用 node 语法,访问路径,环境变量需要使用 import.meta,我们需要在 tsconfig.js 中进行相关的配置

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": [
      "ESNext",
      "DOM"
    ],
    "types": [
      "vite/client" // 配合 vite 使用 import.meta.xxx
    ],
    "isolatedModules": true,
  },
  "include": [ // 校验哪里的ts文件
    "src/**/*.ts",
    "src/**/*.d.ts"
  ]
}

静态文件处理

基本使用

<script setup>
import logo from './assets/logo.png'
</script>

<template>
  <img :src="logo" alt="">
</template>

自带的 types

我们在引入的文件后面拼接 urlraw,会打印文件的路径和文件的内容

import test from './test?url'
console.log(test, 11)
import test1 from './test?raw'
console.log(test1, 22)

web worker

vite 中也为我们内置了 web worker,我们可以单独开个线程处耗时计算

// main.js
import Worker from './worker?worker'

const worker = new Worker()

worker.onmessage = function (e) {
  console.log(e)
}
let i = 0

function timedCount() {
  i += 1
  postMessage(i)
  setTimeout(timedCount, 1000)
}
timedCount()

处理 json 文件

vite 帮我们自动处理了 json 格式

import {version} from '../package.json'
console.log(version)

webassembly

我们需要用其他语言生成 wasm 文件,这里使用 assemblyscript,安装 npm i assemblyscript

新建 assembly.ts

export function fib(n: i32): i32 {
  var a = 0, b = 1
  if (n > 0) {
    while (--n) {
      let t = a + b
      a = b
      b = t
    }
    return b
  }
  return a
}

执行 ./node_modules/.bin/asc assembly --binaryFile fib.wasm

main.js

import init from './fib.wasm'
init().then(m => {
  console.log(m.fib(10)) // 55
})

集成 eslint pritter

eslint

根目录新建 .eslintrc.js,安装 npm i eslint-config-standard eslint-plugin-import eslint-plugin-promise eslint-plugin-node -D

module.exports = {
 extends: 'standard',
 globals: {
   postMessage: true, // 防止全局未定义 报错
 },
}

pritter

根目录新建 .prettierrc 文件,

{
  "semi": false, // 无分号
  "singleQuote": true, // 单引号
}

配置校验

"lint": "eslint --ext js src/"

如果我们想在 commit 前校验,这里使用 husky 包,根目录必须要有 .git 目录,执行如下命令可以进行校验

  • npx husky install
  • npx husky add .husky/pre-commit "npm run lint"

环境变量

vite 的环境变量存在 import.meta.env 中,根路径下创建集中环境文件(文件名 VITE_APP=xxx 形式)

  1. .env 中的变量什么环境都会存在
  2. env.development 测试环境使用
  3. .env.development.local local 本地环境,以 development 方式打包出来的环境运行在其他机器上,可以区分,local 优先级高
  4. .env.production 正式环境使用的变量
  5. .env.test 测试环境使用的变量,配置命令 vite --mode test 如果您使用 ts 开发,可以配置 ts 类型

根目录创建 vite-env.d.ts

/// <reference types="vite/client" />
interface ImportMetaEnv {
  VITE_TITLE: string
}

hmr

热更新的实现是基于 ws,这里就不详细介绍了。如果我们建一个基础模板,基础逻辑如下

// main.js

document.querySelector("#app").innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`;
}

如果我们去改变里面的文字内容,发现页面是刷新的,不是热更新,如果想实现热更新需要修改为:

// 必须要 导出
export function render() {
  document.querySelector("#app").innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`;
}
render()

// 可能不存在 hot,只在开发环境起作用,vite build 没有 hot
if (import.meta.hot) {
  // 文件可以接受 自己的 热更新
  import.meta.hot.accept((newModule) => {
    newModule.render()
    // 这里使用新 module 的 render。如果直接调用 render,页面不会刷新,调用的还是原来的旧 render,
  })
}

glob import

我们在 vite 中使用 import.meta.xxx 是因为 vite 中使用了 fast-glob 第三方包,我们可以目录文件

  1. 通过正则方式引入 一组 js文件,不是一个 src/glob 文件夹, a.js, b.js, a.json, b.json
const globModules = import.meta.glob('./glob/*')

console.log(globModules)

Object.entries(globModules).forEach(([k, v]) => {
  v().then((m) => console.log(k, m.default))
})

在实际工作中例如,多语言支持,需要多个 js 配置文件,就可以批量获取文件

功能来自 fast-glob

预编译

预编译的目的是把浏览器不识别的文件变为 esm 文件,处理三方包的缓存,vite 对每个文件都没有做缓存,只要请求了一定是最新的内容。

  1. vite 第一次使用会稍微慢一些,因为要处理文件变成浏览器能识别的,经过处理的包缓存在 node_modules/.vite 中。要处理浏览器不识别的文件例如 .vue 文件,commonjs 文件转为 esm 文件 参考

  2. 如果我们使用 lodash 包,可以知道 lodash 下包含多个不同文件,文件合并打包到一起,避免分开 import,会导致浏览器发送多个请求

  3. 我们可以配置 vite 的预编译

export default defineConfig({
  // 需要预编译的包 可以自己配置
  optimizeDeps: {
    include: [],
    exclude: []
  }
})

本节对 vite 中的常见使用方式做了介绍,下一节会介绍下 vite 的高级用法,如果有问题欢迎留言,谢谢阅读!