简介:本文深入探讨如何在uni-app框架下实现单域名部署多个应用,涵盖路由配置、子目录部署、安全隔离及性能优化等关键技术点,为开发者提供完整的解决方案。
在云计算资源成本攀升的背景下,单域名部署多应用成为优化资源利用率的关键方案。通过统一域名管理,企业可降低SSL证书采购成本(单证书覆盖多应用)、简化DNS配置复杂度,同时提升SEO效果(域名权重集中)。uni-app作为跨端开发框架,其编译特性天然支持多应用架构,开发者仅需调整项目结构与路由配置,即可实现”一套代码,多端部署”的进阶需求。
典型应用场景包括:企业级微前端架构(如主门户+子系统)、SaaS产品多租户隔离、区域化部署(如按城市分应用实例)。某物流平台通过该方案,将12个区域子站整合至单域名,服务器成本降低40%,运维效率提升65%。
采用”主应用+子应用”的模块化设计,推荐目录结构:
/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": {}}]}]}
实现多应用路由隔离需双重配置:
pages.json的subPackages定义子应用路由范围
// 主应用路由守卫示例App({onLaunch() {wx.onAppRoute((res) => {const path = res.pathif (path.startsWith('/sub-app1/') && !getCurrentPages().some(p => p.__route__.startsWith('/sub-app1/'))) {// 跨应用访问处理逻辑}})}})
采用CDN子目录部署策略,配置示例:
location /sub-app1/ {alias /path/to/sub-app1/dist/;try_files $uri $uri/ /sub-app1/index.html;}
资源加载优化技巧:
webpack.DllPlugin生成vendor.jsoutput.filename: '[name].[contenthash:8].js'<link rel="preload">提示关键资源实现多应用数据隔离的三种模式:
| 模式 | 实现方式 | 适用场景 |
|——————|—————————————————-|————————————|
| 独立Store | 每个子应用创建独立Vuex实例 | 强隔离需求 |
| 命名空间 | Vuex模块化+命名空间 | 中等规模应用 |
| 上下文传递 | 通过props/provide-inject传递状态 | 简单父子应用通信 |
示例:子应用独立Store初始化
// sub-app1/store/index.jsimport Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: { /* 子应用专属状态 */ },mutations: { /* ... */ }})
server {listen 80;server_name example.com;# 主应用location / {root /var/www/main-app;try_files $uri $uri/ /index.html;}# 子应用1location /app1/ {alias /var/www/sub-app1/dist/;try_files $uri $uri/ /app1/index.html;}}
采用Docker Compose实现多应用隔离:
version: '3'services:main-app:image: nginx:alpinevolumes:- ./main-app/dist:/usr/share/nginx/htmlsub-app1:image: nginx:alpinevolumes:- ./sub-app1/dist:/usr/share/nginx/html/app1
通过systemjs或qiankun实现更灵活的加载策略:
// 主应用动态加载子应用import { registerMicroApps } from 'qiankun'registerMicroApps([{name: 'sub-app1',entry: '//example.com/app1/',container: '#subapp-container',activeRule: '/app1'}])
结合Nuxt.js实现部分页面SSR:
// nuxt.config.jsexport default {router: {base: '/app1/',extendRoutes(routes) {routes.push({name: 'subapp',path: '/app1/*',component: resolve(__dirname, 'subapp-loader.vue')})}}}
@dcloudio/uni-mp-webpack的splitChunks<link rel="prefetch">加载非关键子应用uni-skeleton组件提升用户体验Nginx缓存配置示例:
location ~* \.(js|css|png)$ {expires 1y;add_header Cache-Control "public, no-transform";}location /app1/ {expires 30m;add_header Cache-Control "no-cache";}
构建多应用监控看板需收集:
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'] })
配置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';}
实现统一验证中间件:
// 验证函数示例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()}})
采用JWT+CSRF双防护机制:
// 生成Tokenconst 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()})
构建CI/CD流水线关键步骤:
示例GitLab CI配置:
stages:- build- test- deploybuild_subapp1:stage: buildscript:- cd sub-app1- npm install- npm run buildartifacts:paths:- sub-app1/distdeploy_prod:stage: deployscript:- rsync -avz sub-app1/dist/ /var/www/app1/only:- master
结构化日志输出示例:
// 使用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' })
设计多活架构要点:
# 健康检查配置location /app1/health {access_by_lua_file '/path/to/health_check.lua';return 200;}
症状:访问/app1/home跳转到主应用首页
解决方案:
pages.json的subPackages配置解决方案:
css.modules = true<style>标签添加scoped属性
/* 子应用样式命名空间示例 */.app1-container {/* ... */}.app1-button {/* ... */}
推荐方案对比:
| 方案 | 实现复杂度 | 实时性 | 适用场景 |
|———————|——————|—————|————————————|
| 本地存储 | 低 | 异步 | 跨会话数据持久化 |
| 广播通道 | 中 | 实时 | 简单应用间通信 |
| 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%。开发者需重点关注路由隔离、状态管理和安全防护三大核心模块,结合自动化运维工具构建可持续演进的系统架构。