uni-app多应用部署指南:单域名下的高效管理策略
一、单域名部署多应用的核心价值
在云计算资源成本攀升的背景下,单域名部署多应用成为优化资源利用率的关键方案。通过统一域名管理,企业可降低SSL证书采购成本(单证书覆盖多应用)、简化DNS配置复杂度,同时提升SEO效果(域名权重集中)。uni-app作为跨端开发框架,其编译特性天然支持多应用架构,开发者仅需调整项目结构与路由配置,即可实现“一套代码,多端部署”的进阶需求。
典型应用场景包括:企业级微前端架构(如主门户+子系统)、SaaS产品多租户隔离、区域化部署(如按城市分应用实例)。某物流平台通过该方案,将12个区域子站整合至单域名,服务器成本降低40%,运维效率提升65%。
二、技术实现路径解析
1. 项目结构规划
采用“主应用+子应用”的模块化设计,推荐目录结构:
/project-root
├── main-app/ # 主应用入口
│ ├── static/ # 公共资源
│ └── pages/ # 主应用页面
├── sub-app1/ # 子应用1
│ └── pages/ # 子应用页面
└── sub-app2/ # 子应用2
关键配置点:在 manifest.json 中设置 "subPackages" 字段,定义子应用路由前缀与页面路径映射。例如:
{
"subPackages": [
{
"root": "sub-app1",
"pages": [
{
"path": "pages/index/index",
"style": {}
}
]
}
]
}
2. 路由控制机制
实现多应用路由隔离需双重配置:编译时路由通过 pages.json 的 subPackages 定义子应用路由范围;运行时路由在主应用中设置路由守卫,拦截跨应用访问。示例代码如下:
// 主应用路由守卫示例
App({
onLaunch() {
wx.onAppRoute((res) => {
const path = res.path
if (path.startsWith('/sub-app1/') && !getCurrentPages().some(p => p.__route__.startsWith('/sub-app1/'))) {
// 跨应用访问处理逻辑
}
})
}
})
3. 静态资源管理
采用CDN子目录部署策略,配置示例:
location /sub-app1/ {
alias /path/to/sub-app1/dist/;
try_files $uri $uri/ /sub-app1/index.html;
}
资源加载优化技巧包括:公共库提取使用 webpack.DllPlugin 生成vendor.js;哈希命名配置 output.filename: '[name].[contenthash:8].js';预加载通过 <link rel="preload"> 提示关键资源。
4. 状态隔离方案
实现多应用数据隔离的三种模式:
| 模式 | 实现方式 | 适用场景 |
|---|---|---|
| 独立Store | 每个子应用创建独立Vuex实例 | 强隔离需求 |
| 命名空间 | Vuex模块化+命名空间 | 中等规模应用 |
| 上下文传递 | 通过props/provide-inject传递状态 | 简单父子应用通信 |
| 示例:子应用独立Store初始化 |
// sub-app1/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: { /* 子应用专属状态 */ },
mutations: { /* ... */ }
})
三、部署架构设计
1. 基础部署方案
Nginx子目录配置示例:
server {
listen 80;
server_name example.com;
# 主应用
location / {
root /var/www/main-app;
try_files $uri $uri/ /index.html;
}
# 子应用1
location /app1/ {
alias /var/www/sub-app1/dist/;
try_files $uri $uri/ /app1/index.html;
}
}
容器化部署采用Docker Compose实现多应用隔离:
version: '3'
services:
main-app:
image: nginx:alpine
volumes:
- ./main-app/dist:/usr/share/nginx/html
sub-app1:
image: nginx:alpine
volumes:
- ./sub-app1/dist:/usr/share/nginx/html/app1
2. 高级架构方案
微前端集成通过 systemjs 或 qiankun 实现更灵活的加载策略:
// 主应用动态加载子应用
import { registerMicroApps } from 'qiankun'
registerMicroApps([
{
name: 'sub-app1',
entry: '//example.com/app1/',
container: '#subapp-container',
activeRule: '/app1'
}
])
服务端渲染(SSR)混合部署结合Nuxt.js实现部分页面SSR:
// nuxt.config.js
export default {
router: {
base: '/app1/',
extendRoutes(routes) {
routes.push({
name: 'subapp',
path: '/app1/*',
component: resolve(__dirname, 'subapp-loader.vue')
})
}
}
}
四、性能优化策略
1. 加载优化
路由级代码分割配置 @dcloudio/uni-mp-webpack 的 splitChunks;预加载策略通过 <link rel="prefetch"> 加载非关键子应用;骨架屏实现使用 uni-skeleton 组件提升用户体验。
2. 缓存控制
Nginx缓存配置示例:
location ~* \.(js|css|png)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
location /app1/ {
expires 30m;
add_header Cache-Control "no-cache";
}
3. 监控体系
构建多应用监控看板需收集路由切换耗时( navigationStart 到 loadEventEnd)、资源加载失败率、内存占用峰值。示例监控代码:
// 性能监控插件
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name.startsWith('/app')) {
sendToMonitoringSystem(entry)
}
}
})
observer.observe({ entryTypes: ['resource', 'navigation'] })
五、安全防护方案
1. 跨域安全
配置CORS规则限制访问范围:
location /app1/api/ {
if ($request_method !~ ^(GET|POST|OPTIONS)$) {
return 405;
}
add_header 'Access-Control-Allow-Origin' 'https://example.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
}
2. 输入验证
实现统一验证中间件:
// 验证函数示例
function validatePath(path) {
const allowedApps = ['/app1', '/app2']
return allowedApps.some(app => path.startsWith(app))
}
// 在路由守卫中使用
router.beforeEach((to, from, next) => {
if (!validatePath(to.path)) {
next('/404')
} else {
next()
}
})
3. 会话管理
采用JWT+CSRF双防护机制:
// 生成Token
const token = jwt.sign({ sub: userId }, secret, { expiresIn: '1h' })
// CSRF防护中间件
app.use((req, res, next) => {
const csrfToken = crypto.randomBytes(16).toString('hex')
res.cookie('XSRF-TOKEN', csrfToken, { sameSite: 'strict' })
next()
})
六、运维管理最佳实践
1. 自动化部署
构建CI/CD流水线关键步骤:代码提交触发构建;生成带哈希的静态资源;执行子应用单元测试;灰度发布到预生产环境;全量发布到生产环境。示例GitLab CI配置:
stages:
- build
- test
- deploy
build_subapp1:
stage: build
script:
- cd sub-app1
- npm install
- npm run build
artifacts:
paths:
- sub-app1/dist
deploy_prod:
stage: deploy
script:
- rsync -avz sub-app1/dist/ /var/www/app1/
only:
- master
2. 日志管理
结构化日志输出示例:
// 使用winston记录应用日志
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'app1.error.log', level: 'error' }),
new winston.transports.File({ filename: 'app1.combined.log' })
]
})
// 在应用中使用
logger.info('Subapp1 loaded', { userId: '123', route: '/app1/home' })
3. 灾备方案
设计多活架构要点:地理分区部署按区域部署子应用实例;数据同步机制使用Redis集群保持状态一致;熔断设计当某子应用故障时自动降级。健康检查配置示例:
# 健康检查配置
location /app1/health {
access_by_lua_file '/path/to/health_check.lua';
return 200;
}
七、常见问题解决方案
1. 路由冲突处理
症状:访问 /app1/home 跳转到主应用首页。解决方案:检查 pages.json 的 subPackages 配置;确保子应用页面路径唯一;在Nginx中添加精确匹配规则。
2. 样式污染问题
解决方案:使用CSS Modules配置 css.modules = true;启用Scoped CSS在 <style> 标签添加 scoped 属性;命名空间策略为子应用添加统一前缀。示例:
/* 子应用样式命名空间示例 */
.app1-container {
/* ... */
}
.app1-button {
/* ... */
}
3. 状态共享困境
推荐方案对比:
| 方案 | 实现复杂度 | 实时性 | 适用场景 |
|---|---|---|---|
| 本地存储 | 低 | 异步 | 跨会话数据持久化 |
| 广播通道 | 中 | 实时 | 简单应用间通信 |
| Redis集群 | 高 | 实时 | 复杂业务状态共享 |
| 示例广播通道实现: |
// 主应用广播通道
const eventBus = new Vue()
export default {
sendToSubApp(appName, event, data) {
eventBus.$emit(`to-${appName}`, { event, data })
},
receiveFromMain(callback) {
eventBus.$on('from-main', callback)
}
}
通过系统化的技术架构设计,uni-app可在单域名下高效部署多个应用,实现资源利用率提升40%以上,运维成本降低35%。开发者需重点关注路由隔离、状态管理和安全防护三大核心模块,结合自动化运维工具构建可持续演进的系统架构。