vite快速上手

前言

Vite是思维比较前卫而且先进的构建工具 他确实解决了一些webpack解决不了的问题,同时降低了一些心智负担, 已经有一些大厂在使用vite去构建项目

  1. vite基于自己得天独厚的优势,他未来一定会占有一席之地, 前段时间阿里的面试已经在问Vite了
  2. Vite是vue团队的官方出品,背靠这么大的生态,vue-cli会在下面两个版本中将vite作为预设构建工具
  3. 未来你使用vue-cli去构建vue项目的时候, 你要写的vue.config.js不再是webpack的配置, 而是vite的配置(目前只基于浏览器项目)
  4. Vite也支持直接构建react项目,也支持构建angular项目,svelte项目也支持构建

构建工具

企业级项目开发过程中, 需要做哪些工作?

  1. 浏览器他只认识html,css,js, 所以就会产生大量编译工作:
  • typescript: 如果遇到ts文件, 我们需要使用tsc将typescript代码转换为js代码
  • React/Vue: 安装react-compiler/vue-complier,将我们写的jsx文件或者.vue文件转换为render函数
  • less/sass/postcss/component-style: 我们需要安装less-loader,sass-loader等一系列编译工具
  • 语法降级: babel--->将es的新语法转换旧版浏览器可以接受的语法
  • 体积优化: uglifyjs--->将我们的代码进行压缩变成体积更小性能更高的文件
  1. 以上这些动作, 只要文件稍微改一点点东西,就要从新跑一遍, 非常麻烦
  2. 需要有一个工具能够帮你把tsc,react-compiler,less,babel,uglifyjs全部集成到一起
  • 这样, 我们只需要关心我们写的业务代码就好了
  • 只要我们写的代码一变化 --->有人帮我们自动去把tsc,react-compiler,less,babel,uglifyjs全部挨个走一遍 --->得到可执行的js
  • 这个工具就叫做**构建工具**
  • 将我们写的浏览器不认识的代码 交给构建工具进行编译处理的过程就叫做打包,
  • 打包完成以后会给我们一个浏览器可以认识的文件
  1. 一个构建工具他到底承担了哪些脏活累活:
  • 模块化开发支持: 支持直接从node_modules里引入代码 + 多种模块化支持
  • .处理代码兼容性: 比如babel语法降级,less,ts 语法转换(**不是构建工具做的,构建工具将这些语法对应的处理工具集成进来自动化处理**)
  • 提高项目性能: 压缩文件,**代码分割**
  • 优化开发体验:
    • 构建工具会帮你自动监听文件的变化,当文件变化以后自动帮你调用对应的集成工具进行重新打包,然后再浏览器重新运行(整个过程叫做热更新,hot replacement)
    • 开发服务器:跨域的问题,用react-cli create-react-element vue-cli 解决跨域的问题

构建工具是什么?

  1. 构建工具让我们不用关心代码如何在浏览器运行,
  2. 让我们专注于业务逻辑的实现
  3. 我们只需要给构建工具提供一个配置文件(如果不配置,他会有默认的配置),
  4. 他就可以按照我们的要实现代码编译, 代码压缩, 代码热更新等诸多功能
  5. 构建工具的本质是一个集成工具

常见的构建有哪些?

  • webpack
  • vite
  • parcel
  • esbuild
  • rollup
  • grunt
  • gulp

vite相对于webpack的优势: 服务的启动和更新速度更快

官方文档: https://cn.vitejs.dev/guide/why.html#the-problems

了解webpack的工作流程

  1. 当我们执行 npm run dev 类似的命令启动前端服务后, 经过这样一个流程:
复制代码
/**
  webpack支持多种模块化
*/
const lodash = require("lodash") // commonjs规范
import Vue from "vue" // es6 module规范


/**
  webpack的转译过程
  1.经过AST抽象语法分析工具分析
  2.得到JS文件的所有导入和导出操作
  3.把所有的导入和导出语法统一为webpack语法
  4.前端不能操作文件, 但是webpack运行在服务端
  5.下面是一个简单复现代码, 了解就行
*/
(function(){
    function webpack_require() {}
   // 通过webpack的配置文件指定入口文件: index.js
   modules[entry](webpack_require)
},({
    "./src/index.js": (webpack_require) => {
        const loadsh = webpack_require("lodash")
        const Vue = webpack_require("vue")
    }
}))


/**
 webpack的转译结果
*/
const loadsh = webpack_require("lodash")
const Vue = webpack_require("vue")
  1. 因为webpack支持多种模块化, 所以需要统一转译模块化代码后才能启动服务, 这种加载全部依赖后再运行项目的模式也叫全量加载
  2. 项目越大, webpack所处理的js代码越多, 启动服务器的时间就越长
  3. webpack能不能改呢? 不能, 因为这种机制性的改动, 后果是不可预估的

了解vite的工作流程

  1. 当我们执行 npm run dev 类似的命令启动前端服务后, 经过这样一个流程:
  1. 这种先启动服务, 再根据使用情况加载依赖的模式称为按需加载
  2. 按需加载相对全量加载, 冷启动和热更新的优势明星, 且项目越大优势越明显
  3. vite会不会直接把webpack干翻?
  • vite是基于es modules支持规范,关注浏览器端的开发体验,
  • webpack拥有更好的兼容性, node环境和浏览器环境都能跑
  • 侧重点不一样,不存在谁替代谁

vite是什么

vite官网搭建vite项目文档教程

vite官网: https://vitejs,dev/guide/#scaffolding-your-frst-vite-project

当我们执行`yarn create vite`命令

  • 帮我们全局安装一个东西: create-vite(vite的脚手架)
  • 直接运行这个create-vite bin目录的下的一个可执行配置

create-vite 和 vite的关系是什么?

  1. create-vite内置了vite, create-vite是脚手架, vite是构建工具
  2. 脚手架是对构建工具的进一步简化, 提供了最佳实践的配置(预设), 可以做到开箱即用
  3. 我们之前接触过的vue-cli就内置了webpack
  4. 我们先学习vite, 再使用create-vite

vite基本使用

用vite启动项目

  1. 创建工程文件

    <!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> <script src="./main.js" type="module"></script> </body> </html>

    export const count = 0

    import { count } from './counter.js'

    console.log(count);

  1. 初始化工程

    npm init -y
    npm i lodash

    import _ from 'lodash'
    console.log(_, "lodash");

    export const count = 0

复制代码
## 上面的报错意思: 就是找不到lodash模块, 检查资源引用的方式, 只识别 / ./ ../方式引入资源;
## 当我们使用非绝对路径或者相对路径引入资源, 浏览器不自动搜寻node_modules呢?
## 答案: 当我们打开HTML网页, 首先通过HTTP加载main.js, 然后再加载counter.js, 然后加载lodash, 然后 lodas还会依赖其他资源, 这些都要通过网络加载, 这些加载是非常占用网络资源的, 所以浏览器不愿意自动加载node_modules资源
## 解决: 使用vite构建工具
  1. 安装vite, 使用vite运行项目

    npm i vite -D

    {
    "name": "01tiyan",
    "version": "1.0.0",
    "description": "",
    "main": "main.js",
    "scripts": {
    "dev": "vite", // 新增
    "test": "echo "Error: no test specified" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
    "lodash": "^4.17.21"
    },
    "devDependencies": {
    "vite": "^7.1.3"
    }
    }

vite的打包构建

  1. 浏览器默认支持的EsModues规范, 只识别绝对路径或相对路径的方式引入资源, 为什么使用vite启动项目后, 就能识别 import _ from 'lodash' 这段代码了呢?

  2. 在开发环境中, vite在打包的过程中会进行依赖预构建, 效果如下

    ##依赖预构建做了什么事:
    首先vite会找到对应的依赖,然后调用esbuild(对js语法进行处理的一个库),将其他规范的代码转换成esmodule规范,
    然后放到当前目录的node modules/.vite/deps中, 同时对esmodule规范的各个模块进行统一集成

    ##寻找依赖的过程
    找寻依赖的过程是自当前目录依次向上查找的过程,直到搜寻到根目录或者搜寻到对应依赖为止

    ##最终效果

    原始代码 复制代码
    import _ from "lodash"
    打包后的代码 复制代码
    import _ from "/node_modules/.vite/deps/lodash.js"
  3. vite的依赖预构建非常重要, 解决了3个问题:

  • 统一导出格式: 不同的第三方包会有不同的导出格式, 这个vite无法约束, 所以vite找到依赖之后, 会调用esbuild对js语法进行处理, 将其他规范的代码统一转换成esmodule规范, 然后放到当前目录下的 node_modules/.vite/deps中, 同时对esmodules规范的各个模块进行统一集成

  • 路径补全: 由于统一导出格式时把所有的依赖都放在了 .vite/deps 目录中, 所以路径重写就非常方便了, 只要遇到非绝对路径和相对路径的引用, 就尝试路径补全

  • 解决网络多包传输的性能问题: 有了依赖预构建以后无论有多少的额外export 和 import, vite都会尽可能的将他们进行集成, 最后只生成一个或者几个模块

    /**
    原始代码, index.js依赖a.js
    */

    a.js 复制代码
    export default function a() {}
    index.js 复制代码
    export {defaault as a} from './a.js'
    
    // 上面的语法相当于先导入再导出
    // import a from './a.js'
    // export const a = a

    /**
    vite重写之后, 被导入的代码直接替换到文件中(目的是尽可能的集成)
    */

    index.js 复制代码
    function a() {}
  1. 在生产环境中, vite会全权交给rollup这个库去完成打包的, 让代码兼容更多的环境

vite配置文件

复制代码
import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: {
    exclude: [] // 数组中的依赖项不进行依赖构建
  }
})

import { defineConfig } from 'vite'

export default defineConfig({})

import { defineConfig } from 'vite'

export default defineConfig({})

import { defineConfig } from "vite"
import viteBaseConfig from './vite.base.config'
import viteDevConfig from "./vite.dev.config"
import viteProdConfig from "./vite.prod.config"

// 策略模式
const envResolver = {
  "build": () => {
    console.log("生产环境配置文件");
    return ({ ...viteBaseConfig, ...viteProdConfig })
  },
  "serve": () => {
    console.log("开发环境配置文件");
    return ({ ...viteBaseConfig, ...viteDevConfig })
  }
}

export default defineConfig(({ command }) => {
  return envResolver[command]()
})

{
  "name": "01tiyan",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "lodash": "^4.17.21"
  },
  "devDependencies": {
    "lodash-es": "^4.17.21",
    "vite": "^7.1.3"
  }
}

vite的环境变量

基本概念

复制代码
环境变量:  根据当前的代码环境而确定最终值的变量就叫做环境变量

代码环境:  
1,开发环境
2. 测试环境
3,预发布环境
4. 灰度环境
5,生产环境

如何配置

  1. 明确配置需求

    接入百度地图sdk,小程序的sdk
    APP KEY: 测试环境和生产还有开发环境是不一样的key

    • 开发环境: 110
    • 生产环境: 111
      我们去请求第三方sdk接口的时候需要带上的一个身份信息

    对接后端API, 生产环境和开发环境是同一个地址吗? 肯定不是

  2. 新增环境变量文件

    ENV_APP_KEY = 110
    ENV_BASE_URL = http://www.test.api/

    ENV_APP_KEY = 111
    ENV_BASE_URL = http://www.api/

    环境变量文件的分类

    .env:所有环境都需要用到的环境变量
    .env.development:开发环境需要用到的环境变量(默认情况下vite将我们的开发环境取名为development)
    .env.production:生产环境需要用到的环境变量(默认情况下vite将我们的生产环境取名为production)

  3. 配置变量前缀

    import { defineConfig } from 'vite'

    export default defineConfig({
    envPrefix: "ENV_" // 配置vite注入客户端环境变量校验的前缀, 默认是VITE_
    })

  4. 使用环境变量

    import { defineConfig, loadEnv } from "vite"
    import viteBaseConfig from './vite.base.config'
    import viteDevConfig from "./vite.dev.config"
    import viteProdConfig from "./vite.prod.config"

    // 策略模式
    const envResolver = {
    "build": () => {
    console.log("生产环境配置文件");
    return ({ ...viteBaseConfig, ...viteProdConfig })
    },
    "serve": () => {
    console.log("开发环境配置文件");
    return ({ ...viteBaseConfig, ...viteDevConfig })
    }
    }

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

    // loadEnv()方法的作用: 手动确认env文件
    // 参数1: 通过mode传过来的字符擦混
    // 参数2: 当前env文件所在的目录, process.cwd()就是获取node的工作进程目录
    // 参数3: 环境变量的文件名, 默认是.env
    // 为什么? 环境变量文件是可以在配置中修改的, 如果要在这里提前拿到我们定义的环境变量, 就要这么做
    // 补充: process是Node服务给我提供的对象
    const env = loadEnv(mode, process.cwd(), "")
    // 查看生效的环境变量
    console.log("process=", env);

    return envResolvercommand
    })

    // 读取环境变量
    // 开发环境的key是110. 生产环境的key是111
    const getUserPosition = () => {
    console.log("ENV_APP_KEY", import.meta.env.ENV_APP_KEY);

    return {
    APP_KEY: import.meta.env.ENV_APP_KEY
    }
    }
    getUserPosition()

    // 读取环境变量
    // 开发环境是 http://www.test.api/
    // 生产环境是 http://www.api/
    const getBaseUrl = () => {
    console.log("ENV_BASE_URL", import.meta.env.ENV_BASE_URL);

    return {
    ENV_BASE_URL: import.meta.env.ENV_BASE_URL
    }
    }
    getBaseUrl()

    import { count } from './counter.js'
    import './request.js'

    console.log(count);

  5. 启动项目

    启动项目:

    npm run dev

    真正执行的命令:

    npm run dev --mode development

详细的执行流程

  1. 执行 npm run dev命令, node就会去package.json文件的scripts中匹配脚本, 启动 vite 服务

    补充更多细节:

    npm run dev -启动-> vite -真正执行-> vite --mode development

    简单理解为: 自动补全

    npm run dev --mode development -启动-> vite --mode development

  2. vite内置了dotenv这个第三方库, dotenv会自动读取.env文件, 解析这个文件中的环境变量, 并将其注入到process对象下 (不会直接注入,要考虑配置冲突问题)

    import { defineConfig, loadEnv } from "vite"
    import viteBaseConfig from './vite.base.config'
    import viteDevConfig from "./vite.dev.config"
    import viteProdConfig from "./vite.prod.config"

    // 策略模式
    const envResolver = {
    "build": () => {
    console.log("生产环境配置文件");
    return ({ ...viteBaseConfig, ...viteProdConfig })
    },
    "serve": () => {
    console.log("开发环境配置文件");
    return ({ ...viteBaseConfig, ...viteDevConfig })
    }
    }

    export default defineConfig(({ command, mode }) => {
    /**
    按照正常的执行流程, 在这里是拿不到环境变量的
    涉及到vite.config.js中的配置
    -- root
    -- envDir: 用来配置当前环境变量文件的地址
    既然环境变量的文件可以vite.config.js中的配置自定义
    这里连环境变量文件都没确定呢, 怎么拿环境变量中的数据?
    所以强调 "不会直接注入,要考虑配置冲突问题"
    */

    /**
    不过业务中, 我们确实有在这里使用环境变量的需求
    vite给我们提供了一些补偿机制: 我们可以调用vite的loadEnv来手动确认env文件
    因此可以提前拿到环境变量文件中的数据
    强调下 process.cwd()的作用, 就是得到工程目录, 如 D:\UserDatas\Note\21_Vite\01tiyan
    */
    const env = loadEnv(mode, process.cwd(), "")
    console.log(env); // 查看生效的环境变量

    /**
    当我们调用loadenv的时候,他会做如下几件事:
    1,直接找到.env文件不解释, 并解析其中的环境变量 并放进一个对象里
    2,会将传进来的mode这个变量的值进行拼接: 得到.env.development
    3. 根据我们提供的目录(D:\UserDatas\Note\21_Vite\01tiyan), 去取对应的配置文件并进行解析,并放进一个对象
    4.我们可以理解为
    js const baseEnvConfig=读取.env的配置 const modeEnvConfig=读取env相关配置 const lastEnvConfig = {...baseEnvConfig, ...modeEnvConfig }
    5.最终得到全部的环境变量文件的值
    6.如果是客户端,vite会将对应的环境变量注入到import.meta.env里去
    7.vite做了一个拦截, 他为了防止我们将隐私性的变量直接送进import.meta.env中,所以他做了一层拦截,
    8.如果你的环境变量不是以VITE开头的,他就不会帮你注入到客户端中去, 如果我们想要更改这个前缀,可以去使用envPrefix配置
    */

    return envResolvercommand
    })

    补充一个小知识:

    为什么vite.cong.js可以书写成esmdule的形式,这是因为vite他在读取这个vite.cong.js的时候,会率先node去解析文件语法,如果发现你是esmadule规范, 会直接将你的esmadule规范进行替换变成commonjs规范

再添加一个测试环境

  1. 新增环境变量文件

    ENV_APP_KEY = 120
    ENV_BASE_URL = http://测试

  2. 在脚本中配置mode

    {
    "scripts": {
    "dev": "vite",
    "build": "vite build",
    "test": "vite --mode test" // 新增
    }
    }

  3. 启动项目

相关推荐
Dxy12393102162 小时前
Python对图片进行加密,js前端进行解密
前端·javascript·python
支付宝体验科技2 小时前
SEE Conf 2025 来啦,一起探索 AI 时代的用户体验与工程实践!
前端
江城开朗的豌豆2 小时前
路由对决:Vue Router vs React Router,谁是你的菜?
前端·javascript·react.js
建群新人小猿2 小时前
客户标签自动管理:标签自动化运营,画像持久保鲜
android·java·大数据·前端·git
代码79722 小时前
【无标题】使用 Playwright 实现跨 Chromium、Firefox、WebKit 浏览器自动化操作
运维·前端·深度学习·华为·自动化
Zuckjet_2 小时前
第 5 篇:WebGL 从 2D 到 3D - 坐标系、透视与相机
前端·javascript·3d·webgl
天蓝色的鱼鱼2 小时前
高效开发之选:六款优秀的Vue3开源后台模板全面解析
前端·vue.js
江城开朗的豌豆2 小时前
Redux工作流大揭秘:数据管理的"三重奏"
前端·javascript·react.js
大鱼前端2 小时前
告别 Electron 的臃肿:用 Tauri 打造「轻如鸿毛」的桌面应用
前端