Chapter 02

项目结构与配置

深入理解 app.json、page.json、sitemap.json 和 project.config.json,掌握小程序工程化配置

2.1 完整项目结构

一个生产级微信小程序的项目结构远比最简 Demo 复杂。合理的目录组织是工程可维护性的基础:

miniprogram/
├── app.js                    # App 入口逻辑
├── app.json                  # 全局配置(路由/窗口/底部导航)
├── app.wxss                  # 全局样式
├── project.config.json       # 工具配置(不上传)
├── project.private.config.json # 个人私有配置(不提交 git)
├── sitemap.json              # 页面索引配置

├── pages/                    # 主包页面
│   ├── index/                # 首页
│   │   ├── index.js
│   │   ├── index.json
│   │   ├── index.wxml
│   │   └── index.wxss
│   └── profile/              # 我的页面

├── subpackages/              # 分包(按需加载)
│   ├── shop/                 # 商城分包
│   └── settings/             # 设置分包

├── components/               # 公共自定义组件
│   ├── nav-bar/
│   └── empty-state/

├── utils/                    # 工具函数
│   ├── request.js            # 封装 wx.request
│   ├── auth.js               # 登录鉴权
│   └── format.js             # 格式化函数

├── assets/                   # 静态资源
│   ├── images/               # 本地图片(尽量使用 CDN)
│   └── icons/                # 图标文件

└── store/                    # 全局状态管理(mobx/pinia-like)
    └── user.js
⚠️
包体积限制

小程序主包大小上限为 2 MB,单个分包上限 2 MB,所有包总大小上限 20 MB。注意:assets/images/ 中的图片会计入包体积,建议所有图片放 CDN,代码中使用 URL 引用。

2.2 app.json 全局配置

app.json 是整个小程序的"总宪法",控制路由、窗口外观、底部导航、网络超时、分包配置等全局行为。

完整 app.json 示例与注释

{
  // 必填:注册所有页面路由(第一项为默认首页)
  "pages": [
    "pages/index/index",
    "pages/profile/profile",
    "pages/detail/detail"
  ],

  // 全局窗口样式
  "window": {
    "navigationBarTitleText": "我的小程序",
    "navigationBarBackgroundColor": "#07c160",
    "navigationBarTextStyle": "white",   // black 或 white
    "backgroundColor": "#f8f8f8",        // 下拉刷新背景色
    "backgroundTextStyle": "dark",        // 下拉 loading 样式
    "enablePullDownRefresh": false,       // 全局关闭下拉刷新
    "onReachBottomDistance": 50           // 触底距离(px)
  },

  // 底部 TabBar(2-5 个 tab)
  "tabBar": {
    "color": "#999999",
    "selectedColor": "#07c160",
    "backgroundColor": "#ffffff",
    "borderStyle": "black",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "assets/icons/home.png",
        "selectedIconPath": "assets/icons/home-active.png"
      },
      {
        "pagePath": "pages/profile/profile",
        "text": "我的",
        "iconPath": "assets/icons/user.png",
        "selectedIconPath": "assets/icons/user-active.png"
      }
    ]
  },

  // 分包配置(提升首屏加载速度)
  "subpackages": [
    {
      "root": "subpackages/shop",
      "name": "shop",
      "pages": ["pages/list/list", "pages/cart/cart"]
    }
  ],

  // 分包预下载规则
  "preloadRule": {
    "pages/index/index": {
      "network": "all",  // wifi 或 all
      "packages": ["shop"]
    }
  },

  // 网络请求超时设置(毫秒)
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 30000,
    "uploadFile": 30000
  },

  // 指定默认渲染引擎(Skyline)
  "renderer": "skyline",
  "rendererOptions": {
    "skyline": {
      "defaultDisplayBlock": true  // 组件默认 display:block
    }
  },

  // 自定义组件全局启用 Component 2.x
  "componentFramework": "glass-easel",

  // 基础库最低版本要求
  "requiredPrivateInfos": ["getLocation"],
  "permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于展示附近门店"
    }
  }
}

2.3 page.json 页面配置

每个页面目录下的 *.json 文件可以覆盖 app.json 中的 window 配置,专门控制当前页面的外观行为。

// pages/detail/detail.json
{
  // 当前页面的导航栏标题(覆盖 app.json 中的全局设置)
  "navigationBarTitleText": "商品详情",
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",

  // 开启下拉刷新(仅此页面)
  "enablePullDownRefresh": true,
  "backgroundTextStyle": "dark",

  // 禁用页面分享(不显示右上角菜单的分享选项)
  "disableScroll": false,

  // 使用自定义顶部导航栏
  "navigationStyle": "custom",

  // 声明此页面使用的自定义组件
  "usingComponents": {
    "product-card": "/components/product-card/product-card",
    "sku-selector": "/components/sku-selector/sku-selector"
  },

  // 此页面单独指定渲染引擎
  "renderer": "skyline"
}
navigationStyle
设为 "custom" 时隐藏原生导航栏,整个页面全屏,开发者自行用 WXML 实现导航栏,可实现沉浸式效果
usingComponents
声明页面使用的自定义组件,key 为组件标签名,value 为组件文件路径(支持相对路径或绝对路径)
disableScroll
禁用页面滚动,常用于地图、画布等需要自定义手势的全屏页面
pageOrientation
页面旋转设置,auto/portrait/landscape,视频、游戏页面常设为 landscape 支持横屏

2.4 sitemap.json — 搜索索引配置

sitemap.json 控制微信是否可以爬取该页面内容,用于小程序搜索功能。正确配置有助于你的小程序在微信搜索中获得更多曝光。

{
  "desc": "关于本文件的更多信息,请参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
  "rules": [
    {
      // 所有页面默认允许被索引
      "action": "allow",
      "page": "*"
    },
    {
      // 个人中心等隐私页面禁止索引
      "action": "disallow",
      "page": "pages/profile/profile"
    },
    {
      // 商品详情页允许索引,并指定参数优先级
      "action": "allow",
      "page": "pages/detail/detail",
      "params": ["id"],           // 重要参数排前
      "matching": "inclusive"    // 包含这些参数的页面才索引
    }
  ]
}
ℹ️
sitemap 与 SEO

微信搜索会爬取被 allow 的页面内容(包括 WXML 文本),支持页面标题、描述等元信息索引。如果 sitemap.json 不存在,默认所有页面都允许被索引。在开发者工具中,控制台会提示哪些页面被索引了。

2.5 project.config.json 工程配置

该文件由微信开发者工具自动维护,记录工具的个性化设置,建议提交到 Git(但 project.private.config.json 应加入 .gitignore)。

{
  "appid": "wx1234567890abcdef",
  "compileType": "miniprogram",
  "libVersion": "3.3.3",  // 基础库版本
  "projectname": "my-miniprogram",
  "setting": {
    "bundle": false,
    "userConfirmedBundleSwitch": false,
    "es6": true,           // 将 ES6 转 ES5
    "enhance": true,        // 增强编译(支持 async/await)
    "postcss": true,        // WXSS 自动补全前缀
    "minified": true,       // 上传时压缩代码
    "uglifyFileName": false,// 不混淆文件名
    "ignoreUploadUnusedFiles": true  // 上传时过滤无用文件
  },
  "condition": {
    // 小程序的编译条件,调试时跳转到指定页面
    "miniprogram": {
      "list": [
        {
          "name": "商品详情页",
          "pathName": "pages/detail/detail",
          "query": "id=12345",
          "scene": null
        }
      ]
    }
  }
}

编译条件(condition)的妙用

调试详情页、分享落地页等需要传参的页面时,每次手动导航很麻烦。在 condition.miniprogram.list 中配置编译条件后,开发者工具启动时会直接打开指定页面并携带预设参数,极大提升调试效率。

2.6 目录与文件命名规范

💡
命名最佳实践

页面和组件目录统一使用小写字母 + 连字符(kebab-case),如 product-detail/。文件名与目录名保持一致。避免使用中文、空格和特殊字符,以防不同操作系统下的路径问题。

app.wxss 全局样式策略

/* app.wxss — 全局基础样式,谨慎添加 */

/* 全局盒模型 */
page {
  box-sizing: border-box;
  background-color: #f8f8f8;
  font-family: -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
  font-size: 28rpx;
  color: #333333;
  line-height: 1.6;
}

/* 清除默认 margin/padding */
view, text, image, scroll-view {
  box-sizing: border-box;
}

/* 常用工具类 */
.flex-row { display: flex; flex-direction: row; }
.flex-col { display: flex; flex-direction: column; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.text-ellipsis {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.safe-bottom {
  padding-bottom: env(safe-area-inset-bottom);
  padding-bottom: constant(safe-area-inset-bottom);
}
⚠️
全局样式的副作用

app.wxss 中定义的样式会作用于所有页面,甚至会渗入自定义组件(除非组件设置了 styleIsolation: "isolated")。建议 app.wxss 只放极少量的全局 reset 和工具类,页面特有样式放在对应的 *.wxss 文件中。