Project Architecture Design
SPA and Multi-Page Application Architecture Design
SPA Architecture Implementation:
// nuxt.config.js
export default {
ssr: false, // Disable server-side rendering
target: 'client', // Client-side rendering target
router: {
mode: 'history', // HTML5 History mode
base: '/app/' // Custom base path
},
// Disable unnecessary SSR features
render: {
resourceHints: false,
ssr: false
}
}Multi-Page Application Architecture Implementation:
// nuxt.config.js
export default {
ssr: true, // Enable server-side rendering
target: 'server', // Server-side rendering target
router: {
extendRoutes(routes, resolve) {
// Add independent page routes
routes.push({
name: 'about',
path: '/about',
component: resolve(__dirname, 'pages/about.vue')
})
}
},
// Multi-entry configuration (via layout system)
layout: {
default: '~/layouts/default.vue',
about: '~/layouts/about.vue' // Special page layout
}
}Hybrid Architecture Design:
// nuxt.config.js
export default {
ssr: true,
target: 'static', // Static generation
router: {
// Dynamic route SSR
routes: [
{ path: '/user/:id', component: '~/pages/user/_id.vue' },
// Static page SPA
{ path: '/dashboard', component: '~/pages/dashboard.vue', ssr: false }
]
}
}Modularization and Componentization Design
Modular Architecture Example:
modules/
├── auth/ # Authentication module
│ ├── index.ts # Module entry
│ ├── composables/ # Composables
│ ├── components/ # Module components
│ └── store/ # Module state
├── payment/ # Payment module
│ ├── gateway.ts # Payment gateway integration
│ └── components/ # Payment-related components
└── ui/ # UI base module
├── buttons/ # Button components
└── modals/ # Modal componentsComponent Design Specification:
<!-- components/BaseButton.vue -->
<template>
<button
:class="['base-button', `variant-${variant}`]"
:disabled="disabled"
@click="handleClick"
>
<slot></slot>
</button>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
variant: {
type: String,
default: 'primary',
validator: (v: string) => ['primary', 'secondary', 'text'].includes(v)
},
disabled: Boolean
})
const emit = defineEmits(['click'])
const handleClick = (event: MouseEvent) => {
if (!props.disabled) {
emit('click', event)
}
}
</script>State Management Architecture
Pinia Modular Design:
// stores/user.ts
export const useUserStore = defineStore('user', {
state: () => ({
profile: null as UserProfile | null,
token: ''
}),
getters: {
isAuthenticated: (state) => !!state.token
},
actions: {
async login(credentials: LoginCredentials) {
const { data } = await useApi().post('/auth/login', credentials)
this.token = data.value.token
this.profile = data.value.user
}
}
})
// stores/index.ts (aggregate all stores)
export const useStore = () => ({
user: useUserStore(),
cart: useCartStore()
})Vuex Modular Design:
// store/modules/user.ts
export default {
namespaced: true,
state: () => ({
profile: null,
token: ''
}),
mutations: {
SET_TOKEN(state, token: string) {
state.token = token
}
},
actions: {
async login({ commit }, credentials: LoginCredentials) {
const { data } = await useApi().post('/auth/login', credentials)
commit('SET_TOKEN', data.value.token)
}
}
}
// store/index.ts
export default createStore({
modules: {
user: userModule,
products: productsModule
}
})Routing Architecture Design
Dynamic Routing Implementation:
// pages/users/_id.vue
<script setup>
const route = useRoute()
const { data: user } = await useFetch(`/api/users/${route.params.id}`)
</script>
<template>
<div>User ID: {{ route.params.id }}</div>
<div v-if="user">{{ user.name }}</div>
</template>Nested Routing Implementation:
pages/
├── admin/
│ ├── index.vue # /admin
│ └── users/
│ ├── index.vue # /admin/users
│ └── _id.vue # /admin/users/:idRoute Middleware:
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const auth = useAuthStore()
if (to.meta.requiresAuth && !auth.isAuthenticated) {
return navigateTo('/login')
}
})
// pages/protected.vue
<script setup>
definePageMeta({
middleware: 'auth',
requiresAuth: true
})
</script>Project Directory Structure Specification
Recommended Directory Structure:
my-nuxt-app/
├── .nuxt/ # Nuxt generated files (do not modify manually)
├── assets/ # Uncompiled static assets
│ ├── scss/ # Global SCSS files
│ └── images/ # Global images
├── components/ # Global components
│ ├── common/ # Common components
│ └── ui/ # UI base components
├── composables/ # Composables
├── layouts/ # Layout components
├── middleware/ # Route middleware
├── modules/ # Nuxt modules
├── pages/ # Page components
├── public/ # Static files (copied directly to root)
├── server/ # API routes
│ ├── middleware/ # Server middleware
│ └── api/ # API endpoints
├── stores/ # State management
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
├── app.vue # Root component
├── nuxt.config.ts # Nuxt configuration
└── tsconfig.json # TypeScript configurationEngineering Toolchain
Advanced Nuxt Configuration
Complete nuxt.config.ts Example:
export default defineNuxtConfig({
// Module configuration
modules: [
'@nuxtjs/tailwindcss',
'@pinia/nuxt',
'@nuxtjs/i18n'
],
// Build configuration
build: {
transpile: ['@vueuse/core'],
babel: {
presets({ isServer }) {
return [
[
require.resolve('@nuxt/babel-preset-app'),
{
buildTarget: isServer ? 'server' : 'client',
corejs: { version: 3 }
}
]
]
}
}
},
// Pinia configuration
pinia: {
autoImports: [
'defineStore',
['defineStore', 'definePiniaStore']
]
},
// Internationalization configuration
i18n: {
locales: ['en', 'zh'],
defaultLocale: 'en',
strategy: 'prefix_except_default'
},
// Runtime configuration
runtimeConfig: {
public: {
apiBase: process.env.API_BASE || '/api',
appVersion: '1.0.0'
},
private: {
apiSecret: process.env.API_SECRET
}
},
// Environment variable type hints
typescript: {
strict: true,
typeCheck: true
}
})Webpack Advanced Configuration
Custom Webpack Configuration:
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
if (id.includes('components')) {
return 'components'
}
}
}
}
},
plugins: [
// Custom Vite plugin
{
name: 'custom-plugin',
transform(code, id) {
if (id.endsWith('.vue')) {
return code.replace(/<template>/, '<template><div class="custom-wrapper">')
}
}
}
]
},
// Webpack configuration (traditional build)
build: {
extend(config, { isClient, isServer }) {
// Client-specific configuration
if (isClient) {
config.optimization.splitChunks = {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
}
}
// Add custom loader
config.module.rules.push({
test: /\.custom$/,
loader: '~/loaders/custom-loader.js'
})
},
// Externalize dependencies
externals: {
jquery: 'jQuery'
}
}
})TypeScript Integration
tsconfig.json Configuration:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["ES2020", "DOM"],
"baseUrl": ".",
"paths": {
"~/*": ["./*"],
"@/*": ["./*"]
},
"types": ["@types/node", "@nuxt/types"]
},
"exclude": ["node_modules"]
}Type Enhancement Example:
// types/index.d.ts
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
// Extend Nuxt types
declare module '@nuxt/schema' {
interface NuxtConfig {
myCustomOption?: string
}
interface PublicRuntimeConfig {
myApiUrl: string
}
}
// Global type declarations
interface User {
id: number
name: string
email: string
}Code Style Configuration
ESLint Configuration (.eslintrc.js):
module.exports = {
root: true,
env: {
browser: true,
node: true
},
extends: [
'@nuxtjs/eslint-config-typescript',
'plugin:prettier/recommended'
],
rules: {
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn'
},
overrides: [
{
files: ['*.vue'],
rules: {
'max-len': ['error', { code: 120 }]
}
}
]
}Prettier Configuration (.prettierrc):
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 120,
"arrowParens": "avoid",
"endOfLine": "auto"
}Testing Framework Integration
Vitest Configuration (vitest.config.ts):
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./test/setup.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html']
}
}
})Test Example:
// test/components/Button.spec.ts
import { mount } from '@vue/test-utils'
import BaseButton from '~/components/BaseButton.vue'
describe('BaseButton', () => {
it('renders slot content', () => {
const wrapper = mount(BaseButton, {
slots: {
default: 'Click me'
}
})
expect(wrapper.text()).toContain('Click me')
})
it('emits click event', async () => {
const wrapper = mount(BaseButton)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})
})Performance Optimization and Deployment
Code Splitting and Lazy Loading
Dynamic Component Import:
<script setup>
const HeavyComponent = defineAsyncComponent(() =>
import('~/components/HeavyComponent.vue')
)
</script>
<template>
<client-only>
<HeavyComponent v-if="showComponent" />
</client-only>
</template>Route-Level Code Splitting:
// pages/products/_id.vue
<script setup>
// Automatic code splitting
const product = await useFetch(`/api/products/${route.params.id}`)
</script>Third-Party Library Splitting:
// nuxt.config.ts
export default defineNuxtConfig({
build: {
transpile: ['lodash-es'], // Bundle lodash-es separately
splitChunks: {
layouts: true,
pages: true,
commons: true
}
}
})Resource Compression and Caching
Gzip Compression Configuration:
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
compressPublicAssets: {
gzip: {
level: 6
},
brotli: {
quality: 11
}
}
}
})CDN Configuration Example:
// nuxt.config.ts
export default defineNuxtConfig({
app: {
cdnURL: process.env.CDN_URL || 'https://cdn.example.com'
},
nitro: {
publicAssets: [
{ dir: '~/assets/static', baseURL: '/static' }
],
prerender: {
crawlLinks: true,
routes: ['/', '/about']
}
}
})Cache Strategy:
# HTTP response header example
Cache-Control: public, max-age=31536000, immutable
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2022 07:28:00 GMTSSR and SSG Optimization
Hybrid Rendering Configuration:
// nuxt.config.ts
export default defineNuxtConfig({
ssr: true,
target: 'static', // Default SSG
nitro: {
prerender: {
routes: ['/', '/about', '/contact']
}
},
// Dynamic route SSR
routes: ({ params }) => [
{ path: '/user/:id', component: 'pages/user/_id.vue', ssr: true }
]
})Data Prefetching Optimization:
<script setup>
// Use useAsyncData for data prefetching
const { data } = await useAsyncData('userData', () => $fetch('/api/user'))
</script>Incremental Static Regeneration (ISR):
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
isr: {
// Default 30-second revalidation
revalidate: 30
}
}
})Performance Monitoring
Lighthouse CI Integration:
# .github/workflows/lighthouse.yml
name: Lighthouse Audit
on: [push]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: treosh/lighthouse-ci-action@v9
with:
urls: |
http://localhost:3000/
http://localhost:3000/about
budgetPath: ./lighthouse-budget.jsonWeb Vitals Monitoring:
// plugins/web-vitals.ts
export default defineNuxtPlugin((nuxtApp) => {
if (process.client) {
import('web-vitals').then(({ getCLS, getFID, getLCP }) => {
getCLS(console.log)
getFID(console.log)
getLCP(console.log)
})
}
})Deployment and CI/CD
Docker Deployment Configuration:
# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]CI/CD Pipeline Example:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- run: npm ci
- run: npm run build
- run: npm run generate
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./distServerless Deployment:
// serverless.yml
service: nuxt-ssr
provider:
name: aws
runtime: nodejs16.x
memorySize: 512
timeout: 10
functions:
render:
handler: handler.render
events:
- http:
path: /
method: get
- http:
path: /{proxy+}
method: get
plugins:
- serverless-apigw-binary
- serverless-domain-manager
custom:
apigwBinary:
types:
- '*/*'
customDomain:
domainName: api.example.com
basePath: ''
stage: ${sls:stage}



