老项目的外链太多?我是这么处理的
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">作者:苏梓铭</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">背景介绍</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">日前</span>,古茗前端团队内部统一采用了 React 技术栈,所有新项目和<span style="color: black;">基本</span>建设均基于 React 框架<span style="color: black;">研发</span>。然而,许多老旧的 Vue 应用仍在<span style="color: black;">运用</span>和运行,<span style="color: black;">因此呢</span><span style="color: black;">咱们</span><span style="color: black;">必须</span>进行项目迁移,统一技术栈,减少<span style="color: black;">研发</span>认知<span style="color: black;">包袱</span>,接轨现有基建,<span style="color: black;">加强</span>可<span style="color: black;">守护</span>性,以便更好地满足业务新需求。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">尤其</span>地,以笔者负责的学院业务域为例,其业务<span style="color: black;">拥有</span>这么一个特点:存在众多<span style="color: black;">外边</span>链接<span style="color: black;">转</span>场景(例如,发布给加盟商的考试待办链接、张贴在店内设备上的资料二维码等)。在迁移老项目的过程中,<span style="color: black;">咱们</span><span style="color: black;">亦</span>要格外关注外链治理。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本文<span style="color: black;">重点</span>讲述笔者治理老项目存量外链投放问题的<span style="color: black;">处理</span>思路。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">状况</span>及<span style="color: black;">目的</span>分析</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在迁移老项目的过程中,<span style="color: black;">咱们</span><span style="color: black;">发掘</span>了许多问题:</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">外链更新的<span style="color: black;">转</span>问题</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span>对外投放的链接<span style="color: black;">一般</span><span style="color: black;">拥有</span>很强的时效性,例如给加盟商发送的考试链接等,<span style="color: black;">况且</span>这些外链是静态、<span style="color: black;">没</span>法直接修改的,<span style="color: black;">因此呢</span><span style="color: black;">咱们</span><span style="color: black;">一般</span>会采用重定向<span style="color: black;">规律</span>,将旧路由映射到新路由,让老外链<span style="color: black;">亦</span>能<span style="color: black;">转</span>到新页面。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在老项目的导航守卫里,<span style="color: black;">已然</span><span style="color: black;">累积</span>了<span style="color: black;">海量</span>的重定向<span style="color: black;">规律</span>,并且<span style="color: black;">每一个</span>模块都有一套自己单独的重定向策略,如下图所示:</p><img src="https://mmbiz.qpic.cn/sz_mmbiz_png/TpB2QHJbiaicGQMVHSdQ5PlKvRD0vRY6IZU4QIGORKbYqAmHGQ7I2iaxzSrL2Xe8MZMiau9oHmgEWXsib0ER82CrPYw/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">现有<span style="color: black;">规律</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此呢</span>,当老项目迁移完成下线后,<span style="color: black;">已然</span>投放出去的老链接将会<strong style="color: blue;"><span style="color: black;">没</span>法<span style="color: black;">拜访</span></strong>(<span style="color: black;">由于</span>所有的重定向<span style="color: black;">规律</span>都在老项目内完成)</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其次,外链投放还存在<span style="color: black;">必定</span>的不确定性,有的<span style="color: black;">乃至</span>是产研团队自己都不<span style="color: black;">晓得</span>的外链投放,这就<span style="color: black;">引起</span><span style="color: black;">咱们</span>有时对页面路由进行改造后,会得到其他业务域的业务反馈。</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">路由传参的心智<span style="color: black;">包袱</span></span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在分析页面迁移时,<span style="color: black;">咱们</span><span style="color: black;">重视</span>到新旧页面的路由经常<span style="color: black;">经过</span> URL 传递<span style="color: black;">海量</span>参数。缺乏统一规范来<span style="color: black;">守护</span>这些参数,使得页面的<span style="color: black;">守护</span>变得<span style="color: black;">繁杂</span>。</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">目的</span>分析</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">针对<span style="color: black;">以上</span>问题<span style="color: black;">状况</span>,<span style="color: black;">咱们</span><span style="color: black;">能够</span>总结出如下<span style="color: black;">目的</span>:</p><strong style="color: blue;">老项目路由重定向</strong>:将重定向<span style="color: black;">规律</span>做<span style="color: black;">保存</span>,实现对历史外链的兼容<strong style="color: blue;">操作可感知</strong>:用户的<span style="color: black;">拜访</span>应当有完善的链路<span style="color: black;">能够</span>被感知到,用户<span style="color: black;">拜访</span>了老项目路由时,<span style="color: black;">咱们</span><span style="color: black;">必须</span>能够记录日志,当用户<span style="color: black;">拜访</span> 404 时<span style="color: black;">咱们</span><span style="color: black;">必须</span><span style="color: black;">晓得</span>是哪个页面报了 404,并且自动<span style="color: black;">即时</span>地告警同步给业务 Owner 排查。<strong style="color: blue;">统一技术栈/统一规范</strong>:<span style="color: black;">咱们</span>应当全链路接入前端基建,<span style="color: black;">运用</span>最新的统一技术栈,针对路由<span style="color: black;">转</span>等场景<span style="color: black;">必须</span>有一个统一的技术规范<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">知道</span>了几个基本<span style="color: black;">目的</span>后,<span style="color: black;">咱们</span>就<span style="color: black;">能够</span>着手进行代码结构设计了</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">核心代码设计与实现</span></h2>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">路由重定向</span></h3><span style="color: black;"><span style="color: black;">怎样</span>转发——Nginx, NodeJS OR JavaScript?</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在设计重定向转发<span style="color: black;">方法</span>之前,<span style="color: black;">咱们</span><span style="color: black;">首要</span><span style="color: black;">思虑</span>的是直接<span style="color: black;">运用</span> Nginx 或 Node 做转发,但<span style="color: black;">因为</span><span style="color: black;">日前</span>两个 H5 项目都<span style="color: black;">运用</span> Hash 路由,而<span style="color: black;">咱们</span><span style="color: black;">晓得</span> Hash 路由 # 后面的参数是不会发送给服务器的,<span style="color: black;">因此呢</span> Nginx 和 Node <span style="color: black;">乃至</span>都<span style="color: black;">没</span>法读取到路由本身,更<span style="color: black;">不消</span>提做重定向了,<span style="color: black;">因此呢</span><span style="color: black;">咱们</span>确定了<span style="color: black;">最后</span><span style="color: black;">处理</span><span style="color: black;">方法</span>还是交由客户端处理,Nginx 层只做映射路径的转发(将老项目 / 的路径直接转发到 /college 下<span style="color: black;">就可</span>)</p><span style="color: black;">API 调用方式设计</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">设计一个简洁明了的 API 调用方式<span style="color: black;">一样</span>是技术<span style="color: black;">方法</span>的<span style="color: black;">要紧</span>一环。基于配置化的思想,<span style="color: black;">咱们</span><span style="color: black;">必须</span>把原有的导航守卫中 if else 的糅杂一团的重定向<span style="color: black;">规律</span>,改<span style="color: black;">导致</span><span style="color: black;">守护</span>一个路由<span style="color: black;">转</span>表。即<span style="color: black;">经过</span>配置固定格式的原 URL 和<span style="color: black;">目的</span> URL 来声明重定向,调用方式大致如下:</p><span style="color: black;">const</span> redirector = <span style="color: black;">new</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Redirector()</p> .register(<span style="color: black;">/knowledge/learnList</span>, <span style="color: black;">/pages/material-list/index</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">)</p> .register(<span style="color: black;">/knowledge/detail/:id</span>, <span style="color: black;">/pages/material-detail/index?id=:id</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这般</span>一来<span style="color: black;">咱们</span>注册重定向就变得非常简单。注册完成之后,<span style="color: black;">咱们</span>就<span style="color: black;">能够</span><span style="color: black;">经过</span>调用redirector.run<span style="color: black;">办法</span>来执行一次重定向,接下来是<span style="color: black;">详细</span>的代码实现。</p><span style="color: black;">重定向路由<span style="color: black;">转</span>表设计</span><span style="color: black;">名词解析</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在设计<span style="color: black;">转</span>表之前,<span style="color: black;">咱们</span><span style="color: black;">必须</span><span style="color: black;">知道</span>,路由传参有两种类型的方式,一种是 params,一种是 query。其中 params 是<span style="color: black;">做为</span>路由路径的一部分存在的,<span style="color: black;">例如</span> /pending/list/1234567 中的 1234567 就<span style="color: black;">表率</span>着 id 这个参数;而 query <span style="color: black;">便是</span>在 ? 之后的键值对参数了,例如 /pages/list/index?id=1234567 这种形式。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">上文的 API 设计中,仅做了 params 类型的传参映射,而<span style="color: black;">针对</span>页面的其他参数是<span style="color: black;">无</span>处理的,<span style="color: black;">这儿</span><span style="color: black;">咱们</span><span style="color: black;">需求</span>,新老页面的出入参要保持相同,<span style="color: black;">这般</span>就<span style="color: black;">能够</span>直接共用一套 query 参数,减轻<span style="color: black;">咱们</span>的<span style="color: black;">研发</span>成本</p><span style="color: black;"><span style="color: black;">怎样</span>转换路由正则匹配式</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">原先的 Vue2 老项目实现重定向是利用 vue-router 自带的实现。经过调研,<span style="color: black;">咱们</span><span style="color: black;">选取</span><span style="color: black;">运用</span> path-to-regex 库做路由解析,它是 Vue-Router 等众多知名路由库的底层依赖库,正如其名,它能够将路由转化成正则表达式去匹配链接,并且支持动态路由参数等许多功能,官方示例如下:</p><img src="https://mmbiz.qpic.cn/sz_mmbiz_png/TpB2QHJbiaicGQMVHSdQ5PlKvRD0vRY6IZ5qLN5C1h9uXZHRf2dMROlk0iazXYUvW9WmDESic5lzwkdQIib5pMduF2w/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">官方示例<span style="color: black;">实现 Redirector 类</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">path-to-regex <span style="color: black;">拥有</span>非常简单易用的 API,<span style="color: black;">针对</span><span style="color: black;">咱们</span>检测和提取路由参数的需求<span style="color: black;">来讲</span><span style="color: black;">已然</span>完全足够,<span style="color: black;">咱们</span><span style="color: black;">能够</span><span style="color: black;">经过</span>调用 match <span style="color: black;">办法</span>获取到解析路由的正则表达式,并据此实现一个 Redirector 类:</p><span style="color: black;">import</span>{ history }<span style="color: black;">from</span> <span style="color: black;">@tarojs/router</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">import</span> Taro <span style="color: black;">from</span> <span style="color: black;">@tarojs/taro</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">import</span> { match, MatchFunction } <span style="color: black;">from</span> <span style="color: black;">path-to-regexp</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">type</span> RegisterPath = <span style="color: black;">`/<span style="color: black;">${<span style="color: black;">string</span>}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">interface</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">RouteObject {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> matchFn: MatchFunction;</p> target: <span style="color: black;">string</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p><span style="color: black;">class</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Redirector {</p> <span style="color: black;">// 本地注册的路由<span style="color: black;">转</span>配置</span> <span style="color: black;">private</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> routes: RouteObject[] = [];</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">register(oldPath: RegisterPath, newPath: RegisterPath): Redirector {</p> <span style="color: black;">this</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">.routes.push({</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> matchFn: match(oldPath),</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> target: newPath,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p> <span style="color: black;">// 链式调用</span> <span style="color: black;">return</span> <span style="color: black;">this</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p> redirect(path: <span style="color: black;">string</span>, query = ): <span style="color: black;">void</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">this</span>.routes.some(<span style="color: black;">(<span style="color: black;">{ matchFn, target }</span>) =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> result = matchFn(path);</p> <span style="color: black;">if</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> (result) {</p> <span style="color: black;">// 替换路由参数</span> <span style="color: black;">Object</span>.entries(result.params).forEach(<span style="color: black;">(<span style="color: black;"></span>) =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p>target = target.replace(<span style="color: black;">`:<span style="color: black;">${key}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">, value);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p> <span style="color: black;">// 处理 query,Taro 路由的<span style="color: black;">必须</span>直接拼在参数上</span> target = <span style="color: black;">`<span style="color: black;">${target}</span><span style="color: black;">${target.includes(<span style="color: black;">?</span>) ? <span style="color: black;">&</span> : <span style="color: black;">?</span>}</span><span style="color: black;">${query}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;">// 执行重定向</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Taro.redirectTo({ url: target });</p> <span style="color: black;">return</span> <span style="color: black;">true</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p> <span style="color: black;">return</span> <span style="color: black;">false</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p> run(): <span style="color: black;">void</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span> = location.hash.slice(<span style="color: black;">1</span>).split(<span style="color: black;">?</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> <span style="color: black;">this</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">.redirect(path, query);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p><span style="color: black;">// 直接注册重定向后导出实例<span style="color: black;">就可</span></span><span style="color: black;">const</span> redirector = <span style="color: black;">new</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Redirector()</p> .register(<span style="color: black;">/knowledge/learnList</span>, <span style="color: black;">/pages/material-list/index</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">)</p> .register(<span style="color: black;">/knowledge/detail/:id</span>, <span style="color: black;">/pages/material-detail/index?id=:id</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">export</span> <span style="color: black;">default</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> redirector;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其基本思路<span style="color: black;">便是</span><span style="color: black;">经过</span> match <span style="color: black;">办法</span>生成的正则表达式,匹配摘出原 URL 中的路由参数,并拼接和替换到新的 URL 上</p><span style="color: black;">何时执行——完整的一次重定向链路</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这次</span>迁移的 C 端 H5 微应用<span style="color: black;">同期</span>由两个项目<span style="color: black;">构成</span>,分别是<span style="color: black;">运用</span> Vue2 技术栈的老项目和<span style="color: black;">运用</span> Taro React 的新项目。两个项目<span style="color: black;">经过</span> Nginx 转发到同一个域名的<span style="color: black;">区别</span>路由下:老项目映射在 / 根目录,而新项目则是映射在 /college 目录下,所处同一个域,从而<span style="color: black;">能够</span>共享<span style="color: black;">有些</span>本地数据如 localStorage、sessionStorage 等。</p><span style="color: black;">(1)用户<span style="color: black;">拜访</span>,Nginx 层转发</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">以用户外链<span style="color: black;">转</span>到老项目路由为例:</p>https://host/<span style="color: black;">#/knowledge/learnList?rankId=aaa&ListName=bbb</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span>老页面会下线,<span style="color: black;">拜访</span>服务时 Nginx 正常匹配其他路由,兜底匹配根路由 /直接转发到 /college 上:</p>https://host/college/<span style="color: black;">#/pages/material-list/index?rankId=aaa&ListName=bbb</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此呢</span>用户在 Nginx 层被<span style="color: black;">第1</span>次重定向到:</p>https://host/college/<span style="color: black;">#/knowledge/learnList?rankId=aaa&ListName=bbb</span><span style="color: black;">(2)执行重定向</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">重定向后,<span style="color: black;">咱们</span><span style="color: black;">必须</span>在项目内解析路由参数后拼接<span style="color: black;">转</span>。<span style="color: black;">这儿</span> Taro <span style="color: black;">没</span>法匹配到页面,<span style="color: black;">然则</span> app.tsx 中仍然会执行代码<span style="color: black;">规律</span>,<span style="color: black;">因此呢</span><span style="color: black;">咱们</span>在新项目的 app.tsx 中执行重定向</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">// app.tsx</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">import redirector from "@/utils"</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">function App({ children }){</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> useMount(() => {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> redirector.run()</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> })</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">必须</span>监听路由变化吗?</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span><span style="color: black;">能够</span><span style="color: black;">经过</span> history.listen <span style="color: black;">办法</span>监听路由的变化,并且在每次路由改变时都去匹配一次重定向:</p>history.listen(<span style="color: black;">(<span style="color: black;">{ location }</span>) =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{ pathname, search } = location;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> redirector.redirect(pathname, search);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">});</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">但<span style="color: black;">实质</span>上<span style="color: black;">咱们</span>并不<span style="color: black;">必须</span>做到这么全面,<span style="color: black;">咱们</span>完全<span style="color: black;">能够</span><span style="color: black;">保准</span>在学院新项目里不会<span style="color: black;">显现</span>老项目的路由,<span style="color: black;">因此呢</span><span style="color: black;">倘若</span>用户<span style="color: black;">已然</span>进入了应用里,就不会<span style="color: black;">经过</span>路由<span style="color: black;">转</span>进入到老项目了。<span style="color: black;">倘若</span>监听了路由变更反而会带来额外的性能开销。</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">操作感知</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span><span style="color: black;">无</span>触发重定向或是重定向失败,都会<span style="color: black;">引起</span><span style="color: black;">出现</span> 404 错误,<span style="color: black;">咱们</span>会上报一次错误日志。而只要触发了重定向,<span style="color: black;">咱们</span>就会上报一次重定向记录</p><span style="color: black;">404 感知</span><span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">App</span>(<span style="color: black;">{ children }</span>) </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> usePageNotFound(<span style="color: black;">(<span style="color: black;">e</span>) =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span> tag = <span style="color: black;">PAGE_NOT_FOUND</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;">const</span> log = <span style="color: black;">`path=<span style="color: black;">${e.path}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Slardar.logger()?.error(log, tag);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Taro.redirectTo({</p> url: <span style="color: black;">`/pages/404/index?from=<span style="color: black;">${e.path}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }) </p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">详细</span>操<span style="color: black;">做为</span>:在 App.tsx 下新增 usePageNotFound hook,调用 Taro 原生路由回调,<span style="color: black;">经过</span>数据平台上报 error 日志,并在 404 页面展示提示和链接,引导用户回到学院应用和反馈</p><img src="https://mmbiz.qpic.cn/sz_mmbiz_png/TpB2QHJbiaicGQMVHSdQ5PlKvRD0vRY6IZL8E6PUUibicia7hxBXiacJAvsLGF1rKddduR6a87XnPIVRjyF8pcIs8z6w/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">404 页面<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span><span style="color: black;">能够</span>在数据中心查看上报的日志信息等</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">关联</span><span style="color: black;">文案</span>:<a style="color: black;">古茗是<span style="color: black;">怎样</span>做前端数据中心的 - 掘金</a></p><img src="https://mmbiz.qpic.cn/sz_mmbiz_png/TpB2QHJbiaicGQMVHSdQ5PlKvRD0vRY6IZNS6NuouYia1AWOZakSSTPy8CVAekRAwOkiccJ2Q0ClyXT27OAF48eCTA/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">日志<span style="color: black;">查找</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span> 404 错误<span style="color: black;">通常</span>不会偶现,只要<span style="color: black;">显现</span>就<span style="color: black;">表率</span>页面路由或是外链投放存在问题。<span style="color: black;">咱们</span><span style="color: black;">经过</span>配置错误告警策略,来<span style="color: black;">即时</span><span style="color: black;">通告</span><span style="color: black;">研发</span>查看日志,<span style="color: black;">发掘</span>并<span style="color: black;">处理</span>路由问题。</p><img src="https://mmbiz.qpic.cn/sz_mmbiz_png/TpB2QHJbiaicGQMVHSdQ5PlKvRD0vRY6IZzTax8kc0IMevEkMhJC13T0Oj8IPRCoMmeOicibnN9oTWXS3x8zSOAz0A/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">告警配置<span style="color: black;">重定向感知</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在执行重定向的时候上报执行日志,提交原路由和<span style="color: black;">目的</span>路由的完整信息</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">class Redirector {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">private routes: RouteObject[] = [];</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> register(oldPath: RegisterPath, newPath: RegisterPath): Redirector {}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> redirect(path: string, query = ): void {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">this.routes.some(({ matchFn, target }) => {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> const result = matchFn(path);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> if (result) {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Object.entries(result.params).forEach(() => {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">target = target.replace(`:${key}`, value);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> target = `${target}${target.includes(?) ? & : ?}${query}`;</p><span style="color: black;">+ const tag = PAGE_NOT_FOUND;</span><span style="color: black;">+ const log = `from=${path}&to=${target}`;</span><span style="color: black;">+ Slardar.logger()?.info(log, tag);</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Taro.redirectTo({ url: target });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> return true;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> return false;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> run(): void {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">const = location.hash.slice(1).split(?);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> this.redirect(path, query);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这次</span><span style="color: black;">咱们</span>把新迁移的页面路由和已有的重定向路由<span style="color: black;">所有</span>加入到配置表中,并且在重定向<span style="color: black;">出现</span>时上报<span style="color: black;">拜访</span>的链接和<span style="color: black;">转</span>的链接,收集 30 日的数据后再进行一次整理,观察线上流量分布,<span style="color: black;">逐步</span>下掉<span style="color: black;">无</span><span style="color: black;">运用</span>的重定向,减少<span style="color: black;">守护</span>成本</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">统一规范——路由<span style="color: black;">转</span><span style="color: black;">办法</span></span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span>老项目的迁移过程中<span style="color: black;">触及</span>到了<span style="color: black;">海量</span>的路由传参,经常会<span style="color: black;">显现</span>链接里挂了一大堆参数,<span style="color: black;">实质</span>页面里却<span style="color: black;">基本</span><span style="color: black;">无</span>用到的<span style="color: black;">状况</span>,<span style="color: black;">咱们</span>很难分辨<span style="color: black;">那些</span>路由参数是有效的,<span style="color: black;">那些</span>路由参数又是<span style="color: black;">能够</span>舍弃的。<span style="color: black;">因此呢</span>,<span style="color: black;">咱们</span>在本业务域内的移动端项目内做了如下统一规范:</p>针对页面<span style="color: black;">守护</span> TS 入参类型定义;路由<span style="color: black;">转</span>和获取入参<span style="color: black;">运用</span>公共<span style="color: black;">办法</span>,传入页面入参的类型定义<span style="color: black;">做为</span>泛型参数,规范页面<span style="color: black;">转</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">详细</span>调用方式如下:</p><span style="color: black;">转</span>页面<span style="color: black;">运用</span> formatUrlParams 格式化 query 参数<span style="color: black;">import</span> { BaseAssignmentParams } <span style="color: black;">from</span> <span style="color: black;">"@/pages/assignment/index/index"</span><span style="color: black;">const</span>handleClick =<span style="color: black;">(<span style="color: black;">assignment: CourseAssignmentItem</span>) =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> baseQuery = formatUrlParams({
</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> trainingId: trainingDetail.id,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> semesterId: trainingDetail.semesterId,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">assignmentId: assignment.id,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Taro.navigateTo({</p> url: <span style="color: black;">`/pages/assignment/index/index?<span style="color: black;">${baseQuery}</span>`</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> });</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">};</p>承接页面<span style="color: black;">运用</span> getUrlParams 反序列化路由参数<span style="color: black;">export</span> <span style="color: black;">interface</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">AssignmentParams {</p> <span style="color: black;">/** 培训 id */</span> trainingId: <span style="color: black;">string</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;">/** 学期 id */</span> semesterId: <span style="color: black;">string</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;">/** 任务 id */</span> assignmentId: <span style="color: black;">string</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p><span style="color: black;">const</span> Assignment: React.FC = <span style="color: black;"><span style="color: black;">()</span> =></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> {</p> <span style="color: black;">const</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{ semesterId, trainingId, assignmentId } = getUrlParams();
</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p><span style="color: black;">export</span> <span style="color: black;">default</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Assignment;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如此一来,就在两个页面成功<span style="color: black;">经过</span>类型系统架起了一道桥梁,<span style="color: black;">倘若</span>页面新增或是删改了入参,都<span style="color: black;">能够</span><span style="color: black;">经过</span>静态类型分析在<span style="color: black;">研发</span><span style="color: black;">周期</span>就得到提示,修改路由出入参时的心智<span style="color: black;">包袱</span><span style="color: black;">显著</span>减小,项目可<span style="color: black;">守护</span>性得到了<span style="color: black;">明显</span><span style="color: black;">加强</span>。</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">完整流程图</span></h3><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">完整流程图<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">总结</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本文介绍了笔者在做业务项目迁移的时候处理外链<span style="color: black;">规律</span>以及对项目内的页面出入参和<span style="color: black;">转</span>场景进行统一化治理的思路,<span style="color: black;">期盼</span>能给<span style="color: black;">一样</span>被历史项目和技术债<span style="color: black;">熬煎</span>的<span style="color: black;">朋友</span>们<span style="color: black;">供给</span><span style="color: black;">有些</span>可行性<span style="color: black;">意见</span>,<span style="color: black;">亦</span>欢迎<span style="color: black;">大众</span>在评论区<span style="color: black;">一块</span>交流,<span style="color: black;">一起</span>进步</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">最后</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> 回顾历史,我们感慨万千;放眼未来,我们信心百倍。 “沙发”(SF,第一个回帖的人)
页:
[1]