前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vite弃坑指南之:环境文件系统

Vite弃坑指南之:环境文件系统

原创
作者头像
南山种子外卖跑手
发布2022-06-29 18:34:45
1.3K0
发布2022-06-29 18:34:45
举报
文章被收录于专栏:南山种子外卖跑手的专栏

本文为原创文章,引用请注明出处,欢迎大家收藏和分享💐💐

开篇

哈喽大家好,我是外卖仔,老久没静下心来卷文章了。随着Vite在前端工具链中比重越来越大,用的人也越来越多,打算出几期Vite的应用和机制研读,让小伙伴们用起来更得心应手。

文中对于Vite环境文件系统模块介绍主要分两块:

  • 功能理解与如何配置使用(贴点配置代码,搞一两个demo不就完事了😂😂😂)。。。
  • 项目中应用情景的拓展:用我可以,但如何合理使用,如何做到治理项目的效果。

配置Vite环境文件

定义和作用

为了更直观了解Vite的环境,先讲个笔者之前“修仙”时听到的故事:

在「shi」山上,有个小和尚因友拜访而不知如何上山,便请教老和尚小和尚:上山的路崎岖交错,万一有外人来拜访,何以到庙? 老和尚:哈哈隔... 小和尚:... 一会后,老和尚笑着说:干哈呢,这是要到哪座庙? 小和尚心里暗自困恼:好家伙,山上还有多少座庙,不要坑我啊! 老和尚:淡定,我这有个随身听,另外山上每座庙藏宝阁有个U盘,你把U盘插到随身听上,就可播出山下到这座庙的路线了。这随身听我有好几个,给你一个便是。 随后,小和尚接过老和尚的随身听,就跑到后面的屋子拿U盘捣鼓起来。只见开关一按下,随身听便发出声响,它说:

这个故事简单呈现了Vite的多环境功能,其中:

  • 每座庙:等同工程中每个开发环境,如我们所说的开发环境、测试环境;
  • 庙里面的U盘:相当于描述当前环境的配置文件。因为Vite启动服务或打包时支持开发者指定某个环境,并且导入该环境下所有变量做灵活的逻辑定制;
  • 随身听:很好理解,就是环境文件的读取器,告知服务该环境下所有的信息;

指定环境文件启动流程图:

image.png
image.png

参考:《Vite环境与模式》

与环境相关的配置项

envDir#

  • Type:  string
  • Default:  root 设置读取环境文件的路径,默认是跟vite.config文件所在同目录。

envPrefix#

  • Type:  string | string[]
  • Default:  VITE_ 自定义环境变量前缀,默认为VITE_,符合该前缀的环境变量才会暴露在import.meta.env中。

另外官方有安全合规建议:

SECURITY NOTES envPrefix should not be set as '', which will expose all your env variables and cause unexpected leaking of of sensitive information. Vite will throw error when detecting ''.

示例

🌰项目下有2个环境文件:

image.png
image.png

内容如下:

代码语言:shell
复制
# .env.demo
# 透传客户端参数
VITE_NODE_ENV=demo
VITE_OWNER=Outer
VITE_POSITION=.env.demo

# 在envPrefix配置了的前缀参数也可以透传到客户端
MY_PARAM1=自定义参数1
YOUR_PARAM2=自定义参数2

# 私有参数,仅在vite server获取到,
# 假如你的项目包含此类敏感变量。应该将文件添加到你的 .gitignore 中,以避免它们被 git 检入。
MODE_KEY=PRIVATE_KEY_BETA
代码语言:shell
复制
# viteEnv/.env.demo
# 透传客户端参数
VITE_NODE_ENV=demo
VITE_OWNER=Inner
VITE_POSITION=viteEnv/.env.demo

# 在envPrefix配置了的前缀参数也可以透传到客户端
MY_PARAM1=自定义参数1
YOUR_PARAM2=自定义参数2

# 私有参数,仅在vite server获取到,
# 假如你的项目包含此类敏感变量。应该将文件添加到你的 .gitignore 中,以避免它们被 git 检入。
MODE_KEY=PRIVATE_KEY_BETA

接下来是添加启动命令,在package.json设置:

代码语言:json
复制
{
  "scripts": {
    "dev:demo": "vite --mode demo",
  }
}

--mode参数后面带要指定的环境文件,可以忽略文件名的.env.前缀。

❓到这里就有问题了,上面2个环境文件都叫demo,该命令启动后到底用哪一个?

这时候我们就可以通过envDir选项来指定了,因此我们还需要配置一下vite.config.ts:

代码语言:typescript
复制
export default defineConfig(async ({ command, mode }: ConfigEnv) => {
  return {
    envDir: './viteEnv',
    // or
    // envDir: './',
    envPrefix: ['VITE_', 'MY_', 'YOUR_'],
    // 其他配置 ...
  }
});

控制台输出:

image.png
image.png
image.png
image.png

关于envPrefix配置项的用法在上面截图也可以看到了,指定的['VITE_', 'MY_', 'YOUR_']开头的变量都会expose到客户端。

再探源码

其实Vite在启动执行的createServer()方法中,关于读取环境文件这块会执行一个函数叫loadEnv,以下是它的定义。

代码语言:typescript
复制
loadEnv(mode: string, envDir: string, prefixes?: string | string[]): Record<string, string>;

我们可以找到源码看下实现,源码路径packages/vite/src/node/config.ts

image.png
image.png

首先函数接受3个参数:mode名称(也就是启动命令传进去的文件名),和上面我们讲的2个配置项的值。进程会先生成4个默认文件路径保存到envFlies变量,2个mode和2个默认。

接下来会结合envDir寻找目标文件,找到后,使用fs配合prefixes变量前缀数组把对应的变量读取出来放置到env中,最后返回给主线程。

整个过程比较清晰,就是通过fs来取对应的文件变量,返回给进程使用。

环境变量获取

完成时调用

在服务启动后,客户端便可以通过import.meta.env来获取。

见:env variables

运行时调用

其实,我们也可以在Vite启动服务的RUNTIME时机获取环境变量,直接显式调用loadEnv方法即可:

代码语言:typescript
复制
import { defineConfig, ConfigEnv, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import EnvironmentPlugin from 'vite-plugin-environment';
import { fetchEnv } from './server/envUitls';

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }: ConfigEnv) => {
  const env = loadEnv(mode, path.resolve(__dirname, 'viteEnv'), [
    'VITE_',
    'MY_',
    'YOUR_'
  ]);
  console.log('env:', env);

  return {
    envDir: './viteEnv',
    // or
    // envDir: './',
    envPrefix: ['VITE_', 'MY_', 'YOUR_'],
    base: './',
    plugins: [
      vue(),
    ],
    resolve: {
      alias: [
        {
          find: '@',
          replacement: '/src'
        }
      ]
    }
  };
});

控制台输出

image.png
image.png

通过插件透传环境变量

很多情况下,我们的环境变量不仅仅是简单的字符串,而是通过vite服务中二次计算才能得到最终结果,有点类似Vue中computed或React中useMemouseCallback的效果。

像这类非静态的环境变量,我们需要借助插件能力来让它们也能够返回客户端,插件很多,这里推荐vite-plugin-environment,使用大概是这样子的:

You can provide a list of environment variable names to expose to your client code:

代码语言:typescript
复制
import { defineConfig } from 'vite'
import EnvironmentPlugin from 'vite-plugin-environment'

export default defineConfig({
  plugins: [
    EnvironmentPlugin(['API_KEY', 'DEBUG']),
  ],
})

And then use them as:

代码语言:typescript
复制
const apiKey = process.env.API_KEY

在这个基础上,我们还能配合模式文件进行联合判断:

代码语言:typescript
复制
import { defineConfig, ConfigEnv, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import EnvironmentPlugin from 'vite-plugin-environment';
import { fetchEnv } from './server/envUitls';

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }: ConfigEnv) => {
  const env = loadEnv(mode, __dirname);
  const { proxy } = fetchEnv(env.VITE_NODE_ENV); // 设置域名和端口

  return {
    base: './',
    plugins: [
      vue(),
      EnvironmentPlugin({
        PROXY: proxy
      })
    ]
  };
});

const env = loadEnv(mode, __dirname);可以获取.env._local是所有非私密参数,接下来程序可以根据模式参数来计算最终的环境变量,通过插件返回到客户端。

fetchEnv方法可以理解成环境收集器,里面可以写逻辑让环境参数得到统一整合。

收笔

Vite的环境文件系统模块差不多讲到这里了,感谢大家阅览并欢迎纠错,欢迎大家关注本人公众号「是马非马」,一起玩耍起来!🌹🌹

项目传送门

vite-mul-env-learn

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开篇
  • 配置Vite环境文件
    • 定义和作用
      • 与环境相关的配置项
        • envDir#
        • envPrefix#
      • 示例
      • 再探源码
      • 环境变量获取
        • 完成时调用
          • 运行时调用
          • 通过插件透传环境变量
          • 收笔
          • 项目传送门
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档