带你了解基于 Vue 的微服务解决方案 Genesis - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
1340641314
V2EX    分享创造

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

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

    前言

    这几年,因为忙于业务,都很少在社区发言了,直到今年要重构整个 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     Solana     2931 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 12:52 PVG 20:52 LAX 05:52 JFK 08:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86