Nuxt3 ssr build/dev时区分不同的环境

发布于:2025-03-14 ⋅ 阅读:(14) ⋅ 点赞:(0)

package.json

  "scripts": {
    "build": "nuxt build --dotenv .env.prod",
    "build:dev": "nuxt build --dotenv .env.dev",
    "postbuild": "mv -f .output ./dist/.output", //支持自定义文件名
    "dev": "nuxt dev --dotenv .env.dev",
    "dev:prod": "nuxt dev --dotenv .env.prod",
  }

.env.dev

VITE_BASE_PC_URL=http://pc.dev.com/api
VITE_BASE_MOBILE_URL=http://m.dev.com/api
VITE_API_KEY=675f3e7464bdfxxx
VITE_API_IV=2fd454e95cde8xxx

.env.prod

VITE_BASE_PC_URL=http://pc.prod.com/api
VITE_BASE_MOBILE_URL=http://m.prod.com/api
VITE_API_KEY=675f3e7464bdfxxx
VITE_API_IV=2fd454e95cde8xxx

nuxt.config.ts

export default defineNuxtConfig({
  runtimeConfig: {
	// 私有环境变量,仅服务端可访问
    apiKey: process.env.VITE_API_KEY,
    apiIV: process.env.VITE_API_IV,
    pcURL: process.env.VITE_BASE_PC_URL,
    mobileURL: process.env.VITE_BASE_MOBILE_URL,
  }
})

plugins/axiosPlugin.ts(服务端/客户端使用runtimeConfig.pcURL)

import axios from 'axios';
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, AxiosRequestHeaders } from 'axios';
import CryptoJS from 'crypto-js';

import { defineNuxtPlugin } from '#app';

// 加密函数
function encrypt(plainText: string, key: string, iv: string): string {
    const keyHex = CryptoJS.enc.Utf8.parse(key);
    const ivHex = CryptoJS.enc.Utf8.parse(iv);
    const encrypted = CryptoJS.AES.encrypt(plainText, keyHex, {
        iv: ivHex,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}

export default defineNuxtPlugin(() => {
    const runtimeConfig = useRuntimeConfig();
    const deviceType = useDeviceType(); 
    const baseURL = deviceType?.type.value === 'pc' ? (runtimeConfig?.pcURL || process.env.VITE_BASE_PC_URL) : (runtimeConfig?.mobileURL || process.env.VITE_BASE_MOBILE_URL);
    const axiosInstance: AxiosInstance = axios.create({
        baseURL: baseURL,
        timeout: 30000, // 请求超时时间
    });

    let customHeadersConfig: Record<string, string> = {};

    // 请求拦截器
    axiosInstance.interceptors.request.use(
        (config: InternalAxiosRequestConfig) => {
            if (!config.headers) {
                config.headers = {} as AxiosRequestHeaders;
            }

            config.headers['Content-Type'] = 'application/json;charset=UTF-8';
            const plainText = String(new Date().getTime());
            const apiKey = (runtimeConfig.apiKey || process.env.VITE_API_KEY);
            const apiIV = (runtimeConfig.apiIV || process.env.VITE_API_IV);
            // 检查环境变量是否定义
            if (!apiKey || !apiIV) {
                throw new Error('API 密钥或 IV 未定义');
            }
            const encryptedText = encrypt(plainText, apiKey, apiIV);
            config.headers['Token'] = encryptedText;

            for (let key in customHeadersConfig) {
                // config.headers[key] = customHeadersConfig[key];
                if (customHeadersConfig[key] === '') {
                    delete config.headers[key];
                } else {
                    config.headers[key] = customHeadersConfig[key];
                }
            }

            return config;
        },
        (error) => {
            console.error('请求错误:', error.message || '未知错误');
            return Promise.reject(error);
        }
    );

    // 响应拦截器
    axiosInstance.interceptors.response.use(
        (response: AxiosResponse) => response.data,
        (error) => {
            if (error.response) {
                console.log(`错误信息: ${error.response?.data?.message}`)
                // switch (error.response.status) {
                //     case 400:
                //         console.log('未授权,请访问最新');
                //         break;
                //     case 401:
                //         console.log('未授权,请登录');
                //         break;
                //     case 404:
                //         console.log('请求资源不存在');
                //         break;
                //     case 500:
                //         console.log('服务器内部错误');
                //         break;
                //     default:
                //         console.log(`未知错误: ${error.response.status}`);
                //         break;
                // }
            } else {
                console.log(`网络错误或其他错误: ${error}`);
            }
            return Promise.reject(error);
        }
    );

    // 提取请求类型检查逻辑
    function handleRequestType(url: string, params: any, type: string, customConfig?: {}) {
        customHeadersConfig = customConfig || {};
        if (type.toUpperCase() === 'GET') {
            return axiosInstance.get(url, { params, ...customConfig });
        } else if (type.toUpperCase() === 'POST') {
            return axiosInstance.post(url, params, customConfig);
        } else {
            throw new Error('不支持的请求类型');
        }
    }

    return {
        provide: {
            customRequest: (url = '', params = {}, type = 'POST', customConfig?: {}) => {
                return handleRequestType(url, params, type, customConfig);
            },
            apiAxios: axiosInstance
        }
    }
});