[{"data":1,"prerenderedAt":427},["ShallowReactive",2],{"insight-django-tech-debt":3,"insight-related-django-tech-debt":153},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":7,"slug":9,"date":10,"duration":11,"category":12,"author":13,"tags":14,"body":18,"_type":147,"_id":148,"_source":149,"_file":150,"_stem":151,"_extension":152},"\u002Finsights\u002F14-django-tech-debt","insights",false,"","长期可维护：6 年 Django 项目的技术债治理","django-tech-debt","2026-04-02",11,"技术实践","浩途技术团队",[15,16,17],"Django","技术债","长期维护",{"type":19,"children":20,"toc":140},"root",[21,29,43,47,53,58,78,83,86,92,111,120,123,128],{"type":22,"tag":23,"props":24,"children":26},"element","h2",{"id":25},"引子",[27],{"type":28,"value":25},"text",{"type":22,"tag":30,"props":31,"children":32},"p",{},[33,35,41],{"type":28,"value":34},"祁门政务大屏从 2018 年上线至今 6 年，仍在持续迭代。最初的 Django 项目按\"今天\n看明天就过时\"的标准看，技术债理论上爆炸了——但它没有。这篇文章写浩途如何",{"type":22,"tag":36,"props":37,"children":38},"strong",{},[39],{"type":28,"value":40},"边\n走边换",{"type":28,"value":42},"地治理技术债。",{"type":22,"tag":44,"props":45,"children":46},"hr",{},[],{"type":22,"tag":23,"props":48,"children":50},{"id":49},"原则不重构重组装",[51],{"type":28,"value":52},"原则：不重构，重组装",{"type":22,"tag":30,"props":54,"children":55},{},[56],{"type":28,"value":57},"每次新需求来时优先做三件事：",{"type":22,"tag":59,"props":60,"children":61},"ol",{},[62,68,73],{"type":22,"tag":63,"props":64,"children":65},"li",{},[66],{"type":28,"value":67},"把要改的模块的依赖收敛清楚",{"type":22,"tag":63,"props":69,"children":70},{},[71],{"type":28,"value":72},"把\"不再用的\"代码先标记 deprecated 而不删除",{"type":22,"tag":63,"props":74,"children":75},{},[76],{"type":28,"value":77},"在 deprecated 周围逐步建立新模块",{"type":22,"tag":30,"props":79,"children":80},{},[81],{"type":28,"value":82},"3 年下来旧代码消化掉一大半，期间项目从未停止迭代。",{"type":22,"tag":44,"props":84,"children":85},{},[],{"type":22,"tag":23,"props":87,"children":89},{"id":88},"三类常见债的处理占位",[90],{"type":28,"value":91},"三类常见债的处理（占位）",{"type":22,"tag":93,"props":94,"children":95},"ul",{},[96,101,106],{"type":22,"tag":63,"props":97,"children":98},{},[99],{"type":28,"value":100},"数据库 schema 历史遗留",{"type":22,"tag":63,"props":102,"children":103},{},[104],{"type":28,"value":105},"第三方 SDK 升级断点",{"type":22,"tag":63,"props":107,"children":108},{},[109],{"type":28,"value":110},"早期接口设计的硬编码",{"type":22,"tag":112,"props":113,"children":114},"blockquote",{},[115],{"type":22,"tag":30,"props":116,"children":117},{},[118],{"type":28,"value":119},"（每类的具体处理 pattern 后续展开）",{"type":22,"tag":44,"props":121,"children":122},{},[],{"type":22,"tag":23,"props":124,"children":126},{"id":125},"写在最后",[127],{"type":28,"value":125},{"type":22,"tag":30,"props":129,"children":130},{},[131,133,138],{"type":28,"value":132},"技术债治理不是项目，是",{"type":22,"tag":36,"props":134,"children":135},{},[136],{"type":28,"value":137},"日常",{"type":28,"value":139},"。把它当作每周做的事，而不是每年做的事——这是长期项目\n能活下来的关键。",{"title":7,"searchDepth":141,"depth":141,"links":142},2,[143,144,145,146],{"id":25,"depth":141,"text":25},{"id":49,"depth":141,"text":52},{"id":88,"depth":141,"text":91},{"id":125,"depth":141,"text":125},"markdown","content:insights:14-django-tech-debt.md","content","insights\u002F14-django-tech-debt.md","insights\u002F14-django-tech-debt","md",[154,288],{"_path":155,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":156,"description":7,"slug":157,"date":158,"duration":159,"category":12,"author":13,"tags":160,"body":165,"_type":147,"_id":285,"_source":149,"_file":286,"_stem":287,"_extension":152},"\u002Finsights\u002F15-nuxt-pagefind","Nuxt 3 静态化 + Pagefind：内容站的工程实践","nuxt-pagefind","2026-02-28",8,[161,162,163,164],"Nuxt 3","Pagefind","SSG","静态站",{"type":19,"children":166,"toc":279},[167,171,183,186,192,225,228,234,252,260,263,267],{"type":22,"tag":23,"props":168,"children":169},{"id":25},[170],{"type":28,"value":25},{"type":22,"tag":30,"props":172,"children":173},{},[174,176,181],{"type":28,"value":175},"浩途官网（haotunet.com）是一个纯静态站——不需要后端、不依赖 CDN 智能化、单机\nnginx 就能服务全国。但又需要站内搜索。",{"type":22,"tag":36,"props":177,"children":178},{},[179],{"type":28,"value":180},"Nuxt 3 + Pagefind",{"type":28,"value":182}," 的组合让这两件事\n零摩擦共存。",{"type":22,"tag":44,"props":184,"children":185},{},[],{"type":22,"tag":23,"props":187,"children":189},{"id":188},"工程选择的三个-trade-off",[190],{"type":28,"value":191},"工程选择的三个 trade-off",{"type":22,"tag":59,"props":193,"children":194},{},[195,205,215],{"type":22,"tag":63,"props":196,"children":197},{},[198,203],{"type":22,"tag":36,"props":199,"children":200},{},[201],{"type":28,"value":202},"SSG vs SSR",{"type":28,"value":204},"：选 SSG（静态化），换更简单的部署",{"type":22,"tag":63,"props":206,"children":207},{},[208,213],{"type":22,"tag":36,"props":209,"children":210},{},[211],{"type":28,"value":212},"客户端搜索 vs 服务端搜索",{"type":28,"value":214},"：选客户端（Pagefind），不需要 ES",{"type":22,"tag":63,"props":216,"children":217},{},[218,223],{"type":22,"tag":36,"props":219,"children":220},{},[221],{"type":28,"value":222},"站内全文 vs 内容片段",{"type":28,"value":224},"：构建时索引，下载体积可控",{"type":22,"tag":44,"props":226,"children":227},{},[],{"type":22,"tag":23,"props":229,"children":231},{"id":230},"关键工程点占位",[232],{"type":28,"value":233},"关键工程点（占位）",{"type":22,"tag":93,"props":235,"children":236},{},[237,242,247],{"type":22,"tag":63,"props":238,"children":239},{},[240],{"type":28,"value":241},"Pagefind 的索引时机：build 阶段而非 dev",{"type":22,"tag":63,"props":243,"children":244},{},[245],{"type":28,"value":246},"索引体积：50 篇内容大约 500KB，懒加载即可",{"type":22,"tag":63,"props":248,"children":249},{},[250],{"type":28,"value":251},"与 Cmd+K 弹窗的集成",{"type":22,"tag":112,"props":253,"children":254},{},[255],{"type":22,"tag":30,"props":256,"children":257},{},[258],{"type":28,"value":259},"（具体配置文件、索引体积控制、UX 细节后续展开）",{"type":22,"tag":44,"props":261,"children":262},{},[],{"type":22,"tag":23,"props":264,"children":265},{"id":125},[266],{"type":28,"value":125},{"type":22,"tag":30,"props":268,"children":269},{},[270,272,277],{"type":28,"value":271},"不是所有内容站都需要重型架构。",{"type":22,"tag":36,"props":273,"children":274},{},[275],{"type":28,"value":276},"对内容站来说，越简单越长寿",{"type":28,"value":278},"——这是浩途自己用一年\n跑下来的体会。",{"title":7,"searchDepth":141,"depth":141,"links":280},[281,282,283,284],{"id":25,"depth":141,"text":25},{"id":188,"depth":141,"text":191},{"id":230,"depth":141,"text":233},{"id":125,"depth":141,"text":125},"content:insights:15-nuxt-pagefind.md","insights\u002F15-nuxt-pagefind.md","insights\u002F15-nuxt-pagefind",{"_path":289,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":290,"description":7,"slug":291,"date":292,"duration":293,"category":12,"author":13,"tags":294,"body":299,"_type":147,"_id":424,"_source":149,"_file":425,"_stem":426,"_extension":152},"\u002Finsights\u002F16-mysql-to-postgres","数据库迁移：100+ 表的 MySQL 项目迁到 PostgreSQL","mysql-to-postgres","2025-10-15",14,[295,296,297,298],"数据库","迁移","MySQL","PostgreSQL",{"type":19,"children":300,"toc":418},[301,305,317,320,326,354,357,363,391,399,402,406],{"type":22,"tag":23,"props":302,"children":303},{"id":25},[304],{"type":28,"value":25},{"type":22,"tag":30,"props":306,"children":307},{},[308,310,315],{"type":28,"value":309},"某客户的核心业务系统跑在 MySQL 上 5 年了，因合规要求需要迁到 PostgreSQL，且业务",{"type":22,"tag":36,"props":311,"children":312},{},[313],{"type":28,"value":314},"不能\n停超过 2 小时",{"type":28,"value":316},"。这次迁移是浩途近年最复杂的一次基础设施变更，复盘写下来。",{"type":22,"tag":44,"props":318,"children":319},{},[],{"type":22,"tag":23,"props":321,"children":323},{"id":322},"整体策略双写-灰度切流",[324],{"type":28,"value":325},"整体策略：双写 + 灰度切流",{"type":22,"tag":59,"props":327,"children":328},{},[329,334,339,344,349],{"type":22,"tag":63,"props":330,"children":331},{},[332],{"type":28,"value":333},"先在生产环境双写（MySQL 主、PostgreSQL 影子）",{"type":22,"tag":63,"props":335,"children":336},{},[337],{"type":28,"value":338},"影子库跑业务回归 + 数据校对",{"type":22,"tag":63,"props":340,"children":341},{},[342],{"type":28,"value":343},"只读流量先切到 PostgreSQL 灰度",{"type":22,"tag":63,"props":345,"children":346},{},[347],{"type":28,"value":348},"写流量按业务模块逐步切换",{"type":22,"tag":63,"props":350,"children":351},{},[352],{"type":28,"value":353},"MySQL 降级为只读 backup，30 天后下线",{"type":22,"tag":44,"props":355,"children":356},{},[],{"type":22,"tag":23,"props":358,"children":360},{"id":359},"踩过的坑占位",[361],{"type":28,"value":362},"踩过的坑（占位）",{"type":22,"tag":93,"props":364,"children":365},{},[366,371,376,381,386],{"type":22,"tag":63,"props":367,"children":368},{},[369],{"type":28,"value":370},"字符集 \u002F 时区差异",{"type":22,"tag":63,"props":372,"children":373},{},[374],{"type":28,"value":375},"自增 ID 的连续性",{"type":22,"tag":63,"props":377,"children":378},{},[379],{"type":28,"value":380},"全文索引语义差异",{"type":22,"tag":63,"props":382,"children":383},{},[384],{"type":28,"value":385},"触发器与存储过程的等价改写",{"type":22,"tag":63,"props":387,"children":388},{},[389],{"type":28,"value":390},"应用层 ORM 的 SQL 兼容",{"type":22,"tag":112,"props":392,"children":393},{},[394],{"type":22,"tag":30,"props":395,"children":396},{},[397],{"type":28,"value":398},"（每个坑的具体方案与回归脚本后续展开）",{"type":22,"tag":44,"props":400,"children":401},{},[],{"type":22,"tag":23,"props":403,"children":404},{"id":125},[405],{"type":28,"value":125},{"type":22,"tag":30,"props":407,"children":408},{},[409,411,416],{"type":28,"value":410},"数据库迁移没有\"标准方案\"，只有\"对你的业务最小风险的路径\"。",{"type":22,"tag":36,"props":412,"children":413},{},[414],{"type":28,"value":415},"预演 2-3 次比文档读 10\n份更有用",{"type":28,"value":417},"——这是浩途技术团队的硬经验。",{"title":7,"searchDepth":141,"depth":141,"links":419},[420,421,422,423],{"id":25,"depth":141,"text":25},{"id":322,"depth":141,"text":325},{"id":359,"depth":141,"text":362},{"id":125,"depth":141,"text":125},"content:insights:16-mysql-to-postgres.md","insights\u002F16-mysql-to-postgres.md","insights\u002F16-mysql-to-postgres",1780542368293]