基于umijs多模塊系統(tǒng)調(diào)試開發(fā)方案

基于umijs多模塊系統(tǒng)調(diào)試開發(fā)方案

背景

? 隨著前端開發(fā)過程工程化的深入率拒,前端SPA應(yīng)用已經(jīng)越來越多的在各種信息系統(tǒng)內(nèi)部采用,而且隨著微服務(wù)架構(gòu)的深入迈螟,前端SPA應(yīng)用的使用又更加普及了叉抡。如果只是一個(gè)獨(dú)立應(yīng)用的開發(fā),那么前端在開發(fā)階段答毫,往往是以下形態(tài)存在的:

spa app產(chǎn)品形態(tài).png

? 本地npm run start,通過了devServer開啟了一個(gè)web服務(wù)器褥民,另外通過本地模擬或者proxy的方式,把向后端請求接口代理到了后端開發(fā)者提供給我們的地址洗搂。

? 這種方式的確簡單和方便消返,但是有個(gè)前提:一個(gè)獨(dú)立的應(yīng)用。如果開發(fā)的是一個(gè)大型系統(tǒng)的一個(gè)模塊耘拇∧旒眨可以參考下圖:

信息系統(tǒng)部署形態(tài).png

? 那么開發(fā)以上單個(gè)模塊的前端工程,往往需要和多方進(jìn)行交互惫叛,甚至還可能存在前端運(yùn)行的特定容器秦驯。這些交互包括:請求后端其他(非本模塊)接口服務(wù)、接口請求權(quán)限認(rèn)證挣棕、前端調(diào)用其他模塊頁面等等译隘。如果還是采用簡單的方式進(jìn)行本地開發(fā),伴隨而來的就需要解決諸如:添加多個(gè)proxy洛心、前端模擬登錄固耘、前端跨域問題等等,而這種問題的解決词身,同時(shí)也伴隨著工程化配置的復(fù)雜化厅目。

? 本文就基于umijs腳手架前端應(yīng)用為基礎(chǔ),講解伴隨著前端工程化的深入法严,前端應(yīng)用本地開發(fā)三種解決以上問題的方式损敷。

可行方案迭代

前端Http全局跨域

? 前端開發(fā)相關(guān)性最強(qiáng)的是后端請求接口以及接口引起的權(quán)限和跨域問題。那么如果借助瀏覽同一個(gè)窗口深啤,同域cookie共享的機(jī)制,自然而然可以想象把前端頁面對后端接口的請求诱桂,通過全地址的方式進(jìn)行處理(而不是devServer代理一次)。這樣可以提前登陸多模塊的平臺系統(tǒng),然后設(shè)置瀏覽器全局跨域的方式辞槐,繞過接口的授權(quán)和跨域限制。

? 簡單來說就是兩步:

  • 修改前端異步請求庫丙号,添加后端接口全地址前綴犬缨,比如axiosjquery的設(shè)置

    import axios from 'axios';
    
    // 后端接口全路徑前綴
    let serverHost = "http://192.168.91.66/"
    
    if (process.env.NODE_ENV !== 'development') {
      axios.defaults.baseURL = serverHost;
      jquery.ajaxSettings.baseURL = serverHost;
    }
    
  • 修改瀏覽器跨域限制,默認(rèn)開發(fā)階段支持接口調(diào)用全局跨域枝恋。

    chrome瀏覽器畦攘,右鍵屬性知押,在目標(biāo)欄,添加--args --disable-web-security --user-data-dir="C:/chromeDev"

chrome 跨域.png

這樣處理以后,保證了后端接口的合理調(diào)用,但是這種處理方式也存在一定的限制栈虚,比如,如果是前端引用其他模塊的頁面粘姜,跨頁面之間的交互仍舊是限制的(iframe內(nèi)部window.parent)孤紧。

前端devServer代理

既然第一種方案不能那么完美的解決跨頁面交互跨域的問題号显,那么第二種方案自然而然的產(chǎn)生了,深度使用devServer的代理功能揽碘。

我們通過umijs配置的proxy屬性雳刺,把全部需要依賴的后端接口都添加上代理浑此,包括前端跨頁面訪問的其他模塊頁面地址紊馏,一般存在的形式可能如下:

proxy:{
    '/xxService': {
        target: 'http://10.30.21.32:8080/',
        changeOrigin: true
    }
}

同時(shí)每次開發(fā)調(diào)試前岸啡,登錄多模塊系統(tǒng),瀏覽器端獲取到cookie信息(chrome F12 Appliaction)悦荒,添加到proxy代理頭:

const msServiceCookie = 'language=zh_CN; JSESSIONID=EBE18455DA8A776B097DE467B12E6833; GWSessionId=839AEF9FA35BCAF24466CF7A6C85063C; CASTGC=TGT-44-UUEoZ9yhQc1vNNzdeng2YQewyvsErWbjCLPqfTGAYGIFqYiaML';
const isDev = process.env.NODE_ENV === 'development';

const proxyHeaders = isDev ? {
    'Cookie': msServiceCookie,
} : {};

proxy:{
    '/xxService': {
        target: 'http://10.30.21.32:8080/',
        changeOrigin: true,
        headers: proxyHeaders
    }
}

這樣蟀拷,本地前端開發(fā)調(diào)試過程,無論是接口調(diào)用還是跨域問題,都可以解決了强戴。唯一不太方便的地方就是匕累,cookie是有有效期的衰琐,每次失效得從新賦值,后端接口如果前綴規(guī)則很多羡宙,在proxy內(nèi)部需要配置多次狸剃。

Nginx同域代理

行文至此,似乎本文的話題應(yīng)該結(jié)束了狗热,但是總覺得以上兩種方案還是不夠完美钞馁,同時(shí)又讓我想起了一句萬變不離其中的真理:

計(jì)算機(jī)科學(xué)體系內(nèi),沒有加一層解決不了的問題

對匿刮,下面描述的就是基于多一層(Nginx)僧凰,來實(shí)現(xiàn)更合適這種場景的解決方案。

Nginx的特點(diǎn)就不再贅述熟丸,我們今天用到的就是其最普通的功能:代理训措。最終我們的目標(biāo)就是,把我們本地的調(diào)試站點(diǎn)和多模塊的平臺系統(tǒng)實(shí)現(xiàn)同域化。當(dāng)然還要適當(dāng)?shù)膽?yīng)用umijs非根目錄部署特性。大概原理如下:

架構(gòu)流程圖-產(chǎn)品形態(tài)的代理.png

我們在本地開發(fā)環(huán)境運(yùn)行一個(gè)Nginx服務(wù)(http://127.0.0.1:9528)隘竭,配置其代理愈案,使得路徑/app-local//sockjs-node/代理到本地開發(fā)啟動的nodejs服務(wù)(本地代碼http://127.0.0.1:9527),其他路徑直接代理到目標(biāo)多模塊平臺系統(tǒng)(http://10.30.5.36:8080/)。這樣借助nginx代理自動攜帶cookie的特色,我們可以直接訪問本地http://127.0.0.1:9528,既可以做到同訪問http://10.30.5.36:8080的效果了总珠。而只有/app-local/和/sockjs-node/代理到了我們的本地,這也正是我們需要達(dá)到的目標(biāo)勘纯。參考nginx示例如下:


    # 開發(fā)代理
    server {
    
        listen 9528;
        server_name_in_redirect off;

        # 本地開發(fā)啟動的站點(diǎn)
        location ^~/app-local/{
            proxy_pass http://127.0.0.1:9527;
        }
        
        # 本地調(diào)試webpack hot功能的websockt
        location ^~/sockjs-node/{
            proxy_set_header X-Real_IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X_Forward_For $proxy_add_x_forwarded_for;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_pass http://127.0.0.1:9527;
        }

        # BAP遠(yuǎn)程環(huán)境
        location /{
            proxy_pass http://10.30.5.36:8080/;
        }
            
                
    }

介紹到這里局服,熟悉umijs路由的同學(xué)會發(fā)現(xiàn),原先我們的應(yīng)用的產(chǎn)品態(tài)的路由驳遵,現(xiàn)在必須添加/app-local前綴了淫奔,否則前端的路由是沒有辦法定位到我們之前的功能的。直白點(diǎn)講堤结,之前我們的功能可能設(shè)置的路由為/appx/emp/list,那么我們現(xiàn)在開發(fā)階段唆迁,必須修改為/app-local/appx/emp/list才能正常訪問。同時(shí)竞穷,本地應(yīng)用的所有靜態(tài)資源唐责,也必須添加/app-local前綴。幸好瘾带,umijs已經(jīng)提供了合適的機(jī)制來實(shí)現(xiàn)這個(gè)功能鼠哥。還是umijs的配置:

import routes from './routes';

let buildDevBase = `/app-local/`;
const isDev = process.env.NODE_ENV === 'development';

// ++ 功能點(diǎn)添加
const chainWebpack = (config) => {
  // 添加靜態(tài)資源非根目錄部署路徑(開發(fā)階段(yarn start:custom)umi的publicPath沒有生效)
  if (process.env.NODE_ENV === 'development') {
    config.merge({
      output: {
        publicPath: buildDevBase,
      },
    });
  }
}

let appConfig = {
  treeShaking: true,
  routes,
  targets: {
    ie: 11,
  },
  plugins: [
    [
      'umi-plugin-react',
      {
        dva: {
          immer: true
        },
        dynamicImport: {
          webpackChunkName: true,
          loadingComponent: './platform/loading',
        },
        title: 'MES-APP',
        dll: false,
        routes: {
          exclude: [
            /models\//,
            /services\//,
            /model\.(t|j)sx?$/,
            /service\.(t|j)sx?$/,
            /components\//
          ],
        },
      },
    ]
  ],
  chainWebpack: chainWebpack
};

// ++ 功能點(diǎn)添加
if(isDev){
  appConfig = {...appConfig,base: buildDevBase,publicPath: buildDevBase}
}

export default appConfig;

其實(shí)以上的修改,說到底就是實(shí)現(xiàn)umijs應(yīng)用非根目錄部署過程。

那么本地開發(fā)過程中朴恳,第一步當(dāng)然是通過本地9528端口抄罕,登錄平臺系統(tǒng),然后切換到本地應(yīng)用地址進(jìn)行正常打開調(diào)試于颖,此時(shí)已經(jīng)是同域場景呆贿,接口調(diào)用也會直接代理到了平臺,對其他模塊頁面訪問也不再造成跨域問題了森渐,似乎我們需要實(shí)現(xiàn)的功能都實(shí)現(xiàn)了做入。當(dāng)然這個(gè)方案還是有待真實(shí)場景試驗(yàn),比如sockjs-node/這樣的路徑也是在不斷嘗試過程中發(fā)現(xiàn)的同衣。

后記

前端模塊化母蛛、組件化和工程化,已經(jīng)把前端開發(fā)過程變的不再那么簡單乳怎,各種基礎(chǔ)環(huán)境配置也被引入了前端開發(fā)過程,本文的http代理前弯,就是個(gè)例子蚪缀。但是我相信,本質(zhì)還是不變的恕出,無論是前端路由询枚,還是React的虛擬Dom,還是nodejsdevServer都離不開之前的技術(shù)體系浙巫,話說回來了金蜀,前端基礎(chǔ)還是那三把劍:html,css,javascript

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末的畴,一起剝皮案震驚了整個(gè)濱河市渊抄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丧裁,老刑警劉巖护桦,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異煎娇,居然都是意外死亡二庵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門缓呛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來催享,“玉大人,你說我怎么就攤上這事哟绊∫蛎睿” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長兰迫。 經(jīng)常有香客問我信殊,道長,這世上最難降的妖魔是什么汁果? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任涡拘,我火速辦了婚禮,結(jié)果婚禮上据德,老公的妹妹穿的比我還像新娘鳄乏。我一直安慰自己,他們只是感情好棘利,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布橱野。 她就那樣靜靜地躺著,像睡著了一般善玫。 火紅的嫁衣襯著肌膚如雪水援。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天茅郎,我揣著相機(jī)與錄音蜗元,去河邊找鬼。 笑死系冗,一個(gè)胖子當(dāng)著我的面吹牛奕扣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掌敬,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼惯豆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奔害?” 一聲冷哼從身側(cè)響起楷兽,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎华临,沒想到半個(gè)月后拄养,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡银舱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年瘪匿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寻馏。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棋弥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诚欠,到底是詐尸還是另有隱情顽染,我是刑警寧澤漾岳,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站粉寞,受9級特大地震影響尼荆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唧垦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一捅儒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧振亮,春花似錦巧还、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至褒搔,卻和暖如春阶牍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背星瘾。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工荸恕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人死相。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像咬像,于是被迫代替她去往敵國和親算撮。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344