第二十章:特殊场景与扩展

20.1 Web Worker

基础配置

// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  worker: {
    format: 'es',           // 输出格式
    plugins: () => []       // Worker 专用插件
  }
})

使用 Web Worker

// 创建 Worker 文件
// src/workers/compute.worker.js
self.onmessage = (e) => {
  const result = heavyComputation(e.data)
  self.postMessage(result)
}

function heavyComputation(data) {
  // 耗时计算
  return data.map(x => x * x).reduce((a, b) => a + b, 0)
}

// 主线程中使用
// src/App.vue
<script setup>
import MyWorker from './workers/compute.worker?worker'

const worker = new MyWorker()

worker.onmessage = (e) => {
  console.log('计算结果:', e.data)
}

const runComputation = () => {
  worker.postMessage([1, 2, 3, 4, 5])
}
</script>

Shared Worker

// src/workers/shared.worker.js
const connections = []

self.onconnect = (e) => {
  const port = e.ports[0]
  connections.push(port)
  
  port.onmessage = (e) => {
    // 广播给所有连接
    connections.forEach(conn => {
      conn.postMessage(e.data)
    })
  }
}

// 使用 Shared Worker
const worker = new SharedWorker('/src/workers/shared.worker.js')
worker.port.onmessage = (e) => {
  console.log('收到广播:', e.data)
}
worker.port.postMessage('hello')

Worker 中导入模块

// worker 文件可以正常导入
import { heavyFunction } from './utils'

self.onmessage = (e) => {
  const result = heavyFunction(e.data)
  self.postMessage(result)
}

20.2 WebAssembly (WASM)

加载 WASM 模块

// 方式1:直接导入
import wasmModule from './lib.wasm?init'

const initWasm = async () => {
  const { instance } = await wasmModule({
    env: {
      // 导入的函数
      log: (n) => console.log(n)
    }
  })
  
  const result = instance.exports.add(5, 3)
  console.log('WASM 计算结果:', result) // 8
}

// 方式2:使用 fetch
const loadWasm = async () => {
  const response = await fetch('/lib.wasm')
  const bytes = await response.arrayBuffer()
  const { instance } = await WebAssembly.instantiate(bytes, {
    env: { /* 导入 */ }
  })
  return instance.exports
}

配合 Rust 使用

# 安装 wasm-pack
npm install -g wasm-pack

# 创建 Rust 库
wasm-pack new rust-lib
cd rust-lib
// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    if n <= 1 { n } else { fibonacci(n - 1) + fibonacci(n - 2) }
}
# 构建 WASM
wasm-pack build --target web

# 在 Vite 中使用
npm install ./pkg
import init, { fibonacci } from 'rust-lib'

await init()
console.log(fibonacci(10)) // 55

20.3 PWA 配置

安装和配置

npm install vite-plugin-pwa -D
// vite.config.js
import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
      manifest: {
        name: 'My Vite App',
        short_name: 'ViteApp',
        description: 'Vite PWA App',
        theme_color: '#ffffff',
        icons: [
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          }
        ]
      },
      workbox: {
        globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
        runtimeCaching: [
          {
            urlPattern: /^https:\/\/api\..*/,
            handler: 'NetworkFirst',
            options: {
              cacheName: 'api-cache',
              expiration: {
                maxEntries: 100,
                maxAgeSeconds: 60 * 60 * 24 // 24小时
              }
            }
          }
        ]
      }
    })
  ]
})

更新提示

// 监听更新
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    console.log('新版本已激活')
    // 提示用户刷新
    showUpdateNotification()
  })
}

20.4 多页应用 (MPA)

配置多入口

// vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        about: resolve(__dirname, 'about.html'),
        contact: resolve(__dirname, 'contact.html')
      }
    }
  }
})

多页面结构

project/
├── index.html          # 主页入口
├── about.html          # 关于页面
├── contact.html        # 联系页面
├── src/
│   ├── main.js         # 主页脚本
│   ├── about.js        # 关于页面脚本
│   └── contact.js      # 联系页面脚本
└── vite.config.js

共享资源

// 使用别名共享组件
import { defineConfig } from 'vite'
import { resolve } from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@shared': resolve(__dirname, 'src/shared')
    }
  }
})

// 在任意页面中使用
import Header from '@shared/components/Header.vue'

20.5 静态站点生成 (SSG)

使用 vite-plugin-ssr

npm install vite-plugin-ssr -D
// vite.config.js
import ssr from 'vite-plugin-ssr'

export default defineConfig({
  plugins: [ssr()]
})

配置 SSG

// pages/index.page.js
export default {
  // 页面组件
  Page: () => import('./Index.vue'),
  
  // 数据获取
  async onBeforeRender() {
    const data = await fetchData()
    return {
      pageContext: {
        data
      }
    }
  }
}

20.6 Electron 集成

使用 vite-plugin-electron

npm install vite-plugin-electron -D
// vite.config.js
import electron from 'vite-plugin-electron'

export default defineConfig({
  plugins: [
    electron({
      entry: 'electron/main.js'
    })
  ]
})

Electron 主进程

// electron/main.js
import { app, BrowserWindow } from 'electron'

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // 开发环境
  if (process.env.NODE_ENV === 'development') {
    win.loadURL('http://localhost:5173')
    win.webContents.openDevTools()
  } else {
    win.loadFile('dist/index.html')
  }
}

app.whenReady().then(createWindow)

20.7 自定义插件开发

基础插件结构

// my-plugin.js
export default function myPlugin(options = {}) {
  const virtualModuleId = 'virtual:my-module'
  const resolvedVirtualModuleId = '\0' + virtualModuleId

  return {
    name: 'vite-plugin-my',
    
    // 配置解析前钩子
    config(config, env) {
      console.log('配置:', config, env)
      // 返回部分配置
      return {
        define: {
          __MY_PLUGIN__: JSON.stringify(options)
        }
      }
    },
    
    // 解析模块
    resolveId(id) {
      if (id === virtualModuleId) {
        return resolvedVirtualModuleId
      }
    },
    
    // 加载模块
    load(id) {
      if (id === resolvedVirtualModuleId) {
        return `export const version = '${options.version}'`
      }
    },
    
    // 转换代码
    transform(code, id) {
      if (id.endsWith('.vue')) {
        // 处理 Vue 文件
        return code.replace(/__VERSION__/g, options.version)
      }
    },
    
    // 构建结束
    buildEnd() {
      console.log('构建完成')
    }
  }
}

使用插件

// vite.config.js
import myPlugin from './my-plugin'

export default defineConfig({
  plugins: [
    myPlugin({
      version: '1.0.0'
    })
  ]
})

20.8 全局变量注入

// vite.config.js
export default defineConfig({
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
    __BUILD_TIME__: Date.now(),
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
  }
})

20.9 环境变量高级用法

多环境配置

// .env.development
VITE_API_URL=http://localhost:3000
VITE_DEBUG=true

// .env.production
VITE_API_URL=https://api.example.com
VITE_DEBUG=false

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

自定义环境变量模式

// package.json
{
  "scripts": {
    "dev": "vite",
    "build:staging": "vite build --mode staging"
  }
}

20.10 跨域代理配置

// vite.config.js
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
        configure: (proxy, options) => {
          proxy.on('error', (err, req, res) => {
            console.log('代理错误:', err)
          })
        }
      },
      '/ws': {
        target: 'ws://localhost:3000',
        ws: true  // WebSocket 代理
      }
    }
  }
})

20.11 资源处理扩展

SVG 组件化

npm install vite-plugin-svg-loader -D
// vite.config.js
import svgLoader from 'vite-plugin-svg-loader'

export default defineConfig({
  plugins: [svgLoader()]
})

// 在组件中使用
import Icon from './icon.svg?component'

Markdown 支持

npm install vite-plugin-md -D
// vite.config.js
import Markdown from 'vite-plugin-md'

export default defineConfig({
  plugins: [Markdown()]
})

// 导入 Markdown 文件
import Readme from './README.md'

20.12 兼容性处理

Legacy 插件

npm install @vitejs/plugin-legacy -D
// vite.config.js
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11'],
      additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
      renderLegacyChunks: true
    })
  ]
})

本章小结

Vite 通过丰富的插件生态支持各种特殊场景:

  • Web Worker 处理 CPU 密集型任务
  • WASM 集成高性能计算
  • PWA 提供离线能力
  • MPA 多页面架构
  • Electron 桌面应用
  • 自定义插件扩展功能

根据项目需求选择合适的扩展方案,充分发挥 Vite 的灵活性。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐