likes
comments
collection
share

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

作者站长头像
站长
· 阅读数 9

前言

上一章前端构建工具vite进阶系列(一) -- vite比webpack的优势与开箱即用中,我们稍微体验了一下使用vite来打包资源,并且可以解决非相对/绝对路径的资源引入导致的报错问题,那么这一章我们来讲讲vite的本身处理。vite之所以能够比webpack快几十倍,依赖预构建起到了很大的作用,那么这一章讲讲依赖预构建与环境变量相关的事情吧。

为什么要依赖预构建

  1. CommonJS 和 UMD 兼容性:  开发阶段中,Vite 的开发服务器将所有代码视为原生 ES 模块。因此,Vite 必须先将作为 CommonJSUMD 发布的依赖项转换为 ESM

    当转换 CommonJS 依赖时,Vite 会执行智能导入分析,这样即使导出是动态分配的(如 React),按名导入也会符合预期效果:

    // 符合预期
    import React, { useState } from 'react'
    
  2. 性能:  Vite 将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能。

    一些包将它们的 ES 模块构建作为许多单独的文件相互导入。例如,lodash-es 有超过 600 个内置模块!当我们执行 import { debounce } from 'lodash-es' 时,浏览器同时发出 600 多个 HTTP 请求!尽管服务器在处理这些请求时没有问题,但大量的请求会在浏览器端造成网络拥塞,导致页面的加载速度相当慢。

    通过预构建 lodash-es 成为一个模块,我们就只需要一个 HTTP 请求了!

vite是怎么解决路径问题的

vite启动的时候,会执行bin目录下的vite.js文件,在这个文件里面我们会看到获取了当前的电脑的绝对路径,如果不包含node_module路径,就需要引入source-map-support这个包来处理,如果是相对路径则会进行路径补全,当然在dev环境下都会有node_module路径,在prod环境下,vite会使用rollup来进行打包。

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理 进行路径补全当然可以解决这个问题,但是vite一想,我既然是基于ESM规范的,那么如果用户使用了CommonJS规范的导出包,那我还不是需要编译成ESM吗?所以vite就借助了esbuild库(esbuild是一个对js语法处理的库),对用户使用的CommonJS规范的库进行了转换成ESM,并且输入在了node_module/.vite/deps目录下。

  • 一来可以统一ESM模块,统一模块规范。
  • 二来可以解决路径问题,方便路径重写。
  • 三来可以优化http多包传输的性能问题。

为什么原生ESM不支持node_module?:因为如果支持的话,那将会带来非常大的网络性能问题,对于ESM里面具有其他依赖的ESM来说,那浏览器将会无限制的请求依赖库,举个例子当我们使用lodash-es库的时候,我们把不进行预构建的模块写在vite.config.json里面。

export default {
    optimizeDeps:{
        exclude:["lodash-es"] // 当遇到lodash-es的时候 不进行预构建
    }
}

那么就会产生如下多的数不清的文件。

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

所以vite能够把ESM库中的所有三方依赖全部集成,只生成一个或者多个文件(多个文件但是不是类似于上面这么多。。。)这才能够说明可以用来优化http多包传输的性能问题,所以这上面也是vite的依赖预构建做的事情。

配置文件相关处理

  1. 语法提示的支持
    • 类型注解 /** @type import('vite').UserConfig*/

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理 - defineConfig

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

  1. 环境配置文件处理
import {defineConfig} from 'vite';
import viteBaseConfig from './vite-base-config.js'
import viteDevConfig from './vite-dev-config.js'
import viteProdConfig from './vite-prod-config.js'

const handleEnv = {
  "build":()=>{
    // build的时候做的事情
    return Object.assign({}, viteProdConfig, viteBaseConfig)
  },
  "serve":()=>{
    // serve的时候做的事情
    return Object.assign({}, viteDevConfig, viteBaseConfig)
  }
}
export default defineConfig(({command})=>{
  console.log(handleEnv[command]())
  return handleEnv[command]()
})
  1. 环境变量处理
  • vite对环境变量的处理是借助于第三方库dotenv实现的,执行命令的时候,dotenv会去读取.env文件,然后注入到process对象当中。当然用户配置大于默认,我们可以在vite.config.js里面配置envDir指定环境变量的文件地址

  • 为什么nodejs可以读取ESM规范的vite.config.js呢?

    • vite在读取vite.config.js文件的时候,如果遇到ESM规范,node会去解析成CommonJS规范。
    • 如何解析:读取文件的结果就是字符串,通过替换importrequire的方式来进行规范转换。
  • 通过命令来获取环境参数

export default defineConfig(({command, mode})=>{
  // mode 为执行指令环境
  // npm run serve => mode:development
  // npm run build => mode:production
  console.log(handleEnv[command]())
  return handleEnv[command]()
})

通过上述代码中的mode,我们知道了只要我们敲命令,mode会自动获取到,所以我们可以手动设置.env,vite给我们提供了一个loadEnv方法来获取环境变量。

export default defineConfig(({command, mode})=>{
  // mode 为执行指令环境
  // npm run serve => mode:development
  // npm run build => mode:production
  
  const env = loadEnv(mode, process.cwd(), '')
  console.log('/////env', env)
  console.log(handleEnv[command]())
  return handleEnv[command]()
})

我们新建.env.production.env.development文件,分别注入ENV = 10011ENV = 10010

// .env.production
ENV = 10011
BASE_URL = 'http://dev.api'

// .env.development
ENV = 10010
BASE_URL = 'https://api'

所以 npm run serve 的结果是:

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理 所以 npm run build 的结果是:

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

  • import.meta.env 这个是官方提供的一个变量对象,他能够有效的读取到当前环境变量,我们先来看一看官网。

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理 可以在代码中获取到import.meta.env的内容,如果要想获取到环境变量,则需要命名为VITE_*,为前缀的值,否则vite访问不到,原因是因为vite做了一层拦截,把没有带VITE前缀的变量,不会注入到import.meta.env中。

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理 当然这是默认的,一切要遵循配置大于默认,所以我们可以在vite.config.js中去定制envPrefix:"ENV_",才可以。

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

  • 多种环境配置
    • 在实际项目中肯定会有测试环境预发布环境等,那这里我们就按照prepare来指定一下预发布环境。
    • .env.prepare文件。
    ENV_PREPARE = 10012
    ENV_BASE_URL = https://prepare.api/
    

前端构建工具vite进阶系列(二) -- vite的依赖预构建与配置文件相关处理

总结

本文主要讲解了vite的预构建与config文件、环境变量的处理,我们看到了其实跟webpack很类似,在这里我们也预留了问题,dotenv是怎么去处理环境变量的?ESM是怎么去变成CommonJS的,这些问题后期源码阅读的时候,都会得到解答,请戳 >>> 前端构建工具vite进阶系列(三) -- 静态资源与css模块化的处理