最近,我们团队开源了一套沉淀了2年的前端SPA架构框架,主要是用来解决动态路由的问题。我们的思路来源于后端,采用中间件的设计模式来架构整个框架。我们的原则是让大家快速开发一个SPA单页应用,只关心业务逻辑,其他的行为都可以帮助处理掉。

其实我们的开源比较匆忙,从很多方面看还是有些不标准的,但是之后我们会严格按照标准的规范和流程走下去,给大家一份稳定的架构。对于现在开始关注我们团队的小伙伴,我表示非常的感谢。有大家的支持,我们会做的更好。

Miox到底要解决什么问题?

这个问题从我们设计的初衷来说,就是解决所有路由的问题。在业界,其实大家都普遍认可一对一的路由模式,从而生产出了很多路由体系,比如vue-routerreact-router。他们都是非常不错的架构,从某种意义上来说,引领了前端路由的前进。很多小伙伴都是直接使用他们的全家桶来开发项目,也得到了很好的效果。

我不确定大家是否考虑过一个问题,当一个用户从登陆页面A登陆后进入B,再回到A页面的情况。一对一的静态路由其实理论上最终会将A页面显示为未登录,这是完全正确的,但是逻辑上它应该是一个登录的页面。静态路由无法区分环境变量对页面选择的影响,只能通过hook等手段来将页面内容替换掉。理论上,我们借助后端的写法应该是这样的逻辑:

route.get('/a', ctx => {
    if (global.logined) {
        ctx.render(webveiwA);
    } else {
        ctx.render(webviewB);
    }
})

  

我们需要根据周边的环境变量去自动选择该渲染哪个页面,如此的逻辑才是我们想要的。所以我们会根据这样的思路来设计动态路由。在nodejs的世界中,这种模式已经非常常见,比如express-routerkoa-router,都是采用这种设计思路来实现动态话的路由体系。我观察了前端的发展,都没有提出在前端实现这样的逻辑。于是,我们便开始研究如何将这种思路架设在前端使用,来获得更理想的逻辑体验。

Miox从来都不是依赖任何MVX框架来实现

为什么这么说呢?原因非常简单。在公司里面,我们大概有90%的H5业务都是采用Miox来实现的。我们的技术栈其实是Vue,因为Miox对Vue的结合太过深入,所以自然有部分小伙伴认为Miox是基于Vue来开发的,也就是说Miox是依赖着Vue?其实不是,Miox并不依赖任何框架实现。我来举个列子:

我们的电脑,如果换了一个显卡,那么必须要装显卡驱动。根据不同的显卡驱动,表现也不同。如果我们将Vue当作一个显卡,而Miox当作我们的电脑,那么我们需要一份显卡驱动来让整台电脑接受这块显卡。

所以我提出一个概念,就是渲染驱动的概念。Vue仅仅是我们Miox的一个渲染引擎,用来渲染页面的,可以理解为模板。我们还需要一份驱动告诉Miox,来说明Vue的渲染是如何在Miox实现的。这部分可以从这里看明白。当然,不仅仅是Vue,我们还能够将React接入到Miox中。理论上,只要能提供对应的渲染驱动,都可以将任意的渲染引擎接入到Miox中来使用。自然的,大家的书写都将会变成那种引擎的书写方式。这就是我们的插拔式设计。在公司里面使用的时候,我们不必在意使用何种渲染引擎,Miox都可以支持,同时帮您管理好整个路由体系。

基于中间件实现

在前端,如果我们能够用中间件来拦截整个逻辑过程的话,对开发是相当有利的,不仅仅在代码层面能够提高可读性,同时可以在具体业务层面提高效率。我们用后端路由逻辑来举个例子:

当我们遇到一些API都是需要经过登录验证的时候,我们可以将/authorize的路由前缀都使用中间件统一处理。其他的都不走验证逻辑。

const Authorize = require('./auth');
const AuthorizeApi = require('./auth/routes');
route.use(
    '/authorize', 
    Authorize.connect(), // Authorize.connect是统一的验证逻辑代码
    AuthorizeApi.routes(), 
    AuthorizeApi.allowedMethods()
);

  

如此当通过/authorize的路由都需要经过Authorize.connect()来验证是否具有权限。这使得代码非常简洁易懂。

Miox的设计便是如此,通过这种中间件的架构,使得我们在前端获得了统一拦截处理的能力。在实际生产中,我们很多地方都用到了中间件来处理统一的校验逻辑,使得代码维护性得到很大地提升。

那么如果不使用呢?我们需要在进入页面的时候,每个页面中都要嵌入一段代码来处理权限问题,不仅仅代码量增加,而且对于之后的维护,可能会产生漏改的问题。

具体想了解中间件的小伙伴,我推荐去看下koa-router

缓存页面得到更好的渲染性能

说到缓存,这个话题过于庞大,对于Miox的缓存机制,我只能简单介绍一下,有兴趣的小伙伴可以看下源码

在开发过程中,特别是对于开发移动端页面,我们需要保存前一个页面滚动位置,那么我们在切换到另一个页面的时候是不能将前一个页面销毁的,原因是我们希望回到前一个页面的时候还是停留在之前滚动的位置。那么我们需要缓存这个页面来确保位置的不改动。Miox模拟了history的部分API,同时增加了一层页面堆栈。我们需要维护这层页面堆栈来确保页面的可溯性。每次我们通过一种算法来动态比较路由与页面的关系,从而从这个堆栈中选出我们想要的缓存页面。当然,没有这个对应关系的时候,我们自然是要创建的。我们基于尽最大可能限度复用页面的宗旨,来缓存这些页面与路由的关系。

可能有人要问,如果缓存过多,对于页面的切换会有性能上的影响吧?是的,过多的页面缓存也是阻碍性能的关键。这里我们进行了缓存个数的优化。在启动miox服务的时候,我们有一个配置的参数max,一般默认为一个,当然,大家也可以自己自由设置最大个数,来保障缓存的性能问题。

历史遗留问题:history方向问题的解决方案

在History中,我们都承认无法判断出当前浏览器行为的方向性,所以无法给出我们想要的方向来自动做页面切换的效果。为了解决这个问题,我们搜集了业界的解决方案,采用sessionStorage来模拟history堆栈,从而解决这个问题(新history的API中已经增加了history.index动态属性来告诉我们现在位于堆栈中的位置)。我们将此方案整合到了Miox中,并且对其加强,来告诉动画引擎这次行为在浏览器中是如何表现的。自然,动画引擎就能够根据这个来自动切换页面的动画,达到自动处理的效果。

官方提供了一个简单的模块来支持动画,当然小伙伴想要自定义动画也是非常简单的,具体见这里

独立的页面生命周期

在传统的MVX框架中提供了组件的生命周期,我们在某种意义上也认为是页面的生命周期,但是我们对比原生IOS的周期行为,还是有所欠缺的。比如说active生命周期。这个是什么意思呢?我来举例说明:

当一个页面被推入后台,又被唤起的时候,我们根本不知道它是不是再一次被激活,我们只能知道页面又一次被进入,第二次进入的概念是需要很多代码来辅助完成的。而在传统框架中,很难触发再一次的mounted生命周期,因为页面已经被mounted过了。Miox提供了这样的生命周期的定义。

// use vue.js
export default Vue.extend({
    mounted() {
        this.$on('webview:active', this.activeLife);
    },
    methods: {
        activeLife() {
            console.log('我被唤起了');
        }
    }
})

  

当然,我们也可以将这些生命周期直接抛到全局去,用于全局的监控。

app.on('webview:mounted', webview => {
    console.log(webview);
})

  

对于前置的生命周期,我们同样提供了以下的生命周期来辅助:

  • webview:enter
  • webview:leave
  • webview:beforeEnter
  • webview:beforeLeave

这些周期能够让你很好地掌控整个过程,对于自动埋点什么的功能非常实用。

服务端渲染

目前主流的架构都支持了服务端渲染来增强SEO的能力,那么对于Miox而言,也需要支持他们的服务端渲染。考虑到Miox自身会给渲染出来的内容包裹一些代码,所以,我们需要自己实现SSR。当然,渲染引擎的SSR实现是交给自己来完成的。也就是说我们需要给他包裹一层SSR渲染。

Miox暂时支持Vue的SSR渲染,后续会逐步添加对于React的SSR渲染。还有比如百度的san.js其实也可以接入进来实现SSR渲染。服务端渲染并不是太麻烦,如果大家能够掌握Miox的运行原理的话。

最后

对于开源,我们团队内部做了很多努力,也咨询了很多大牛,希望能够给大家创造出一份简易开发的架构来帮助大家完成业务。目前,团队后续计划如下:

  • 完善SSR的文档
  • 规范化Github上的git message
  • 维护Github上的Issues和PR
  • 单测和代码覆盖率增强
  • 对路由架构更多思考来完善Miox
  • 提供Pc端的演示demo
  • 提供Miox实际开发场景下的开发代码示例

希望大家看到这篇文章后可以支持我们,给我们多提供一些意见和建议,让我们共同将Miox完善下去。喜欢的小伙伴,帮忙点个Star。

项目开源在 GitHub: 51nb/Miox

 

出处:掘金专栏-51信用卡前端团队 https://juejin.im/post/5a0eee94f265da430702d8e0