Vite 深度剖析(一)

Vite 深度剖析(一)

  • [1. Vite 概述](#1. Vite 概述)
  • [2. 快速开始](#2. 快速开始)
    • [2.1 初始化项目](#2.1 初始化项目)
    • [2.2 安装依赖](#2.2 安装依赖)
    • [2.3 添加资源](#2.3 添加资源)
    • [2.4 运行](#2.4 运行)
    • [2.5 修改package.json文件,添加script命令](#2.5 修改package.json文件,添加script命令)
    • [2.6 打包](#2.6 打包)
    • [2.7 支持 ES 模块化](#2.7 支持 ES 模块化)
    • [2.8 预览打包后的情况](#2.8 预览打包后的情况)
  • [3. 配置项和一些常见问题](#3. 配置项和一些常见问题)
    • [3.1 根目录下创建 vite.config.ts](#3.1 根目录下创建 vite.config.ts)
    • [3.2 类型提示问题](#3.2 类型提示问题)
    • [3.3 环境问题](#3.3 环境问题)
      • [3.3.1 node 环境(需要修改package.json的type为module)](#3.3.1 node 环境(需要修改package.json的type为module))
      • [3.3.2 浏览器环境(使用npm包需要使用全路径)](#3.3.2 浏览器环境(使用npm包需要使用全路径))
    • [3.4 ts 文件的引入处理](#3.4 ts 文件的引入处理)
  • [4. 环境变量](#4. 环境变量)
    • [4.1 .env 文件的基本使用](#4.1 .env 文件的基本使用)
    • [4.2 创建读取 .env 文件函数](#4.2 创建读取 .env 文件函数)
    • [4.3 浏览器读取环境变量](#4.3 浏览器读取环境变量)
    • [4.4 浏览器读取环境变量类型提示报错修改](#4.4 浏览器读取环境变量类型提示报错修改)
    • [4.5 不同的 .env 文件及其配置(生产环境删除console为例)](#4.5 不同的 .env 文件及其配置(生产环境删除console为例))
  • [5. 框架加入](#5. 框架加入)
    • [5.1 加入 vue 框架](#5.1 加入 vue 框架)
    • [5.2 加入 React 库](#5.2 加入 React 库)
  • [6. 依赖预构建](#6. 依赖预构建)
    • [6.1 依赖预构建的作用](#6.1 依赖预构建的作用)
    • [6.2 如果不执行依赖预构建(引发请求瀑布流的问题)](#6.2 如果不执行依赖预构建(引发请求瀑布流的问题))

1. Vite 概述

官网:https://cn.vitejs.dev/guide/

2. 快速开始

代码可参考:https://cn.vitejs.dev/guide/ 的vanilla-ts预设模版

2.1 初始化项目

shell 复制代码
mkdir vite-demo
cd vite-demo
pnpm init

2.2 安装依赖

shell 复制代码
pnpm add vite -D
pnpm add typescript -D

2.3 添加资源

index.html ( 和webpack或者vue2项目不同,vite直接将index.html放在根目录下,而不是在public文件夹中):

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>
  <body>
  		<!-- 在 index.html 中引入 src/index.ts // 直接支持ts文件,不需要配置webpack的loader。 -->
    <script src="./src/index.ts"></script>
  </body>
</html>

src/index.ts:

typescript 复制代码
console.log(123)

2.4 运行

typescript 复制代码
npx vite

发现,浏览器不认识ts,但是vite帮我们做了处理。

2.5 修改package.json文件,添加script命令

json 复制代码
{
  "name": "vite-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "preview": "vite preview",
    "build": "vite build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "packageManager": "pnpm@10.21.0",
  "devDependencies": {
    "typescript": "^6.0.2",
    "vite": "^8.0.2"
  }
}

2.6 打包

shell 复制代码
npm run build

2.7 支持 ES 模块化

(1)index.html 添加 type="module"

javascript 复制代码
<!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>
  <body>
    <div id="app"></div>
    <!-- 在 index.html 中引入 src/index.ts // 直接支持ts文件,不需要配置webpack的loader。 -->
    <script type="module" src="./src/index.ts"></script>
  </body>
</html>

(2)添加 src/counter.ts:

javascript 复制代码
export function setupCounter(element: HTMLButtonElement) {
  let counter = 0;
  const setCounter = (count: number) => {
    counter = count;
    element.innerHTML = `Counter: ${counter}`;
  };
  setCounter(0);
  element.addEventListener("click", () => setCounter(counter + 1));
}

(3)src/index.ts 引入:

javascript 复制代码
import { setupCounter } from "./counter";

document.querySelector("#app")!.innerHTML = `
  <div>
    <button id="counter" type="button"></button>
  </div>
`;
setupCounter(document.querySelector("#counter") as HTMLButtonElement);

(4)查看运行情况
点击触发

2.8 预览打包后的情况

shell 复制代码
npm run preview

需要注意的是,这条指令看到的是上次运行npm run build打包后的dist文件夹中的内容。

所以想看到最新的内容,需要先再打包一次再预览。

如果希望每次看到的都是最新的打包后的情况,可以往package.json额外添加一条指令,结合打包和预览:

shell 复制代码
"bp": "vite build && vite preview"

然后执行 npm run bp 即可。

3. 配置项和一些常见问题

配置 Vite 可参考 https://cn.vitejs.dev/config/,以开发服务器的打开配置 server.open 为例。

3.1 根目录下创建 vite.config.ts

(1)配置如下:

typescript 复制代码
export default {
  server: {
    // 默认5173
    port: 3000,
    // 是否默认打开
    // open: true,
    // 也可以设置打开的页面
    open: "./index1.html",
  },
};

(2)使用 defineConfig 工具函数,获取类型提示

typescript 复制代码
import { defineConfig} from "vite";
export default defineConfig({
  server: {
    port: 3000,
    open: true,
  },
});

(3)可以将配置项提取成函数,进行更多操作:

typescript 复制代码
const config = () => {
  // 可以执行一些自定义函数
  console.log(111);
  return {
    server: {
      port: 3000,
      open: true,
    },
  };
};
export default defineConfig(config);

(4)config 是 defineConfig 默认配置对象,有mode、command等属性

typescript 复制代码
import { defineConfig, ConfigEnv} from "vite";
export default defineConfig((config: ConfigEnv) => {
  // config 是默认配置对象,有mode、command等属性
  console.log(config);
  return {
    server: {
      port: 3000,
      open: true,
    },
  };
});

不同命令执行后,终端输出的config都有所不同。但是,我们通常只查看command和mode两个参数,并习惯使用解构的方式输出。

typescript 复制代码
import { defineConfig, ConfigEnv, UserConfig } from "vite";
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
  // config 是默认配置对象,有command、mode等属性
  // 执行npm run build或者npm run test 时,可以看到对应的,命令和模式
  console.log(command);
  console.log(mode);
  // 可以根据不同的命令和模式,返回不同的配置对象
  return {
    server: {
      port: 3000,
      open: true,
    },
  };
});

3.2 类型提示问题

(1)npm 包的TS类型问题

shell 复制代码
pnpm add lodash-es

下载对应包,引入时需要有对应的类型提示包,否则同样会有报错提示。

shell 复制代码
pnpm add @types/lodash-es -D

(2)node 的TS类型问题。

在ts文件中,使用 import path from 'path' 同样会有类型提示问题。

shell 复制代码
pnpm add @types/node -D

3.3 环境问题

3.3.1 node 环境(需要修改package.json的type为module)

创建src/test2.js:

typescript 复制代码
export default function test2() {
  console.log("test2");
}

创建 src/index1.js:

typescript 复制代码
// 如果 cd src,运行node test1.js,会报错
// 需要修改package.json的type字段为module,才能使node运行js文件
import test2 from "./test2.js";
test2();

如果 cd src,运行node test1.js,会报错。需要修改package.json的type字段为module,才能使node运行js文件。

3.3.2 浏览器环境(使用npm包需要使用全路径)

创建index1.html:

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>
  <body>
    <h1>HTML</h1>
    <script type="module" src="./src/test1.js"></script>
  </body>
</html>

修改src/test1.js:

javascript 复制代码
import { debounce } from "lodash-es"; // bare import  ESM默认不支持
// import debounce from "../node_modules/lodash-es/debounce.js"; // 如果在html中直接使用script引入index1.js,需要使用全路径
debounce(() => console.log("test1"), 1000)();
import test2 from "./test2.js";
test2();

使用live-server打开index1.html,会有路径问题。

因为浏览器的ESM默认不支持自动补全路径,需要使用全路径。

typescript 复制代码
import debounce from "../node_modules/lodash-es/debounce.js"; // 如果在html中直接使用script引入index1.js,需要使用全路径
debounce(() => console.log("test1"), 1000)();
import test2 from "./test2.js";
test2();

当然,如果是vite项目运行则没有问题,因为它内部帮我们做了处理。

3.4 ts 文件的引入处理

在引入其他ts文件时,如果加上.ts后缀,可能会有报错(我用的最新版本没有),需要创建tsconfig.json进行处理:

json 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": [
      "DOM",
      "DOM.Iterable",
      "ESNext"
    ],
    "isolatedModules": true,
    "useDefineForClassFields": true,
    "skipLibCheck": true,
    "moduleResolution": "Bundler",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "resolveJsonModule": true,
    "allowImportingTsExtensions": true,
    "noEmit": true
  },
  "include": [
    "src",
    "vite.config.ts"
  ]
}

4. 环境变量

(1)当前模块路径和 node.js 进程的工作目录所在路径

typescript 复制代码
// 当前模块所在路径
console.log(__dirname);
// node.js 进程的工作目录路径
console.log(process.cwd());

二者可能相同,但是并非同一个概念。

4.1 .env 文件的基本使用

(1)在项目根路径创建 .env 文件

typescript 复制代码
#标题
VITE_APP_TITLE='Vite App'
#端口
VITE_PORT=5173
#是否自动打开浏览器
VITE_OPEN=true

(2)在 vite.config.ts 配置文件中使用

typescript 复制代码
import { defineConfig, ConfigEnv, UserConfig, loadEnv } from "vite";
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {

  // mode 表示当前情景,默认development
  // root 表示项目根目录
  // '' 表示前缀,默认读取所有环境变量
  // 可以借助这个函数读取.env文件中的环境变量
  // const env = loadEnv(mode, root, "");
  // 这样只读取以VITE_开头的环境变量
  const env = loadEnv(mode, root, "VITE_");

  // 通常我们会使用解构获取自定义的环境变量,但是注意,读取到的都是string类型,需要转换为对应的类型
  const { VITE_PORT, VITE_OPEN } = env;
  const port = Number(VITE_PORT) || 3000;
  const open = VITE_OPEN === "true" ? true : false;

  console.log(env);
  // 可以根据不同的命令和模式,返回不同的配置对象
  return {
    root,
    server: {
      port: port,
      open: open,
    },
  };
});

4.2 创建读取 .env 文件函数

(1)创建src/vite-env.d.ts:

typescript 复制代码
declare interface ViteEnv {
  VITE_TITLE: string;
  VITE_PORT: number;
  VITE_OPEN: boolean;
}

(2)创建 build/getEnv.ts:

typescript 复制代码
type Recordable<T = any> = Record<string, T>;
export function wrapperEnv(envConfig: Recordable): ViteEnv {
  const ret: any = {};
  for (const envName of Object.keys(envConfig)) {
    let realName = envConfig[envName].replace(/\\n/g, "\n");
    realName =
      realName === "true" ? true : realName === "false" ? false : realName;
    if (envName === "VITE_PORT") {
      realName = Number(realName);
    }
    ret[envName] = realName;
  }
  return ret;
}

(3)在 vite.config.ts 中引入:

typescript 复制代码
import { defineConfig, ConfigEnv, UserConfig, loadEnv } from "vite";
import { wrapperEnv } from "./build/getEnv";

export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
  // 这样只读取以VITE_开头的环境变量
  const env = loadEnv(mode, root, "VITE_");
  console.log(env);

  const viteEnv = wrapperEnv(env);

  // 可以根据不同的命令和模式,返回不同的配置对象
  return {
    root,
    server: {
      port: viteEnv.VITE_PORT,
      open: viteEnv.VITE_OPEN,
    },
  };
});

4.3 浏览器读取环境变量

(1)读取环境变量

typescript 复制代码
console.log(import.meta.env);

src/counter.ts:

typescript 复制代码
export function setupCounter(element: HTMLButtonElement) {
  // 会报错,因为是运行在浏览器端的,所以没有__dirname等全局变量
  // console.log(__dirname);
  // console.log("process", process.cwd());
  console.log(import.meta.env);
  let counter = 0;
  const setCounter = (count: number) => {
    counter = count;
    element.innerHTML = `Counter: ${counter}`;
  };
  setCounter(0);
  element.addEventListener("click", () => setCounter(counter + 1));
}

(2)限制

只能读取到有限的环境变量以及以VITE开头的环境变量。

typescript 复制代码
#标题
VITE_APP_TITLE='Vite App'
#端口
VITE_PORT=5173
#是否自动打开浏览器
VITE_OPEN=true
APP_TEST=XXX

这里加的APP_TEST则读取不到。

(3)修改限制。

可以通过修改共享选项envPrefix,但是没有必要。

4.4 浏览器读取环境变量类型提示报错修改

src/vite-env.d.ts 加入ImportMetaImportMetaEnv

typescript 复制代码
declare interface ViteEnv {
  VITE_TITLE: string;
  VITE_PORT: number;
  VITE_OPEN: boolean;
}

// 定义后,浏览器读取env也会有对应提示
// interface ImportMetaEnv {
//   readonly VITE_APP_TITLE: string;
//   readonly VITE_PORT: number;
//   readonly VITE_OPEN: boolean;
// }

//  定义映射类型,将类型设置为只读
type ReadonlyProps<T> = {
  readonly [P in keyof T]: T[P];
};

interface ImportMetaEnv extends ReadonlyProps<ViteEnv> {}

// 浏览器读取import.meta.env时不报错
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

4.5 不同的 .env 文件及其配置(生产环境删除console为例)

(1).env.development(开发环境):

typescript 复制代码
#开发环境端口
VITE_PORT=8848
#是否删除console打印日志
VITE_DROP_CONSOLE=false

(2).env.production(生产环境):

typescript 复制代码
#是否删除console打印日志
VITE_DROP_CONSOLE=true

(3)src/vite-env.d.ts 添加 VITE_DROP_CONSOLE

typescript 复制代码
declare interface ViteEnv {
  VITE_TITLE: string;
  VITE_PORT: number;
  VITE_OPEN: boolean;
  VITE_DROP_CONSOLE: boolean;
}

// 定义后,浏览器读取env也会有对应提示
// interface ImportMetaEnv {
//   readonly VITE_APP_TITLE: string;
//   readonly VITE_PORT: number;
//   readonly VITE_OPEN: boolean;
// }

//  定义映射类型,将类型设置为只读
type ReadonlyProps<T> = {
  readonly [P in keyof T]: T[P];
};

interface ImportMetaEnv extends ReadonlyProps<ViteEnv> {}

// 浏览器读取import.meta.env时不报错
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

(4)配置 build 属性,控制浏览器是否输出 console.logdebug 语句。

vite.config.ts:

typescript 复制代码
// defineConfig 用于自动提示配置项
import { defineConfig, ConfigEnv, UserConfig, loadEnv } from "vite";
import { wrapperEnv } from "./build/getEnv";

export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {

  const root = process.cwd();
  // 这样只读取以VITE_开头的环境变量
  const env = loadEnv(mode, root, "VITE_");
  // console.log(env);

  const viteEnv = wrapperEnv(env);
  console.log(viteEnv);

  // 可以根据不同的命令和模式,返回不同的配置对象
  return {
    root,
    server: {
      port: viteEnv.VITE_PORT,
      open: viteEnv.VITE_OPEN,
    },
    // esbuild 已弃用,看官网使用build配置
    // esbuild: {
    //   pure: viteEnv.VITE_DROP_CONSOLE ? ["console.log", "debugger"] : [],
    // },
    build: {
      // 使用该选项需要 pnpm add -D terser
      // 参考 https://cn.vitejs.dev/config/build-options#build-minify
      minify: "terser",
      terserOptions: {
        compress: {
          drop_console: viteEnv.VITE_DROP_CONSOLE,
          drop_debugger: viteEnv.VITE_DROP_CONSOLE,
        },
      },
    },
  };
});

(5)执行 pnpm dev


发现端口号变了,浏览器仍然有输出。

(6)执行 pnpm bp

果然,浏览器的console输出消失了。

5. 框架加入

5.1 加入 vue 框架

(1)复制一份vite-demo,更名为vite-vue-demo。删除node_modules重新下载。

(2)下载vue相关的npm包

typescript 复制代码
pnpm add vue
pnpm add @vitejs/plugin-vue -D
pnpm add @vue/tsconfig -D
pnpm add vue-tsc -D

参照 https://cn.vitejs.dev/guide/ 中的 vue-ts 预设,查看package.json,就知道需要下载哪些包了。

其中 @vitejs/plugin-vue 提供:

  • 单文件组件支持
  • 热重载
  • 生产优化

详细使用参考 https://www.npmjs.com/package/@vitejs/plugin-vue

(3)在 ts.config.ts 中加入 vue 相关配置。关键代码:

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

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

(4)创建 src/App.vue:

typescript 复制代码
<template>
  <div>
    <h2>Welcome</h2>
    <button @click="handleCounter">count is {{ count }}</button>
  </div>
</template>

<script setup>
import { ref } from "vue";
const count = ref(0);
const handleCounter = () => {
  count.value++;
};
</script>

<style lang="scss" scoped></style>

(5)创建 src/main.ts:

typescript 复制代码
import { createApp } from "vue";
import App from "./App.vue";

createApp(App).mount("#app");

(6)在 index.html 引入:

typescript 复制代码
<!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>
  <body>
    <div id="app"></div>
    <!-- 在 index.html 中引入 src/index.ts // 直接支持ts文件,不需要配置webpack的loader。 -->
    <!-- <script type="module" src="./src/index.ts"></script> -->
    <script type="module" src="./src/main.ts"></script>
  </body>
</html>

(7)运行 pnpm dev

点击按钮,修改代码WelcomeWelcome!!!,你会发现,并不会整个页面刷新,而是实现了局部热更新(counter 的数字不会归零)。

5.2 加入 React 库

(1)复制一份vite-demo,更名为vite-react-demo。删除node_modules重新下载。

(2)下载react相关的npm包

typescript 复制代码
pnpm add react
pnpm add dom
pnpm add @types/react -D
pnpm add @types/react-dom -D
pnpm add @vitejs/plugin-react -D
pnpm add eslint -D
pnpm add eslint-plugin-react-hooks -D
pnpm add eslint-plugin-react-refresh -D
pnpm add typescript-eslint -D

参照 https://cn.vitejs.dev/guide/ 中的 react-ts 预设,查看package.json,就知道需要下载哪些react相关包了。

(3)tsconfig.json 加入对应语法支持,关键代码:

typescript 复制代码
{
  "compilerOptions": {
    "jsx": "preserve"
  }
}

(4)创建 src/App.tsx:

typescript 复制代码
import React, { useState } from 'react';
export default () => {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h2>Hello World</h2>
      <button onClick={
        () => {
          setCount(count + 1);
        }
      }>count is { count }</button>
    </div>
  )
}

(5)创建src/main.tsx:

typescript 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'

import App from './App.tsx'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

(6)在index.html中引入:

typescript 复制代码
<!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>
  <body>
    <div id="root"></div>
    <!-- 在 index.html 中引入 src/index.ts // 直接支持ts文件,不需要配置webpack的loader。 -->
    <script type="module" src="./src/main.tsx"></script>
  </body>
</html>

(7)运行 pnpm dev

(8)模块热更新。

vite.config.ts 加入 @vitejs/plugin-react,关键代码:

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

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

但是此时还不能做到模块热更新,需要修改 App.tsx 为固定格式:

typescript 复制代码
import React, { useState } from 'react';
const App = () => {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h2>Hello World!!!</h2>
      <button onClick={
        () => {
          setCount(count + 1);
        }
      }>count is { count }</button>
    </div>
  )
}

export default App;

此时就支持模块热更新了。

(9)eslint 相关。

创建 eslintrc.config.cjs:

typescript 复制代码
module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react-hooks/recommended",
  ],
  ignorePatterns: ["dist", ".eslintrc.cjs"],
  parser: "@typescript-eslint/parser",
  plugins: ["react-refresh"],
  rules: {
    "react-refresh/only-export-components": [
      "warn",
      { allowConstantExport: true },
    ],
  },
};

记得下载VSCode的 ESLint 插件。

6. 依赖预构建

参考: https://cn.vitejs.dev/guide/why

6.1 依赖预构建的作用

Vite 通过在一开始将应用中的模块区分为 依赖源码 两类,改进了开发服务器启动时间。
依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。
Vite 将会使用 esbuild 预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍


可以看到,每次执行 pnpm dev 都进行依赖预构建,生成 node_modules/.vite 文件夹,即使删除,下次执行还是会生成。

后续请求包中的文件时,只需要引入与构建的文件即可。

比如,我们在App.vue中引入lodash-es

typescript 复制代码
<template>
  <div>
    <h2>Welcome!!!</h2>
    <input type="text" @input="handleInput" />
    <button @click="handleCounter">count is {{ count }}</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { debounce } from "lodash-es";
const count = ref(0);
const handleCounter = () => {
  count.value++;
};
const handleInput = debounce((e: Event) => {
  console.log((e.target as HTMLInputElement).value);
}, 1000);
</script>

<style lang="scss" scoped></style>

就会在依赖预构建文件夹中生成相关代码,从而直接使用。

6.2 如果不执行依赖预构建(引发请求瀑布流的问题)

vite.config.ts 的 return 中加入关键代码:

typescript 复制代码
optimizeDeps: {
  exclude: ["lodash-es"],
},

关闭依赖预构建的话,所有的node_modules/lodash-es中所有的模块都会直接以请求瀑布流的方式进行获取,十分恐怖。

vite 系列文章:

Vite 深度剖析(一)

Vite 深度剖析(二)

Vite 深度剖析(三)

Vite 深度剖析(四)

相关推荐
zhz52142 小时前
一个简单、轻量级且安全的离线GIS 系统架构设计
安全·系统架构·vue·gis·fastapi
旷世奇才李先生15 小时前
Vue3\+Pinia实战:企业级后台管理系统开发(附权限控制)
vue
花千树-0101 天前
LangGraph 与 ReAct Agent 调试技巧:从日志到可视化全解析
langchain·react·function call·ai agent·langgraph·mcp·j-langchain
空中海1 天前
Vue 全栈开发知识体系
vue
walking9572 天前
Vite 打包优化终极指南:从 30MB 到 800KB 的性能飞跃
前端·vue.js·vite
吴声子夜歌2 天前
Vue3——Vuex状态管理
前端·vue.js·vue·es6
花千树-0102 天前
两行注解把企业 RPC 接口变成 AI 工具
java·rpc·langchain·react·function call·ai agent·mcp
whyfail3 天前
CVE-2026-39363-Vite开发服务器安全漏洞深度分析
安全·vite
江上清风山间明月3 天前
Vite现代化的前端构建工具详解
前端·webpack·nodejs·vite