需求描述

  • 前段时间有这样的一个需求:
  • 笔者有一个项目,在启动或者打包的时候
  • 需要根据一些实际情况,去选择展示那个视图
  • 就是我们在项目启动或者打包的时候,需要注入一个全局变量(保存在.env.development或.env.production文件中)通过命令行npm run dev的方式
  • 一般来说,vue-router就可以实现这个需求
  • 但是,某些情况下,这个需求不太适合用vue-router去实现
  • 所以,笔者分享这篇文章,给到一个思路和示例
  • 完整代码附上,在文末的github上

效果图

第一步,在启动项目的时候命令行传参,修改package.json

{
  "name": "build",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "de": "node ./choose.js",
    "pr": "node ./choose.js"
  },
  "dependencies": { ... },
  "devDependencies": { ... }
}
  • 也就是说,当执行npm run de这个脚本的时候,会驱动node去执行choose.js这个文件脚本js文件
  • 当然了,这个文件在和package.json在同一目录下(根目录)

第二步 编写脚本choose.js文件

想要编写好一个choose.js文件,我们需要掌握以下的前置知识

前置知识child\_process

  • 说到child_process模块,就不得不提process模块
  • 大家类比一下理解即可
  • 前者是 Node.js 中的全局对象,这个对象提供了与当前 Node.js 进程进行交互的各种信息和控制能力。
  • 后者是一个 Node.js 内置模块,该模块允许 Node.js 创建新的子进程,实现多进程编程
  • 所以,我们可以使用child\_process来启动一个vite项目

即为:

  • 假设此文件和vite项目在同一根目录,叫做c.js
  • 那么,我们执行node c.js就可以把同级目录的vite项目跑起来了
  • 相当于执行了,npm run dev
  • 因为前者也是驱动vite运行项目的("dev": "vite",
  • 默认package.json文件如下:
  "scripts": {
    "start": "npm run dev",
    "dev": "vite",
    "build:prod": "vite build",
    "build:stage": "vite build --mode staging",
    "preview": "vite preview",
  }

我们直接改动手动地,通过node的child\_process模块驱动vite项目跑起来

// c.js
import { execSync } from 'child_process'

// 启动开发环境
execSync(`vite --host`, { stdio: 'inherit' });

// 启动生产环境
execSync(`vite build`, { stdio: 'inherit' });
execSync可以执行外部命令,如执行vite的命令

脚本choose.js文件

  • 有了上述前置知识,我们就可以编写出以下脚本
  • 拿到命令行输入的参数比如
  • npm run de -- 1 或者 npm run de -- 2 或者 npm run de -- 3
  • 根据传进来的 1 或者 2 或者 3
  • 去选择对应的视图单位
  • 注意,这里要把命令行传递进来参数,存一份到.env.development文件中(开发环境,生产环境.env.production)
  • 我们直接写入到文件中,这样在任何一个.vue文件中都可以访问到这个命令行参数变量了
  • 比如:fs.writeFileSync('./.env.development', VITE_UNIT = ${params})
  • 注意,命令行传参的格式,否则Vite接受不到
  • npm run de -- xxx ,才能接收到这个xxx参数(let params = process.argv.at(-1)
  • npm run de -- xxx ,才能接收到这个xxx参数(let params = process.argv.at(-1)
  • npm run de -- xxx ,才能接收到这个xxx参数(let params = process.argv.at(-1)
import process from 'process'
import { execSync } from 'child_process'
import fs from 'fs'

// 假设校验只有三个单元视图
const checkArr = ['1', '2', '3']

// 获取命令行参数
let params = process.argv.at(-1) 
if (!checkArr.includes(params)) {
    throw new Error('参数不对') // process.exit(1); // 遇到错误退出
}

if (process.env.npm_lifecycle_event == 'de') {
    fs.writeFileSync('./.env.development', `VITE_UNIT = ${params}`)
    execSync(`vite --host`, { stdio: 'inherit' });
} else if (process.env.npm_lifecycle_event == 'pr') {
    fs.writeFileSync('./.env.production', `VITE_UNIT = ${params}`)
    execSync(`vite build`, { stdio: 'inherit' });
}

.env.development和.env.production文件

  • .env.development和.env.production都是环境变量文件
  • 一个开发,一个生产
  • 这里直接存放对应值就行了
  • 如:VITE\_UNIT = 1
  • 我们通过fs模块,直接往这个文件中写入内容:
  • fs.writeFileSync('./.env.development', 'VITE_UNIT = ${params}')
  • .env.development.env.production有内容后,
  • 这样的话,就可以在任意的.vue文件中使用这个变量了

访问vite环境变量文件中的变量数据

直接:import.meta.env.VITE_UNIT,如下:

<template>
  <div>{{ unit }}</div>
</template>

<script setup>
let unit = import.meta.env.VITE_UNIT;
</script>
  • 这里,笔者去把一些用到的html文件存放在
  • public文件夹unitView文件夹
  • 如下图

  • 这样的话,就可以启动的时候,根据存放在.env.development文件中的变量VITE_UNIT使用对应视图了
  • 比如,当我启动项目的时候,执行命令是:npm run de -- 2
  • 代表着开发环境,我要查看视图2
  • 这个时候,choose.js脚本会把传递的参数2写入到.env.development文件中,如下图:
  • 最后,就可以通过import.meta.env.VITE_UNIT去动态使用了
<template>
  <div>
    <div v-html="htmlContent"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";

// 获取传递进来的unit参数
let unit = import.meta.env.VITE_UNIT;

// 定义一个响应式变量来存储HTML内容
const htmlContent = ref("");

onMounted(async () => {
  try {
    // 使用fetch API读取publick文件架下unitView中的html视图文件
    const response = await fetch(`/unitView/${unit}.html`);
    if (response.ok) {
      // 将响应内容转换为文本
      const html = await response.text();
      // 赋值响应式变量
      htmlContent.value = html;
    } else {
      console.error("error");
    }
  } catch (error) {
    console.error("Error fetching HTML file:", error);
  }
});
</script>

这样的话,就可以实现相应效果了

补充:使用http-server本地访问打包好的dist文件夹

  • 我们打包后的dist文件夹的入口文件,不能双击打开查看项目
  • 关于Vite打包dist后的index.html双击无法访问参考文章
  • vite 打包本地文件无法直接打开, file 类型 URL 引发跨域等问题探讨
  • https://blog.csdn.net/qq_34727886/article/details/136163494
  • 这个时候,我们可以使用http-server快速启动一个服务(不用部署在服务器上)
// 打开cmd,全局安装http-server
npm install -g http-server

// 进入指定打包的目录
cd dist

// cmd中输入启动服务
http-server

如下图:

这样的话,我们在本地,也能直接查看到打包好的dist文件夹的内容效果

完整代码


水冗水孚
1.1k 声望595 粉丝

每一个不曾起舞的日子,都是对生命的辜负