阿里云主机折上折
  • 微信号
Current Site:Index > Multi-page application configuration issue

Multi-page application configuration issue

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

Multi-Page Application Configuration Issues

Vite.js, as a modern front-end build tool, natively supports Single-Page Applications (SPA). However, in real-world projects, there are often scenarios where configuring a Multi-Page Application (MPA) is required. A multi-page application refers to a project containing multiple independent HTML entry files, with each page having its own JavaScript and CSS resources.

Basic Directory Structure

A typical MPA project directory structure is as follows:

project-root/
├── public/
│   ├── favicon.ico
│   └── global-assets/
├── src/
│   ├── page1/
│   │   ├── index.html
│   │   ├── main.js
│   │   └── style.css
│   ├── page2/
│   │   ├── index.html
│   │   ├── main.js
│   │   └── style.css
│   └── shared/
│       ├── components/
│       └── utils/
└── vite.config.js

Core Vite Configuration Solution

In vite.config.js, you need to specify multiple page entries using build.rollupOptions.input:

import { defineConfig } from 'vite'
import path from 'path'

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        main: path.resolve(__dirname, 'src/page1/index.html'),
        about: path.resolve(__dirname, 'src/page2/index.html'),
        contact: path.resolve(__dirname, 'src/page3/index.html')
      }
    }
  }
})

Dynamic Entry Configuration

When there are many pages, it is recommended to use dynamic scanning to generate entry configurations:

import fs from 'fs'
import path from 'path'

function getPageEntries(dir) {
  const pagesDir = path.resolve(__dirname, dir)
  return fs.readdirSync(pagesDir).reduce((entries, page) => {
    const pagePath = path.join(pagesDir, page)
    const indexPath = path.join(pagePath, 'index.html')
    
    if (fs.existsSync(indexPath)) {
      entries[page] = indexPath
    }
    return entries
  }, {})
}

export default defineConfig({
  build: {
    rollupOptions: {
      input: getPageEntries('src/pages')
    }
  }
})

HTML Template Handling

Each page's HTML must correctly reference resources, and Vite will automatically handle resource paths:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
  <!-- Correctly reference CSS -->
  <link rel="stylesheet" href="./main.css">
</head>
<body>
  <div id="app"></div>
  <!-- Correctly reference JS -->
  <script type="module" src="./main.js"></script>
</body>
</html>

Public Code Splitting

To avoid duplicate bundling of public dependencies, configure code splitting:

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor'
          }
          if (id.includes('src/shared/')) {
            return 'shared'
          }
        }
      }
    }
  }
})

Development Server Configuration

Ensure the correct pages are returned in the development environment:

export default defineConfig({
  server: {
    open: '/page1/index.html' // Default page to open
  }
})

Environment Variable Handling

Different pages may require different environment variables:

// vite.config.js
export default defineConfig({
  define: {
    __APP_ENV__: JSON.stringify(process.env.APP_ENV || 'development')
  }
})

// Usage in pages
console.log('Current env:', __APP_ENV__)

Routing Matching Issues

Pay special attention to routing configuration in MPA:

// src/page1/main.js
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory('/page1/'), // Note the base path
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

Static Resource References

Public static resources should be placed in the public directory, while page-specific resources should be in their respective directories:

public/
  images/
    logo.png  # Globally available, referenced directly via /images/logo.png
src/
  page1/
    assets/
      banner.jpg  # Page-specific, referenced via relative paths

Build Output Optimization

Customize the build output directory structure:

export default defineConfig({
  build: {
    outDir: 'dist',
    rollupOptions: {
      output: {
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
      }
    }
  }
})

Pre-Rendering Integration

Integrate with vite-plugin-ssr for partial page pre-rendering:

import ssr from 'vite-plugin-ssr'

export default defineConfig({
  plugins: [
    ssr({
      prerender: {
        partial: true,
        pages: ['page1', 'page2']
      }
    })
  ]
})

Hot Module Replacement (HMR) Issues

HMR may fail in multi-page development; check the following:

export default defineConfig({
  server: {
    watch: {
      usePolling: true,
      interval: 100
    }
  }
})

Proxy Configuration Differences

Different pages may require different API proxies:

export default defineConfig({
  server: {
    proxy: {
      '/page1-api': {
        target: 'http://localhost:3001',
        rewrite: path => path.replace(/^\/page1-api/, '')
      },
      '/page2-api': {
        target: 'http://localhost:3002',
        rewrite: path => path.replace(/^\/page2-api/, '')
      }
    }
  }
})

Custom Page Builds

Apply different build options for specific pages:

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        entryFileNames: chunkInfo => {
          return chunkInfo.name.includes('admin') 
            ? 'admin/js/[name]-[hash].js' 
            : 'assets/js/[name]-[hash].js'
        }
      }
    }
  }
})

Multi-Framework Hybrid Projects

Use both Vue and React in one project:

import vue from '@vitejs/plugin-vue'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [
    vue({
      include: [/\.vue$/, /\.md$/],
      exclude: ['src/react-pages/**']
    }),
    react({
      include: 'src/react-pages/**'
    })
  ]
})

Deployment Path Issues

Handle base paths for different environments:

export default defineConfig(({ mode }) => {
  const base = mode === 'production' 
    ? 'https://cdn.example.com/project/' 
    : '/'
    
  return {
    base,
    build: {
      assetsDir: 'static'
    }
  }
})

Performance Monitoring Integration

Add performance monitoring for different pages:

// vite.config.js
export default defineConfig({
  plugins: [
    {
      name: 'inject-analytics',
      transformIndexHtml(html, { filename }) {
        const pageName = path.basename(path.dirname(filename))
        return html.replace(
          '</head>',
          `<script>trackPageView('${pageName}')</script></head>`
        )
      }
    }
  ]
})

Multi-Theme Support

Implement theme switching based on pages:

// vite.config.js
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @import "./src/themes/default.scss";
          @import "./src/themes/${process.env.THEME || 'light'}.scss";
        `
      }
    }
  }
})

Type Checking Configuration

Configure TypeScript path aliases for multi-page projects:

import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths()],
  resolve: {
    alias: {
      '@components': path.resolve(__dirname, 'src/shared/components')
    }
  }
})

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

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.