一、现代化前端架构设计
本教程将基于JavaScript构建一个企业级前端应用,涵盖从项目初始化到生产部署的完整工程化流程。
技术架构:
- 核心框架:Vue 3.2 + Composition API
- 构建工具:Webpack 5 + Vite 3
- 状态管理:Pinia 2.0
- UI组件:Element Plus + 自定义主题
- 代码规范:ESLint + Prettier + Husky
核心功能模块:
- 微前端架构实现
- 自动化代码分割
- 可视化性能监控
- 静态资源优化方案
- CI/CD流水线配置
二、项目初始化与工程配置
1. 多模式项目创建
# 使用Vite创建基础项目
npm create vite@latest enterprise-app --template vue-ts
# 添加核心依赖
cd enterprise-app
npm install pinia vue-router@4 element-plus
npm install @vueuse/core lodash-es
# 添加开发依赖
npm install eslint prettier eslint-plugin-vue @typescript-eslint/parser -D
2. 目录结构设计
src/
├── apis/ # API模块化
├── assets/ # 静态资源
│ ├── fonts/ # 字体文件
│ └── styles/ # 全局样式
├── components/ # 公共组件
│ ├── business/ # 业务组件
│ └── ui/ # 基础UI组件
├── composables/ # 组合式函数
├── layouts/ # 布局组件
├── router/ # 路由配置
├── stores/ # Pinia状态
├── utils/ # 工具函数
├── views/ # 页面组件
├── App.vue # 根组件
└── main.ts # 应用入口
三、核心架构实现
1. 自动化按需加载
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: {
preload: true // 标记需要预加载的路由
}
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 路由预加载逻辑
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.preload)) {
const matchedComponents = to.matched.map(record => record.components.default)
Promise.all(matchedComponents.map(component => {
if (typeof component === 'function') {
return component()
}
return Promise.resolve()
}))
}
next()
})
export default router
2. 状态管理设计
// stores/userStore.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { fetchUserInfo, login } from '@/apis/user'
export const useUserStore = defineStore('user', () => {
const userInfo = ref(null)
const token = ref(localStorage.getItem('token') || '')
const isLogin = computed(() => !!token.value)
async function loginAction(credentials) {
try {
const res = await login(credentials)
token.value = res.token
localStorage.setItem('token', res.token)
await getUserInfo()
} catch (error) {
throw error
}
}
async function getUserInfo() {
if (!token.value) return
userInfo.value = await fetchUserInfo()
}
function logout() {
token.value = ''
userInfo.value = null
localStorage.removeItem('token')
}
return {
userInfo,
token,
isLogin,
loginAction,
getUserInfo,
logout
}
})
四、性能优化实践
1. 虚拟列表实现
<template>
<div class="virtual-list" ref="listContainer">
<div class="list-phantom" :style="{ height: totalHeight + 'px' }"></div>
<div
class="list-content"
:style="{ transform: `translateY(${offset}px)` }">
<div
v-for="item in visibleData"
:key="item.id"
class="list-item"
:style="{ height: itemHeight + 'px' }">
{{ item.content }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
const props = defineProps({
data: {
type: Array,
required: true
},
itemHeight: {
type: Number,
default: 60
}
})
const listContainer = ref(null)
const offset = ref(0)
const startIndex = ref(0)
const visibleCount = ref(0)
const totalHeight = computed(() => {
return props.data.length * props.itemHeight
})
const endIndex = computed(() => {
return Math.min(startIndex.value + visibleCount.value, props.data.length)
})
const visibleData = computed(() => {
return props.data.slice(startIndex.value, endIndex.value)
})
function updateVisibleData() {
if (!listContainer.value) return
const scrollTop = listContainer.value.scrollTop
startIndex.value = Math.floor(scrollTop / props.itemHeight)
offset.value = scrollTop - (scrollTop % props.itemHeight)
}
onMounted(() => {
visibleCount.value = Math.ceil(listContainer.value.clientHeight / props.itemHeight)
listContainer.value.addEventListener('scroll', updateVisibleData)
})
onUnmounted(() => {
listContainer.value.removeEventListener('scroll', updateVisibleData)
})
</script>
2. Webpack深度优化
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
vue(),
visualizer({
open: true,
gzipSize: true,
brotliSize: true
})
],
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('lodash')) {
return 'lodash'
}
if (id.includes('element-plus')) {
return 'element-plus'
}
return 'vendor'
}
}
}
},
chunkSizeWarningLimit: 1000
}
})
五、微前端架构实现
1. 基于Module Federation的微前端
// webpack.config.js (主应用)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
app2: 'app2@http://localhost:3002/remoteEntry.js'
},
shared: {
vue: { singleton: true },
'vue-router': { singleton: true },
pinia: { singleton: true }
}
})
]
}
// webpack.config.js (子应用)
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./App': './src/bootstrap.js'
},
shared: {
vue: { singleton: true },
'vue-router': { singleton: true },
pinia: { singleton: true }
}
})
]
}
2. 动态加载微应用
// src/utils/loadMicroApp.js
export function loadMicroApp(scope, module) {
return new Promise((resolve, reject) => {
const element = document.createElement('script')
element.src = `${scope.url}/remoteEntry.js`
element.type = 'text/javascript'
element.async = true
element.onload = () => {
const proxy = {
get: (request) => window[scope.name].get(request),
init: (arg) => {
try {
return window[scope.name].init(arg)
} catch (e) {
reject(e)
}
}
}
proxy.init(scope.sharedScope || {})
.then(() => proxy.get(module))
.then(factory => {
const Module = factory()
resolve(Module)
})
.catch(reject)
}
element.onerror = reject
document.head.appendChild(element)
})
}
// 使用示例
loadMicroApp(
{ name: 'app1', url: 'http://localhost:3001' },
'./App'
).then(module => {
// 渲染微应用
})
六、监控与异常处理
1. 前端监控系统
// src/utils/monitor.js
class FrontendMonitor {
constructor(options) {
this.options = options
this.initPerformanceObserver()
this.initErrorHandler()
}
initPerformanceObserver() {
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries()
entries.forEach(entry => {
if (entry.entryType === 'longtask') {
this.report('longtask', {
duration: entry.duration,
startTime: entry.startTime
})
}
})
})
observer.observe({ entryTypes: ['longtask'] })
}
}
initErrorHandler() {
window.addEventListener('error', (event) => {
this.report('error', {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
stack: event.error?.stack
})
})
window.addEventListener('unhandledrejection', (event) => {
this.report('promise_error', {
reason: event.reason?.toString(),
stack: event.reason?.stack
})
})
}
report(type, data) {
const reportData = {
app: this.options.appName,
env: this.options.env,
type,
data,
timestamp: Date.now(),
url: window.location.href,
userAgent: navigator.userAgent
}
// 使用navigator.sendBeacon上报
navigator.sendBeacon(this.options.reportUrl, JSON.stringify(reportData))
}
}
// 初始化监控
const monitor = new FrontendMonitor({
appName: 'enterprise-app',
env: process.env.NODE_ENV,
reportUrl: 'https://monitor.example.com/api/report'
})
七、自动化部署
1. CI/CD配置
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build production
run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dist
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: dist
- name: Deploy to S3
uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read --follow-symlinks --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-east-1'
SOURCE_DIR: 'dist'
八、总结与展望
本教程构建了一个完整的企业级前端应用:
- 设计了现代化前端架构
- 实现了核心工程化方案
- 优化了应用性能表现
- 构建了微前端体系
- 完善了监控部署流程
扩展方向:
- WebAssembly集成
- 边缘计算方案
- 低代码平台构建
- 全栈TypeScript