需求描述
- 前段時間有這樣的一個需求:
- 筆者有一個項目,在啓動或者打包的時候
- 需要根據一些實際情況,去選擇展示那個視圖
- 就是我們在項目啓動或者打包的時候,需要注入一個全局變量(保存在.env.development或.env.production文件中)通過命令行npm run dev的方式
- 一般來説,vue-router就可以實現這個需求
- 但是,某些情況下,這個需求不太適合用vue-router去實現
- 所以,筆者分享這篇文章,給到一個思路和示例
- 完整代碼附上,在文末的github上
效果圖
第一步,在啓動項目的時候命令行傳參,修改package.json
- 實際上,類似的功能效果筆者之前分享過一篇文章
- 《效能工具之node在項目中的應用(二)《以開發環境多後端服務切換問題為例》》
- 那個是使用的 inquirer 的npm包
- 相比較而言,本篇文章,不使用包
- 即用Vue和Vite自帶功能的實現之
- 首先,我們去自定義腳本
"de": "node ./choose.js",實現啓動或者打包 - (這裏刪除了默認的
npm run dev腳本即:"dev": "vite",),如下:
{
"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文件夾的內容效果
完整代碼
- 在筆者的github倉庫:https://github.com/shuirongshuifu/build-choose
- 建議大家pull下項目,跑起來操作一下,更好理解