V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
1340641314
V2EX  ›  分享创造

带你了解基于 Vue 的微服务解决方案 Genesis

  •  
  •   1340641314 ·
    lzxb · 2020-06-28 10:06:46 +08:00 · 1234 次点击
    这是一个创建于 1638 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    这几年,因为忙于业务,都很少在社区发言了,直到今年要重构整个 FOLLOWME5.0 网站,为了满足业务发展的需要,才设计了 Genesis ,顺势推出了基于 Vue 的微服务解决方案。

    在设计之初,不是没有考虑过社区的一些解决方案,但是无一例外的都是基于客户端聚合的微前端解决方案,和我们真正的需求还差之很远。

    需求

    • 国际化
      FOLLOWME5.0 之前,有很多项目都是采用 CSR 渲染的,导致页面被分享给外国网站或者 APP 时,页面的标题和描述,呈现出来的是中文的,导致在海外推广时,非常的不利于传播。
      所以,在这一点上,我们都否定了基于客户端的微前端聚合方案,起点必须是立足于 SSR 的渲染,可以针对每一个页面进行标题、描述的国际化。

    • SEO
      在流量为王的时代,通过 SEO 的优化,仍然是一个获取免费流量重要的渠道。我们内部也尝试过,去做一些 SEO 相关的项目,采用的技术就是最原始的那种后端模板渲染的方式,也取得了一些成绩,但是也带来了很高的维护成本。当时我们有一个网站通用的头部,基于 Vue 的维护了一套,基于后端模板渲染的也维护了一套。
      所以,我们需要有一个 Vue 的服务,可以提供一个网站的头部组件,由后端模板渲染的服务区调用它,嵌入到页面中。

    • 老项目迁移
      很多老的项目,还停留在 Webpack2.0 的版本,跑起来经常出现各种问题,有 CSR 渲染的,也有 SSR 渲染的
      所以,我们需要新的技术架构上,对老项目最好是无入侵的,支持 CSR 的渲染,可以解决部分 CSR 渲染页面的标题和描述的国际化问题。

    • 无刷新跳转
      今年网站重构最大的目的之一,就是要解决之前架构的弊端,要做到页面与页面之间的无刷新跳转。这个问题看似很简单,只需要在一个项目中使用 vue-router 开发即可,但是 FOLLOWME 有成百上千个页面,如果只做到一个应用中,在基于 SSR 的前提下,只要有一个地方出现了故障或者内存泄漏,对于整站来说都是一个不小的打击。或者只要每次发布,整站的那一瞬间都会挂掉
      所以,微服务的拆分,可以帮助我们分散风险,一个服务挂了不能影响到另外一个服务。

    • 公共组件的使用
      FOLLOWME5.0 之前,有个公共的网站头部,每个项目都是单独的导入到自己的项目中使用,随之而来的问题就是,每次导航有内容更新的时候,就不得不对十几个前端项目进行依赖的更新,重新构建镜像,然后发布。
      所以,我们需要可以对其它服务的组件进行调用,不管是 CSR 还是 SSR,对组件进行解耦,减少这种因为一个组件的更新,导致一大堆项目发布更新的问题。

    总结:
    我们需要一个可以支持 SSRCSR 渲染的微服务解决方案。

    有哪些应用场景?

    架构设计图 上面这张图,很好的诠释了 Genesis 微服务的工作原理,以及你使用 Genesis 可以做些什么。

    • 单页应用
      通过 CSR 或 SSR 渲染的能力,你可以构建一个单页应用,等到你的项目复杂到一定程度时,可以再考虑拆分服务。

    • 企业网站
      和使用后端渲染相比,你可以使用 Genesis 快速的构建一个 SSR 的企业网站。

    • 后端渲染的项目组件复用
      如果你们公司的技术栈是 Vue,为了 SEO 同时还存在着后端渲染的项目,部分页面需要组件复用时,你可以新增一个 SSR 服务,让后端渲染的项目去调用你的服务复用通用的组件。

    • 后台管理系统
      随着业务的发展,后台管理系统的将会慢慢的演变成巨石应用,在不改动老项目的情况下,你可以考虑在新的业务中,拆分成微服务,由老项目中去调用新服务的页面。

    • 大型的单页应用
      如果你的业务,达到和 FOLLOWME 一样的复杂程度,并且需要 SEO 、国际化,那么 Genesis 应该你目前最好的解决方案了。

    如何避免服务冲突?

    样式的冲突,在 Vue 中可以通过 scoped 来解决,全局的变量之类的,就需要通过开发的规范对开发人员进行约束了。

    路由管理

    和平时普通的使用方式一样,没有什么差别。当你一个页面两个服务都使用了路由时,才需要使用 Genesis 包装后的 vue-router 解决历史模式时,产生多次记录的 bug 。

    付费分享

    如果你们公司,对本套微服务解决方案感兴趣的话,在深圳地区,可以考虑到贵公司付费的分享一些在 FOLLOWME实践,GitHub 可以联系到我。有钱,我想可以让我更有动力把项目做得更好,毕竟深圳的房子还是太贵了。

    传送门

    8 条回复    2020-06-28 16:11:56 +08:00
    zlu1123
        1
    zlu1123  
       2020-06-28 10:18:03 +08:00
    技术小白只能膜拜~
    1340641314
        2
    1340641314  
    OP
       2020-06-28 10:34:05 +08:00
    @zlu1123 互相交流,共同成长。
    Asyncway
        3
    Asyncway  
       2020-06-28 12:24:31 +08:00
    不懂就问 感觉像是哪里配置错误 执行 npm run dev 报错 使用的是那个 demo

    ENOENT: no such file or directory, open '/myUrls/vue-genesis-micro-master/examples/ssr-home/dist/ssr-home/src/entry-client.ts'
    1340641314
        4
    1340641314  
    OP
       2020-06-28 14:00:02 +08:00
    @Asyncway 你这个是在 window 环境下运行的吗?是最新的代码吗?
    我刚才试着跑了一下,没问题。可以贴一下更完整的错误信息来看看。
    Asyncway
        5
    Asyncway  
       2020-06-28 14:09:52 +08:00
    @1340641314 我是在 mac 环境下跑的 我看上去貌似是 write 模块出了问题


    vue-genesis-micro-master % npm run dev

    > [email protected] dev /xxxx/vue-genesis-micro-master
    > ts-node genesis.dev -p=tsconfig.json

    (node:69425) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open '/xxxx/vue-genesis-micro-master/examples/ssr-common/dist/ssr-common/src/entry-client.ts'
    at Object.fs.openSync (fs.js:660:18)
    at Object.fs.writeFileSync (fs.js:1319:33)
    at Function.write.sync (/xxxx/vue-genesis-micro-master/node_modules/write/index.js:101:6)
    at writeDistSrcTemplate (/xxxx/vue-genesis-micro-master/node_modules/@fmfe/genesis-compiler/dist/plugins/template.js:52:29)
    at TemplatePlugin.beforeCompiler (/xxxx/vue-genesis-micro-master/node_modules/@fmfe/genesis-compiler/dist/plugins/template.js:54:9)
    at PluginManage.callHook (/xxxx/vue-genesis-micro-master/node_modules/@fmfe/genesis-core/dist/plugin.js:75:30)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:182:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:697:11)
    at main (/Users/gaoya/Documents/code/vue-genesis-micro-master/node_modules/ts-node/src/bin.ts:227:14)
    (node:69425) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 7)
    (node:69425) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    Asyncway
        6
    Asyncway  
       2020-06-28 14:10:27 +08:00
    @1340641314 猜测是不是跟 node 版本有关 我的版本为 9.11.0
    Asyncway
        7
    Asyncway  
       2020-06-28 14:23:11 +08:00
    @Asyncway @1340641314 node 版本切换到 12.18 最新的之后成功编译了
    1340641314
        8
    1340641314  
    OP
       2020-06-28 16:11:56 +08:00
    @Asyncway 可能有关系,因为我开发的时候,版本都是 12.x 以上的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   923 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 22:36 · PVG 06:36 · LAX 14:36 · JFK 17:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.