Our Shopping List 5.0.0 配置参数详解

Our Shopping List 5.0.0 全部 5 个系统键与 35 个前端注入键的逐项说明与实测行为(config.js 运行时注入机制、BASE_URL、实时通道参数、i18n、面板门控),附家庭内网生产配置模板。

Our Shopping List自托管2026/10/24

Our Shopping List 5.0.0 配置参数详解

目标:说清 Our Shopping List(OSL)5.0.0 的全部配置面——配置载体、参数查看与修改方式、5 个系统键与 35 个前端注入键的逐项语义与实测行为,并给出家庭内网场景的生产配置模板。本文所有「实测」项均在一台 Linux 服务器(Docker 28.3.3,OSL 5.0.0 + FerretDB 2.7 + PostgreSQL 17 栈,服务端口 8132)上验证,实测日期 2026-10-24;标注「溯源」的项取自官方 README 与源码(config.js/entrypoint),未单独构造场景验证。

一、环境信息

  • 操作系统:Linux x86_64(内核 6.8),Docker 28.3.3 + compose v2
  • OSL:ourshoppinglist/our-shopping-list:5.0.0(APP_BUILD_ID 1d6f81d3,Node.js 22.23.4)
  • 数据库栈:FerretDB 2.7.0 + PostgreSQL 17(postgres-documentdb:17-0.107.0-ferretdb-2.7.0)
  • 服务端口:8132(宿主机)→ 8080(服务默认 LISTEN_PORT)
  • 部署目录:/opt/osl(compose.yaml + .env,编排全文见《Our Shopping List Docker Compose 部署指南》)

二、前置条件

  • 已按《Our Shopping List Docker Compose 部署指南》完成三服务部署并能通过 curl http://127.0.0.1:8132/healthcheck(回显 {"success":true})。
  • 理解 OSL 的配置形态:没有传统配置文件。服务端全部配置靠环境变量;唯一可挂载的文件是 robots.txt。前端配置不进镜像构建,而是服务端启动时读取环境变量、经动态端点 /config.js 注入浏览器(本文第三章实测该机制)。

三、参数查看与修改方式

3.1 配置运行时注入机制(先懂这个再改参数)

OSL 前端是预构建产物,VITE_APP_* 变量不是构建期烧死的:服务端进程启动时把全部配置整理成一个对象,由 /config.js 动态下发,浏览器加载页面时执行 Object.assign(window, {...}) 完成注入。因此:

  • 改环境变量 + 重启服务进程 = 配置生效,无需重新构建;
  • 排查「配置到底有没有生效」直接看 /config.js,这是前端视角的最终事实。

实测闭环:给服务进程追加 VITE_APP_TITLE=家庭购物清单、VITE_APP_HOME_MESSAGE=今天买什么?、VITE_APP_BOARD_DELETION_ENABLED=1 后重启,curl http://127.0.0.1:8132/config.js 中这三键立即变为:

"VITE_APP_TITLE": "家庭购物清单"
"VITE_APP_HOME_MESSAGE": "今天买什么?"
"VITE_APP_BOARD_DELETION_ENABLED": true

同时首页 <title> 的静态占位仍显示 Loading...(真实回显),实际标题由前端加载后按注入值动态替换——不要用「右键查看网页源码里的 title」判断标题配置是否生效。

3.2 查看方式一:前端视角(curl /config.js)

curl -s http://127.0.0.1:8132/config.js

实测回显(输出节选,共 35 个 VITE_APP_* 注入键):

"VITE_APP_I18N_LOCALE": "zh"
"VITE_APP_LIST_ALL_BOARDS_ENABLED": false
"VITE_APP_SINGLEBOARD_MODE": false
"VITE_APP_SOCKETIO_PING_INTERVAL": 25000
"VITE_APP_THEME": "system"
"VITE_APP_TITLE": "Our Shopping List"
...
"BASE_URL": "./"

3.3 查看方式二:服务端视角(CLI config:show)

docker compose exec app node cli.js config:show

实测回显(输出节选,首尾):

{
  "env": {
    "VITE_APP_I18N_LOCALE": "zh",
    "VITE_APP_SINGLEBOARD_MODE": "0",
    "MONGODB_HOST": "ferretdb",
    "APP_VERSION": "5.0.0",
    "APP_BUILD_ID": "1d6f81d3",
    "APP_ENV": "production"
  },
  "config": {
    "BASE_URL": "./",
    "DEBUG": "",
    "VITE_APP_APM_ENABLED": false,
    ...
    "VITE_APP_TITLE": "Our Shopping List",
    "VITE_APP_USE_ITEM_QUICK_SYNTAX": false
  }
}

env 段是进程实际收到的原始变量(字符串),config 段是服务端归一化后的生效值(布尔/数值已转换)。两个视角对照,能定位「环境变量写了但没生效」是没传进进程(看 env 段)还是值不合法被回落(看 config 段)。

3.4 修改方式

  1. 编辑部署目录 compose.yaml 中 app 服务的 environment 段(或 .env 引用);
  2. 应用执行 docker compose up -d app 重建进程(实测回显 Container ... Recreated);
  3. 用 3.2/3.3 的两个视角验证生效。

⚠️ 注意:VUE_APP_ 前缀是 v3 之前的旧写法,v3 起迁移到 Vite 后必须用 VITE_APP_(服务端启动时会把旧前缀转换并打印映射,但建议直接用新写法)。升级老部署时这是最常见的「配置失效」原因。

四、参数总览

OSL 5.0.0 配置面全景(「实测」= 本文构造场景验证过行为;「溯源」= 官方 README/源码口径)。所有 VITE_APP_* 均经 /config.js 注入前端(第三章机制)。

系统键(服务端行为):

参数默认值实测/溯源
LISTEN_PORT8080实测(默认端口下 OSL Server started on [::]:8080)
MONGODB_HOSTmongodb实测(指向 ferretdb 后全栈联通)
MONGODB_PORT27017溯源
MONGODB_DBosl溯源
BASE_URL空实测(子路径/根路径双重行为,见 5.2)
DEBUG空实测(日志开关,见 5.3)

应用键(VITE_APP_*,35 个注入键): 语言 3 个、站点信息 3 个、面板模式与门控 5 个、条目行为 6 个、实时通道 4 个、日志与调试 4 个、APM 5 个、存储键 1 个、单面板内部键 2 个、杂项 2 个。逐项见第五章。

五、核心参数分类详解

5.1 数据库连接(系统键)

参数默认值说明
MONGODB_HOSTmongodb数据库主机名。官方 compose 里 FerretDB 栈填 ferretdb、遗留栈填 mongodb(按服务名解析)。实测指向 ferretdb 后应用正常建表读写
MONGODB_PORT27017数据库端口,FerretDB 兼容同一端口,一般不改
MONGODB_DBosl业务库名,首次启动自动创建
LISTEN_PORT8080应用监听端口;改它时 compose 的 ports 映射右侧要同步改

⚠️ 注意:MongoDB 协议认证不支持(官方 README 原文 "MongoDB authentication is not supported yet")。数据库访问控制靠部署内网隔离,这也是 compose 默认不给数据库服务映射宿主机端口的原因——不要给 ferretdb/postgres 加 ports:。

5.2 BASE_URL(子路径部署,实测最细的一组)

场景配置实测行为
根路径部署(最常见)不设一切默认,页面与 API 都在 / 下
子路径部署BASE_URL=osl2//osl2/ 正常出页;/osl2/config.js 中 "BASE_URL": "osl2/";静态资源走相对路径 ./assets/...
误配后访问根路径同上直接访问 / 返回 400 Bad Request(应用拒绝非子路径请求,不是 404)

三条硬规则(实测 + 溯源):

  1. 值必须带尾部斜杠(osl2/ 而非 osl2);
  2. 反代侧要做对应的子路径转发;
  3. 同机多实例挂不同子路径时,各实例必须配不同的 VITE_APP_LOCALSTORAGE_KEY_PREFIX(官方 README 明示,否则浏览器端 localStorage 互相踩)。

另注:BASE_URL 在开发模式(源码 Vite dev)下不受支持,属构建链限制;生产形态无影响。空值时 config:show 显示归一化结果 "./"(实测)。

5.3 DEBUG(服务端调试日志,实测)

默认 DEBUG="" 时日志只有启动横幅与错误。设为调试命名空间后重启,可看到内部行为日志。实测 DEBUG=socket.io:server,express-urlrewrite 的回显(输出节选):

2026-10-24T02:15:06.028Z express-urlrewrite rewrite /^\/*\/+(.*)/ -> /$1
2026-10-24T02:15:06.075Z socket.io:server initializing namespace /
2026-10-24T02:15:06.075Z socket.io:server creating engine.io instance with opts {"path":"/socket.io/","pingInterval":25000,"pingTimeout":20000,"connectionStateRecovery":{"maxDisconnectionDuration":1800000,...}}
Serving socket-io on /socket.io/
OSL Server started on [::]:8080

这组日志的价值:确认实时通道的实际生效参数(路径、心跳、断线恢复窗口)与 URL 重写规则,排障 WebSocket 问题时是第一手证据。格式遵循 debug 库惯例(DEBUG=socket.io:* 可开全命名空间)。

5.4 语言与界面(i18n / 标题 / 主题)

参数默认值实测/溯源说明
VITE_APP_I18N_LOCALEen实测界面语言;中文设 zh(官方 12 语言之一)。实测设 zh 后 /config.js 下发 "zh"
VITE_APP_I18N_FALLBACK_LOCALEen溯源翻译缺失时的回退语言
VITE_APP_I18N_FORCE_LOCALE0溯源1 = 忽略浏览器语言,强制用 VITE_APP_I18N_LOCALE
VITE_APP_TITLEOur Shopping List实测站点标题(浏览器标签页),注入机制见 3.1
VITE_APP_SHORT_TITLEOSL实测PWA 短标题(主屏图标名)。实测注入 "家购" 生效
VITE_APP_THEMEsystem溯源system/light/dark 三档(v4.1.x 起提供)
VITE_APP_HOME_MESSAGE空实测首页提示语,注入 今天买什么? 生效

5.5 面板模式与危险操作门控(安全默认的核心)

参数默认值实测/溯源说明
VITE_APP_SINGLEBOARD_MODE0溯源+实测注入1 = 单面板模式(v1 行为,全实例一块面板)。切换模式后的数据归位用 CLI(见部署指南升级一节)
VITE_APP_BOARD_DELETION_ENABLED0实测双向默认 0 时删除面板返回 403(DELETE /boards/:id 实测回显 {"error":{"message":"Not available! See VITE_APP_BOARD_DELETION_ENABLED."}});设 1 重启后同接口实测返回 200 并级联删除
VITE_APP_LIST_ALL_BOARDS_ENABLED0实测默认 0 时 GET /boards 返回 403(实测回显同上形式,提示本变量);1 才允许列全部面板。单面板模式下无效果
VITE_APP_SINGLEBOARD_ID / _SLUG全零 UUID / _实测(注入值)单面板模式下公共面板的内部标识,一般不动

设计逻辑:OSL 无认证,所以把「危险面」全部默认关闭——能列全部面板(侦察)与能删面板(破坏)都需要显式打开。这组默认值建议保持。

5.6 条目行为

参数默认值实测/溯源说明
VITE_APP_CHECKED_ITEMS_HISTORY_SORT_FIELDlastCheckedAt溯源已勾选历史排序字段(条目模型字段,如 createdAt)
VITE_APP_CHECKED_ITEMS_HISTORY_SORT_ORDERdesc溯源已勾选历史排序方向
VITE_APP_EDIT_ITEM_ON_CREATE0溯源1 = 新建条目后立即进入编辑
VITE_APP_USE_ITEM_QUICK_SYNTAX0溯源1 = 输入快捷语法(名称后跟数量等)
VITE_APP_DISABLE_PASTE_CSV0溯源1 = 关闭 CSV 粘贴批量建条目(v4.2.0 引入的功能)
VITE_APP_PASTE_CSV_SEPARATOR,溯源CSV 粘贴解析分隔符(中文表格导出常为 \t 时改它)
VITE_APP_HIDE_FORCE_REFRESH_HINT0溯源1 = 隐藏「请刷新页面」提示浮层(v4.1.2 新增)

5.7 实时通道(Socket.IO)

参数默认值实测/溯源说明
VITE_APP_SOCKETIO_PING_INTERVAL25000实测(注入值+服务端日志)心跳间隔(毫秒),实测服务端 opts 中同为 25000
VITE_APP_SOCKETIO_PING_TIMEOUT20000实测(注入值+服务端日志)心跳超时(毫秒)
VITE_APP_SOCKETIO_CSR_MAXDISCONNECTIONDURATION1800000实测(注入值+服务端日志)断线连接状态恢复窗口:30 分钟内重连可恢复会话
VITE_APP_SOCKETIO_TRANSPORTSwebsocket实测(注入值)传输方式;被反代拦截 WebSocket 时临时改回轮询是排障手段,不建议长期

💡 说明:这组参数决定「手机切后台再回来清单还在不在」的体验。默认 30 分钟恢复窗口对买菜场景足够;若网络环境频繁断连(如地铁弱网 PWA),可调大 CSR_MAXDISCONNECTIONDURATION。

5.8 日志、APM 与杂项

参数默认值实测/溯源说明
VITE_APP_LOCALSTORAGE_KEY_PREFIXOurShoppingList_实测(注入值)浏览器存储键前缀;多实例同域名部署时必须互不相同
VITE_APP_CLIENT_LOG_ENABLEDfalse实测(注入值)前端日志开关
VITE_APP_CLIENT_LOG_CONSOLE_ENABLEDfalse实测(注入值)前端日志是否进控制台
VITE_APP_CLIENT_LOG_LEVELdebug实测(注入值)前端日志级别
VITE_APP_DISABLE_CONTEXTMENUfalse实测(注入值)1 = 禁用右键菜单(触屏误触场景)
VITE_APP_DISABLE_AGRESSIVE_ASSETS_CACHINGfalse溯源1 = 关闭前端资源强缓存(排查前端更新不生效时用)
VITE_APP_APM_ENABLEDfalse实测(注入值)Elastic APM RUM 前端监控开关
VITE_APP_APM_LOGLEVEL / _SERVERURL / _SERVERURLPREFIX / _SERVICENAMEwarn / http://localhost:8200 / /intake/v.../rum/events / 空实测(注入值)APM 上报参数,家庭场景用不到
VITE_APP_ENVproduction(镜像内定)实测(注入值)运行环境标识,不要手改

5.9 数据库层参数(compose 侧,非应用键)

参数位置默认说明
FERRETDB_AUTHferretdb 服务false实测采用;OSL 的 mongoose 连接串不带账号,官方默认即关
FERRETDB_POSTGRESQL_URLferretdb 服务—指向 PostgreSQL 的连接串,建议引用 .env 变量拼装(见部署指南 4.1)
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DBpostgres 服务(.env)—存储层账号;演示值 osl/q1w2e3r4,生产换强口令并 chmod 600 .env

六、生产配置模板(家庭内网 12 GB 内存 / 任意磁盘 / 520 人)

    environment:
      # ---- 数据库连接 ----
      MONGODB_HOST: ferretdb
      # ---- 子路径部署才需要(根路径不要设)----
      # BASE_URL: osl/
      # ---- 界面 ----
      VITE_APP_I18N_LOCALE: zh
      VITE_APP_I18N_FALLBACK_LOCALE: en
      VITE_APP_I18N_FORCE_LOCALE: 0
      VITE_APP_TITLE: 家庭购物清单
      VITE_APP_SHORT_TITLE: 家购
      VITE_APP_HOME_MESSAGE: 出门前看一眼
      VITE_APP_THEME: system
      # ---- 模式与门控(安全默认,保持关闭)----
      VITE_APP_SINGLEBOARD_MODE: 0
      VITE_APP_BOARD_DELETION_ENABLED: 0
      VITE_APP_LIST_ALL_BOARDS_ENABLED: 0
      # ---- 实时通道(默认已合适)----
      VITE_APP_SOCKETIO_PING_INTERVAL: 25000
      VITE_APP_SOCKETIO_PING_TIMEOUT: 20000
      VITE_APP_SOCKETIO_CSR_MAXDISCONNECTIONDURATION: 1800000
      # ---- 多实例同域名时才需要 ----
      # VITE_APP_LOCALSTORAGE_KEY_PREFIX: OSL2_

适用说明:该模板面向家庭内网/NAS(实测全套内存占用约 100 MiB,1 GB 内存机器可跑);磁盘无特殊要求(文本数据增长可忽略)。要点是门控三键全部保持默认 0,面板入口走 slug 链接分发;公司团队场景可按需打开 VITE_APP_BOARD_DELETION_ENABLED=1 由管理员删面板,同时考虑在上游反代加认证。

七、常见问题

Q1:环境变量明明写了,界面没变? 三步定位:docker compose exec app node cli.js config:show 看 env 段有没有该键(没有=没传进进程,检查 compose 缩进/服务段);再看 config 段的归一化值;最后 curl /config.js 确认下发值。最常见原因是变量名前缀写成了旧的 VUE_APP_。

Q2:VITE_APP_THEME=dark 设了但页面还是亮色? 该变量为「默认主题」,用户在界面里手动切换主题后会以浏览器本地偏好为准(存 localStorage)。清站点数据或换浏览器可验证服务端默认值。

Q3:改了 LISTEN_PORT=9000 但外部访问不通? 只改了监听端口而没改端口映射。compose 的 ports 右侧仍指向 8080。两边同步:'8132:9000'。验证:curl http://127.0.0.1:8132/healthcheck。

Q4:子路径部署后页面白屏、资源 404? 检查三点:BASE_URL 是否带尾部斜杠;反代是否把该前缀完整转发(不能 rewrite 掉前缀);前端资源路径应是 ./assets/ 相对路径(实测子路径部署下 index.html 如此引用)。另注意多实例时 localStorage 键前缀要错开。

Q5:删面板的 403 是坏了还是默认? 默认。VITE_APP_BOARD_DELETION_ENABLED=0 时服务端明确拒绝(实测 403 + 提示语)。确需删除时置 1 重启,操作完建议改回 0。

Q6:config:show 里 env 段是字符串 "0",config 段是布尔 false,哪个是真的? 都是真的:env 是进程收到的原始字符串,config 是服务端解析后的生效值。判断行为以 config 段与 /config.js 下发值为准。

八、参考链接

本专栏其余篇目:部署编排与变量传递见《Our Shopping List Docker Compose 部署指南》;选型背景见《Our Shopping List 5.0.0 介绍与选型指南》;变量对应的 API 行为实测见《Our Shopping List 5.0.0 API 使用详解》。