做这个 H5 项目,目标很单纯也很贪心:一套代码,要跑通 N 个渠道,支持多国语言,还要快。
为了达成这个目标,我们没少在"理想"和"现实"之间做取舍。以下这 7 点,是我们踩坑之后总结出来的生存法则。
1. 路由选择:为了"活着",不得不妥协
做前端的都喜欢 History 模式,URL 干净又漂亮。但在这个项目里,我们果断选了 Hash(/#/path)。 为什么?因为我们的 H5 要嵌入到各种各样奇怪的 APP WebView 里,还要跨不同的域名部署。 History 模式需要服务端配合配置 Nginx,而 Hash 模式完全独立,部署时就像扔静态文件一样简单。更重要的是,在一些老旧或逻辑诡异的第三方 APP 中,Hash 路由的兼容性是无敌的。 虽不优雅,但它皮实。
2. 状态管理:拒绝"一把梭"
以前我们也试过把所有数据都塞进 Redux,结果 Store 变得巨大无比,难以维护。这次我们学聪明了,搞了个"双轨制":
3. 给首屏"瘦身"
H5 最怕什么?白屏。 我们有 80 多个页面,如果打包成一个大 JS 文件,用户在弱网下得等到天荒地老。 我们利用 Loader() 配合 react-loadable,把这 80 多个路由切成了 80 多块小蛋糕。用户点哪里,我们就只加载哪一块代码。这不仅仅是技术指标的提升,更是对用户流量的尊重。
4. 拒绝 Copy-Paste:渠道配置中心
今天运营说要上"双十一特供版",明天BD说要给"某省银行"做个内嵌版。如果每次都去改代码逻辑,开发得累死。 我们将所有差异化配置(各省特性、活动开关、内购参数)全部抽离到 store/channel.js。 这里就像个总控台。代码是一样的代码,配置表一换,它就能变身成完全不同的样子。 维护成本直接砍半。
5. 代码洁癖:按业务域分家
很多项目是按技术类型分的(比如所有的 Actions 放在一起),结果改个购物车功能要跨 5 个文件夹。 我们直接按业务域切分:Product、Order、Pay。 每个目录下,再细分 Ticket(门票)、Goods(实物)。这样划分后,多人协作时很少冲突——做支付的人绝不会误触做商品详情的代码。物理隔离,各司其职。
6. 国际化:不仅仅是翻译
做跨境电商,最怕的不是翻译文案,而是那些隐形的坑:货币符号、日期格式、时区。 我们引入了 react-intl-universal 处理多语言,同时封装了 jegoCtx 上下文对象。它就像个管家,统一管理所有跟"地区"有关的展示逻辑。不管你是美元还是日元,是 MM/DD 还是 DD/MM,管家说了算,组件不需要操心。
7. 给组件"减负"
React 组件应该只负责"画皮",不要负责"算账"。 以前我们在组件里写了太多 if (price > 100 && user.vip) ... 这种逻辑,太丑了。 现在我们引入 Model 层(如 CouponModel)。后端返的数据,先在 Model 里洗个澡,转换成好用的领域模型。组件拿到的是处理干净的数据,直接渲染就行。 逻辑下沉,视图上浮,世界清静了。
总结
这套架构没什么"黑科技",核心就在于平衡。 我们在可维护性、首屏性能和业务扩展性之间,找到了一条最适合当下业务的路。
架构不是为了炫技,而是让团队少加班、用户少等待。能做到这点就够了。