阿里云主机折上折
  • 微信号
Current Site:Index > Environment variables and mode management

Environment variables and mode management

Author:Chuan Chen 阅读数:13764人阅读 分类: 构建工具

Project Configuration and Basic Usage

The Vite.js configuration file vite.config.js is located in the project root directory and customizes build behavior by exporting a configuration object. The basic configuration structure is as follows:

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    port: 3000,
    open: true
  },
  build: {
    outDir: 'dist'
  }
})

Configuration items are mainly divided into several categories:

  • plugins: Configures the plugins to be used
  • server: Development server options
  • build: Production build options
  • resolve: Module resolution options
  • css: CSS-related configurations

Common configuration example:

// More complete configuration example
export default defineConfig({
  base: '/my-app/', // Deployment base path
  publicDir: 'public', // Static resources directory
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`
      }
    }
  }
})

Environment Variables and Mode Management

Vite uses dotenv to load environment variables from .env files in the project root directory. Naming rules for environment variable files:

  • .env: Loaded in all cases
  • .env.local: Local overrides, ignored by git
  • .env.[mode]: Loaded only in the specified mode
  • .env.[mode].local: Local overrides for the specified mode

Basic usage:

# .env.development
VITE_API_URL=https://dev.api.example.com
VITE_DEBUG=true
# .env.production
VITE_API_URL=https://api.example.com
VITE_DEBUG=false

Accessing environment variables in code:

console.log(import.meta.env.VITE_API_URL)

Mode is an important concept in Vite, with three default modes:

  • development: Used for vite or vite dev
  • production: Used for vite build
  • test: Used for vite test

Custom modes can be specified using the --mode option:

vite build --mode staging

Correspondingly, create a .env.staging file:

# .env.staging
VITE_API_URL=https://staging.api.example.com

Advanced Environment Variable Configuration

For more complex environment variable requirements, dynamic configuration can be done in vite.config.js:

export default defineConfig(({ command, mode }) => {
  // Load different environment variables based on the current command and mode
  const env = loadEnv(mode, process.cwd(), '')
  
  return {
    define: {
      __APP_VERSION__: JSON.stringify(env.VITE_APP_VERSION || '1.0.0')
    },
    // Other configurations...
  }
})

Type-safe environment variables can be achieved by creating an env.d.ts file in the src directory:

// src/env.d.ts
interface ImportMetaEnv {
  readonly VITE_API_URL: string
  readonly VITE_APP_TITLE: string
  // More environment variables...
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

Multi-Environment Configuration Practices

Large projects often require managing multiple environment configurations. A practical organizational approach:

├── config/
│   ├── env.development
│   ├── env.staging
│   ├── env.production
│   └── env.test
├── scripts/
│   └── build.js
└── vite.config.js

Custom build script example:

// scripts/build.js
const fs = require('fs')
const { execSync } = require('child_process')

const env = process.argv[2] || 'production'
const envFile = `./config/env.${env}`

if (!fs.existsSync(envFile)) {
  console.error(`Environment config file does not exist: ${envFile}`)
  process.exit(1)
}

// Copy environment file to project root directory
fs.copyFileSync(envFile, '.env')

console.log(`Building with ${env} environment configuration...`)
execSync('vite build', { stdio: 'inherit' })

Usage:

node scripts/build.js staging

Using Environment Variables in HTML

Vite supports using environment variables in index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>%VITE_APP_TITLE%</title>
</head>
<body>
  <div id="app"></div>
  <script>
    console.log('Current environment:', '%MODE%')
  </script>
</body>
</html>

Enable HTML variable substitution in the configuration:

export default defineConfig({
  // ...
  html: {
    inject: {
      injectData: {
        MODE: process.env.NODE_ENV,
        VITE_APP_TITLE: process.env.VITE_APP_TITLE
      }
    }
  }
})

Cross-Project Environment Variable Sharing

For micro-frontend architectures or scenarios requiring shared configurations, create a shared environment variable module:

// shared-config/env.js
const sharedEnv = {
  VITE_COMMON_API: 'https://common.api.example.com',
  VITE_AUTH_DOMAIN: 'auth.example.com'
}

module.exports = {
  development: {
    ...sharedEnv,
    VITE_DEBUG: true
  },
  production: {
    ...sharedEnv,
    VITE_DEBUG: false
  }
}

Use in Vite configuration:

const sharedEnv = require('./shared-config/env.js')

export default defineConfig(({ mode }) => ({
  define: {
    'process.env': {
      ...sharedEnv[mode],
      ...process.env
    }
  }
}))

Security Considerations

Important security considerations for environment variable handling:

  1. Never commit sensitive information to version control
  2. .env.local and *.local files should be added to .gitignore
  3. Client-visible variables must start with VITE_
  4. Server-only variables should use other prefixes and be injected via backend
# Unsafe practice - these variables will be included in client code
API_KEY=123456
DB_PASSWORD=secret

# Safe practice - only VITE_ prefixed variables are exposed to the client
VITE_PUBLIC_KEY=pub_123
VITE_API_URL=/api

Special Handling for Test Environments

Test environments often require special configurations:

// vite.config.js
export default defineConfig(({ mode }) => {
  const isTest = mode === 'test'
  
  return {
    test: {
      environment: 'jsdom',
      globals: true,
      setupFiles: './tests/setup.js',
      // Environment variables specific to testing
      env: {
        VITE_TEST_MODE: 'true',
        VITE_MOCK_API: 'true'
      }
    },
    // Other configurations...
  }
})

Using environment variables in test files:

// tests/example.spec.js
import { describe, it, expect } from 'vitest'

describe('Environment Variable Test', () => {
  it('should be in test mode', () => {
    expect(import.meta.env.VITE_TEST_MODE).toBe('true')
  })
})

Environment Variable Validation

Use libraries like zod to validate environment variables:

// src/utils/env.ts
import { z } from 'zod'

const envSchema = z.object({
  VITE_API_URL: z.string().url(),
  VITE_ENABLE_ANALYTICS: z.boolean().default(false),
  VITE_TIMEOUT: z.number().default(5000)
})

const env = envSchema.parse({
  VITE_API_URL: import.meta.env.VITE_API_URL,
  VITE_ENABLE_ANALYTICS: import.meta.env.VITE_ENABLE_ANALYTICS === 'true',
  VITE_TIMEOUT: Number(import.meta.env.VITE_TIMEOUT)
})

export default env

Dynamic Configuration Loading

For scenarios requiring dynamic configuration loading based on environment:

// src/config/index.js
const env = import.meta.env.MODE

const configs = {
  development: {
    apiBase: 'https://dev.api.example.com',
    analyticsId: 'UA-DEV-123'
  },
  production: {
    apiBase: 'https://api.example.com',
    analyticsId: 'UA-PROD-456'
  },
  test: {
    apiBase: 'http://localhost:3000/mock',
    analyticsId: null
  }
}

export default configs[env] || configs.development

Environment Information in Build Output

Inject environment information into build output:

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        banner: `/*! 
         * App Version: ${process.env.npm_package_version} 
         * Build Date: ${new Date().toISOString()}
         * Environment: ${process.env.NODE_ENV}
         */`
      }
    }
  }
})

Environment-Specific Resource Handling

Load different resources based on environment:

// Dynamically load environment-specific images
function getEnvImage(name) {
  const env = import.meta.env.MODE
  return new URL(`../assets/${env}/${name}.png`, import.meta.url).href
}

// Usage
const logo = getEnvImage('logo')

Environment-Specific Plugin Configuration

Some plugins may require different configurations based on environment:

import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig(({ mode }) => {
  const plugins = []
  
  if (mode === 'production') {
    plugins.push(
      visualizer({
        open: true,
        filename: 'bundle-analysis.html'
      })
    )
  }
  
  return {
    plugins
  }
})

Environment Variables and Proxy Configuration

Common proxy configuration for development environments:

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: import.meta.env.VITE_API_BASE || 'http://localhost:8080',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, '')
      }
    }
  }
})

Environment-Specific CSS Handling

Inject different CSS variables based on environment:

export default defineConfig({
  css: {
    postcss: {
      plugins: [
        require('postcss-preset-env')({
          stage: 3,
          features: {
            'nesting-rules': true
          },
          // Environment-specific CSS variables
          variables: {
            '--env-color': 
              import.meta.env.MODE === 'production' 
                ? '#1a1a1a' 
                : '#4a90e2'
          }
        })
      ]
    }
  }
})

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.