亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

微前端改造初探

KunMinX / 910人閱讀

摘要:我們繼續(xù)沿用了原來就有的,借此把融入整個(gè)微前端框架,而已經(jīng)改造的則不需要我們的開發(fā)團(tuán)隊(duì),分框架組和各個(gè)業(yè)務(wù)組。項(xiàng)目該項(xiàng)目是整個(gè)微前端項(xiàng)目的入口。本坑實(shí)踐它很大的理由也是用自己的方法初探微前端實(shí)踐方法的可行性。

在寫這篇文章的一個(gè)多月前,本坑還不知道微前端是什么,大概從字面上的含義是比較小的前端項(xiàng)目。

本坑開始實(shí)踐它,是由于工作要求。改造一個(gè)運(yùn)行多年,前端用jsp寫的服務(wù)平臺(tái)項(xiàng)目(以下簡(jiǎn)稱該平臺(tái))。改造它是改造它的前端架構(gòu)。改造它的原因是比較多人反饋,其頁面加載和渲染顯得吃力,頁面切換后首屏等待時(shí)間長(zhǎng)的問題,交互體驗(yàn)舒適度不可避免的下降了,特別是在老式電腦面前。

該平臺(tái)業(yè)務(wù)比較多,所以組長(zhǎng)希望前端框架組能把平臺(tái)中的前端部分分離出來,最好用當(dāng)下滿大街的Vue、能夠按照各個(gè)一級(jí)菜單分成若干前端子項(xiàng)目,用戶訪問依然是整體的項(xiàng)目,同時(shí)這一改造實(shí)施過程不需要重做一個(gè)、而是整個(gè)500多個(gè)頁面從局部開始、是逐步、兼容的,新舊同時(shí)運(yùn)行,直至整體被替換。(ps:不重做?這......科學(xué)嗎?)

看看,慢在哪里

其實(shí)大概知道慢在哪里,但是不知道究竟慢在具體哪個(gè)部分。和其他一以貫之的類似管理平臺(tái)布局并無不同。左邊導(dǎo)航欄,上面頂欄,右側(cè)內(nèi)容欄,整體頁面是一個(gè)index.jsp。上面提到的內(nèi)容欄是一個(gè)iframe,里面通過切換src來切換頁面。更多的業(yè)務(wù)造就更多頁面,更多頁面帶來更多的加載。加上長(zhǎng)時(shí)間沒有做好資源加載的管理,導(dǎo)致渲染一次頁面需要加載大量js,css或者多次加載同一個(gè)文件的情況。該平臺(tái)大量的配置頁面生成,是通過easyui的來做的。通過數(shù)據(jù)來創(chuàng)造整個(gè)頁面dom節(jié)點(diǎn),也拖累了內(nèi)容完整呈現(xiàn)的時(shí)間。

我們使用谷歌瀏覽器performance可以最終追查到這個(gè)系統(tǒng)在哪些方面,哪個(gè)方法存在著哪些延遲。結(jié)論是:

1、混亂的項(xiàng)目資源管理導(dǎo)致大量的資源請(qǐng)求。

2、easyui和項(xiàng)目中不少的dom操作帶來大量的重排和重繪。

3、埋點(diǎn),插件使用不當(dāng)以及其他。

微前端

它是什么呢?

微前端的概念來自于之前流行的微服務(wù)。它的來源很大程度是來自于這篇文章 。微服務(wù)系統(tǒng)使得后臺(tái)服務(wù)架構(gòu)能夠比較好地規(guī)避越來越臃腫的體積帶來的性能下降。根據(jù)業(yè)務(wù)合理拆分成一個(gè)個(gè)的服務(wù),盡量避免一個(gè)子服務(wù)影響整個(gè)項(xiàng)目運(yùn)行的優(yōu)勢(shì),有效的進(jìn)行隔離。

那么,前端也有同樣的需求嗎?答案是肯定的。

今天,日益更新的前端技術(shù),已經(jīng)能夠把一個(gè)個(gè)頁面各個(gè)小元素打包成組件庫,功能包,在多個(gè)項(xiàng)目中引入使用。此外,我們不用再使用難受的iframe來聚合不同的項(xiàng)目,而是導(dǎo)出一個(gè)個(gè)web component,只需要import 到頁面就可以使用。把一個(gè)個(gè)子項(xiàng)目打包成一個(gè)個(gè)web component,聚合在入口項(xiàng)目之內(nèi)。這也許就是微前端現(xiàn)在比較時(shí)髦的樣子。
如果一個(gè)大項(xiàng)目有以下特點(diǎn),微前端可以在這些項(xiàng)目中運(yùn)用:
1、大項(xiàng)目有統(tǒng)一的入口,子項(xiàng)目頁面需要無刷新下切換,可是各個(gè)子項(xiàng)目在業(yè)務(wù)上和開發(fā)團(tuán)隊(duì)上是不同的。

2、項(xiàng)目過大,打包、運(yùn)行、部署效率出現(xiàn)顯著下降的問題。這時(shí)希望能根據(jù)業(yè)務(wù)拆分打包,部署。

方案與實(shí)施

回到本文開頭,一開始面對(duì)這樣的需求還是有些想辭職的沖動(dòng),因?yàn)橛X得需求有點(diǎn)不是符合實(shí)際,實(shí)際上要實(shí)施改版也是需要過程的。

不過靜下來想想,搜搜,翻了翻當(dāng)前項(xiàng)目的前端結(jié)構(gòu),隱隱約約似乎浮現(xiàn)一些需求可行性的線索。

因?yàn)轫?xiàng)目的最終目的是把整個(gè)jsp頁面改成vue來寫。而這一要求是逐步替換的過程,所以在改造過程中,同時(shí)要保證項(xiàng)目兼容jsp的頁面。我們繼續(xù)沿用了原來就有的iframe,借此把jsp融入整個(gè)微前端框架,而已經(jīng)改造的micro則不需要iframe.
我們的開發(fā)團(tuán)隊(duì),分框架組和各個(gè)業(yè)務(wù)組。其中每個(gè)業(yè)務(wù)組有3到8個(gè)人,他們大多數(shù)是后端背景,主要做的也是后端開發(fā)??蚣芙M有前端和后端。為了應(yīng)付龐大的業(yè)務(wù)開發(fā)需求。大部分后端人員都需要使用jsp,js等前端技術(shù)進(jìn)行開發(fā)。
框架組為了減少他們的前端開發(fā)門檻,前端框架組會(huì)封裝好easyui組件,提供業(yè)務(wù)組使用。所以,正如前文提到,后端人員是通過數(shù)據(jù),結(jié)合框架組提供的組件來完成頁面的開發(fā)的。從某種角度來說,數(shù)據(jù)配置的頁面對(duì)接下來的改造工作有一定的幫助,因?yàn)榇蟛糠猪撁婵梢酝瑫r(shí)改寫。

我們對(duì)整個(gè)項(xiàng)目進(jìn)行了大致的分類。

1、portal 項(xiàng)目:該項(xiàng)目是整個(gè)微前端項(xiàng)目的入口。里面含有l(wèi)oader,用以加載各個(gè)項(xiàng)目模塊。它也嵌入到子項(xiàng)目中,使得多帶帶運(yùn)行子項(xiàng)目和portal項(xiàng)目一樣的界面要求。
2、permission 項(xiàng)目:該項(xiàng)目包含菜單組件,登錄頁面,頂欄組件,權(quán)限控制等。在任何環(huán)境下,它都必須首先加載,為子項(xiàng)目模塊掛載提供錨點(diǎn)。
3、common項(xiàng)目:該項(xiàng)目包含公共業(yè)務(wù)組件。比如封裝好的頁面,可以直接給不太能夠掌握vue項(xiàng)目的后端人員更加友好的去使用。
4、業(yè)務(wù)項(xiàng)目:就是指業(yè)務(wù)組各個(gè)模塊開發(fā)的前端項(xiàng)目。什么樣的業(yè)務(wù)分為一個(gè)項(xiàng)目,這點(diǎn)由產(chǎn)品和技術(shù)人員一起來決定。相對(duì)于portal項(xiàng)目,業(yè)務(wù)項(xiàng)目相當(dāng)于它的子項(xiàng)目。

前端框架組必須提供一套統(tǒng)一的業(yè)務(wù)項(xiàng)目的前端模板,可以在確認(rèn)新建的子項(xiàng)目后迅速的加入到整個(gè)項(xiàng)目中,進(jìn)行開發(fā)和部署,而這一過程不能影響其他項(xiàng)目的部署和運(yùn)行。

除了上述方案浮出水面,還會(huì)在改造過程中遇到一個(gè)個(gè)細(xì)節(jié)問題。 不過在大方向,框架組成上,前端結(jié)構(gòu)上做好了,細(xì)節(jié)問題也會(huì)隨耐心和時(shí)間被解決。

分別闡述

本坑根據(jù)以上的分類,大致進(jìn)行說明其實(shí)現(xiàn)。這其中結(jié)合了不少前輩之經(jīng)驗(yàn),在文章結(jié)尾處鳴謝。

Portal:

portal 項(xiàng)目是整個(gè)項(xiàng)目部署的入口,它的核心來自于single-spa
在整個(gè)項(xiàng)目結(jié)構(gòu)中它將集成到每一個(gè)子項(xiàng)目。集成的方式很粗暴簡(jiǎn)單,就是外聯(lián)加載。
portal負(fù)責(zé)根據(jù)不同的環(huán)境來對(duì)應(yīng)的組件和app,同時(shí)也安裝各個(gè)app,卸載各個(gè)app等,它負(fù)責(zé)app在single-spa的生命周期。比如集成模式下根據(jù)環(huán)境和路由加載對(duì)應(yīng)的app,而在子項(xiàng)目運(yùn)行時(shí)只加載公共組件和不同業(yè)務(wù)的app。

那么protal是如何加載的呢?

protal維護(hù)了一個(gè)json里面包含了各個(gè)子項(xiàng)目的index.html的信息,通過匹配index.html里面的src 、link,加載各項(xiàng)資源。


module.exports = {
  common: {
    webName:"common",
    globalVarName: "mfe:common",
    componentsTarget: "/common/release/components/web.html",
    resourcePatterns: ["/components.[0-9a-z]{8}.js/g"],
    loadType:"before"
  },
  permission: {
    webName:"permission",
    globalVarName: "mfe:permission",
    // URL 匹配模式
    matchUrlHash: "",
    // 微前端地址
    componentsTarget: "/permission/release/components/web.html",
    webTarget:"/permission/release/web/web.html",
    // 資源匹配模式
    resourcePatterns: ["/common.[0-9a-z]{8}.css/g","/store.[0-9a-z]{8}.js/g", "/publicPath.[0-9a-z]{8}.js/g","/singleSpaEntry.[0-9a-z]{8}.js/g","/components.[0-9a-z]{8}.js/g"],
    //是否要在項(xiàng)目啟動(dòng)前加載,before為提前加載,after為hash變化后加載
    loadType:"before"
  },
  app4vue:{
    webName:"repair-order",
    globalVarName: "mfe:app4vue",
    matchUrlHash: "/layout/repair-order",
    webTarget: "/app4/release/web/web.html",
    resourcePatterns: ["/common.[0-9a-z]{8}.css/g","/store.[0-9a-z]{8}.js/g", "/singleSpaEntry.[0-9a-z]{8}.js/g"],
    loadType:"after"
  }
}
  async  gatherResource () {
    const self = this
    // const spaEntry = "portal"
    const web = self._webName
    //如果是微前端聚合模式
    if (window._IS_SIGLE_PORTAL) {
      if (web !== "mfe-permission") {
        await self.loadComponents(micros.common)
        await self.loadApp(micros.permission)
      }
    }
    else {
      if (web === "mfe-permission") {
        await self.loadComponents(micros.common)
      } else {
        if (web !== "mfe-common") {
          await self.loadComponents(micros.common)
        }
        await self.loadApp(micros.permission)
      }
    }
    // return new Promise(resolve => resolve("loader:all Finish!"))
  }
permisson:

permission負(fù)責(zé)登錄頁,layout中的菜單欄,頂欄。所有的子項(xiàng)目app都必須掛載到permission項(xiàng)目中的顯示區(qū)塊里。也就是說permssion會(huì)提供錨點(diǎn)給子項(xiàng)目掛載。

所以permission負(fù)責(zé)路由的控制,這里的路由有總體路由和app內(nèi)路由切換。如果app切換的路由控制涉及到singer-spa,app的切換會(huì)觸發(fā)single-spa:routing-event事件,portal監(jiān)聽該事件 unmounted和mounted app,如果app內(nèi)部的路由切換,需要觸發(fā)app內(nèi)部路由切換。

本坑嘗試監(jiān)聽permission的 hash,由于vue新版本,hash實(shí)際是監(jiān)聽不了的,所以監(jiān)聽hash是沒辦法的。

這看上去會(huì)干涉到子項(xiàng)目的代碼,如果哪位大神有好方法可以在評(píng)論區(qū)貼上你的看法。

業(yè)務(wù)項(xiàng)目

業(yè)務(wù)項(xiàng)目的獨(dú)立運(yùn)行只會(huì)發(fā)生在開發(fā)模式之下,在生產(chǎn)或者測(cè)試環(huán)境并不會(huì)獨(dú)立運(yùn)行。

集成環(huán)境下輸出成三個(gè)周期,提供給single-spa

export var global = {};
export const bootstrap = () => { return Promise.resolve(); }
export function mount (props) {
    Vue.mixin({
        data: function () {
            return {
                props
            }
        }
    })
    return Promise.resolve().then(() => {
        createDomElement();
        global.instance = new Vue({
            el: "#app4",
            router,
            render: h => h(App)
        })
    })
}
export function unmount () {
    return Promise.resolve().then(() => {
        global.instance.$destroy();
        global.instance.$el.innerHTML = "";
        delete global.instance
    })
}
function createDomElement () {
    // Make sure there is a div for us to render into
    let node = document.getElementById("main-content");
    let el = document.getElementById("app4");
    if (!el) {
        el = document.createElement("div");
        el.id = "app4";
        node.appendChild(el);
    }
    return el;

}

開發(fā)模式獨(dú)立運(yùn)行

const init = async () => {
  //啟動(dòng)single-spa
  const loader = new Loader(process.env)
  await loader.startSingleSpa()
  Vue.mixin({
    data () {
      return {
        loader
      }
    }
  })
  Vue.config.productionTip = false;
  //permission渲染后再掛載自己上去
  window.addEventListener("single-spa:main-content-mount", evt => {
    if (!window.vim) {
      window.vm = new Vue({
        el: loader.createHookEle("app4"),//掛載自己
        // store,
        router,
        render: h => h(App)
      })
    }
  })
}
init()
common

common 類似插件的打包,不贅述。

import "./styles/vars.scss"
import MButton from "./components/button"
const components = [MButton];

const install = function (Vue) {
  if (install.installed) return;
  components.map(component => {
    Vue.use(component);
  });
};
//  全局引用可自動(dòng)安裝
if (typeof window !== "undefined" && window.Vue) {
  install(window.Vue);
}
export default {
  install,
  MButton
}

幾個(gè)主要源碼采用外聯(lián)形式

    
    
    
    
    
    
    
    
Single-spa

single-spa是怎么聚合各個(gè)獨(dú)立的vue app的呢?本坑嘗試?yán)斫馑?/p>

Single-spa 把a(bǔ)pp聚合成三個(gè)周期 bootstrap mounted unmounted,這三個(gè)周期是需要自己去配置改寫的,其實(shí)single-spa還有其他周期,不需要改寫。

也就是對(duì)single-spa來說app只有這三個(gè)東西需要特別的關(guān)心,app的卸載和加載。其他都是app自己的事。mounted、unmonuted和vue app 獨(dú)立運(yùn)行的mounted和destroy本質(zhì)上沒有區(qū)別,只是single-spa做了一層代理。代理完成app的掛載和銷毀。

single-spa內(nèi)部也保存了一個(gè)數(shù)組,負(fù)責(zé)維護(hù)內(nèi)部注冊(cè)的app.注冊(cè)完后代理完成app的掛載。卸載后銷毀之。

總結(jié)

如果親愛的客官,你也遇到這種問題,用這種改法是沒有保證的。

本坑實(shí)踐它很大的理由也是用自己的方法初探微前端實(shí)踐方法的可行性。

這種大跨度的改變會(huì)帶來不少不可預(yù)測(cè)的底層沖突,前后端的沖突。

第二呢,這種大跨度的改變幾乎等同于重構(gòu)。

第三呢,微前端方案也有自身的局限性,比如對(duì)庫版本的管理,app樣式的隔離沒有做到很好等等。還是要根據(jù)實(shí)際來衡量。

針對(duì)太過古老的系統(tǒng)比如jsp,可以先嘗試把jsp轉(zhuǎn)為html,在前端性能上多改進(jìn),再另行考慮綜合性改版。

估計(jì)很多地方搞的不好,代碼或者信息錯(cuò)誤,歡迎各位指導(dǎo)。

鳴謝

single-spa官網(wǎng)

微前端實(shí)踐

前端微服務(wù)化解決方案

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/54165.html

相關(guān)文章

  • 馬蜂窩火車票系統(tǒng)服務(wù)化改造初探

    摘要:為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)?,F(xiàn)在,用戶在馬蜂窩也可以完成購買機(jī)票火車票等操作。第二階段架構(gòu)轉(zhuǎn)變及服務(wù)化初探從年開始,整個(gè)大交通業(yè)務(wù)開始從架構(gòu)向服務(wù)化演變。 交通方式是用戶旅行前要考慮的核心要素之一。為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)。現(xiàn)在,用戶在馬蜂窩也可以完成購買機(jī)票、火車票等操作。 與大多數(shù)業(yè)務(wù)系統(tǒng)相同,我們一樣經(jīng)歷著從無到有...

    Raaabbit 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<