uni-app单域名多应用部署指南

Viewed 0

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.jsonsubPackages 定义子应用路由范围;运行时路由在主应用中设置路由守卫,拦截跨应用访问。示例代码如下:

// 主应用路由守卫示例
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. 高级架构方案

微前端集成通过 systemjsqiankun 实现更灵活的加载策略:

// 主应用动态加载子应用
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-webpacksplitChunks;预加载策略通过 <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. 监控体系

构建多应用监控看板需收集路由切换耗时( navigationStartloadEventEnd)、资源加载失败率、内存占用峰值。示例监控代码:

// 性能监控插件
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.jsonsubPackages 配置;确保子应用页面路径唯一;在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%。开发者需重点关注路由隔离、状态管理和安全防护三大核心模块,结合自动化运维工具构建可持续演进的系统架构。

0 Answers