<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          微前端 qiankun 項(xiàng)目實(shí)踐 !!! 防踩坑指南

          共 10508字,需瀏覽 22分鐘

           ·

          2021-04-06 20:17

          作者:zxh1307

          原文地址:https://juejin.im/post/5ea55417e51d4546e347fda9

          點(diǎn)擊上方“前端簡報(bào)”,選擇“設(shè)為星標(biāo)

          第一時(shí)間關(guān)注技術(shù)干貨!

          導(dǎo)語

          最近在做微前端的項(xiàng)目 , 過程中真是踩了不少坑 , 在有限的資料中不斷試錯(cuò) , 默默無語兩行淚 哈哈.  在此次將采坑部分都記錄下來, 讓更多的人少走點(diǎn)彎路 ,   此項(xiàng)目使用 螞蟻金服qiankun 為基礎(chǔ)作為開發(fā) . 話不多說 開講 !!!

          那什么是 qiankun 呢

          qiankun 是一個(gè)基于 single-spa 的微前端實(shí)現(xiàn)庫,旨在幫助大家能更簡單、無痛的構(gòu)建一個(gè)生產(chǎn)可用微前端架構(gòu)系統(tǒng)。

          什么是微前端

          微前端架構(gòu)具備以下幾個(gè)核心價(jià)值:

          • 技術(shù)棧無關(guān)

            主框架不限制接入應(yīng)用的技術(shù)棧,微應(yīng)用具備完全自主權(quán)

          • 獨(dú)立開發(fā)、獨(dú)立部署

            微應(yīng)用倉庫獨(dú)立,前后端可獨(dú)立開發(fā),部署完成后主框架自動完成同步更新

          • 增量升級

            在面對各種復(fù)雜場景時(shí),我們通常很難對一個(gè)已經(jīng)存在的系統(tǒng)做全量的技術(shù)棧升級或重構(gòu),而微前端是一種非常好的實(shí)施漸進(jìn)式重構(gòu)的手段和策略

          • 獨(dú)立運(yùn)行時(shí)

            每個(gè)微應(yīng)用之間狀態(tài)隔離,運(yùn)行時(shí)狀態(tài)不共享

          摘自 qiankun官方文檔

          主應(yīng)用配置

          此次項(xiàng)目 主應(yīng)用與 子應(yīng)用均為 vue ,

          下載 qiankun

          npm install qiankun

          在主應(yīng)用中注冊微應(yīng)用

          // 導(dǎo)入乾坤函數(shù)
          import {
            registerMicroApps,
            setDefaultMountApp,
            start
          from "qiankun";


          封裝 render 方法

          此方法在main.js 中要初始調(diào)用一次, 主要用來掛載主應(yīng)用 , 之后子應(yīng)用分別依次調(diào)用 ,所以故作判斷. 傳入的參數(shù)分別為 子應(yīng)用 的 HTML 和 加載狀態(tài) content 字段 我們用 vuex 存儲 起來,方便使用


          let app = null;

          function render({ appContent, loading }{
            if (!app) {
              app = new Vue({
                router,
                store,
                renderh => h(App),
              }).$mount('#app');
              
            } else {
              store.commit('microApp/changeCenter', appContent);
              store.commit('microApp/changeLoading', loading);
            }

          }

          微應(yīng)用注冊

          下文中的apps 可以為獲取后數(shù)據(jù) , 注冊微應(yīng)用 本文案例比較簡單,方便大家理解 ,

          在注冊自應(yīng)用的參數(shù) ** container 與 render** 采坑比較多,下邊會著重講解.


          function genActiveRule(routerPrefix{
            return location => location.pathname.startsWith(routerPrefix);
          }

          //傳遞給子應(yīng)用的數(shù)據(jù)
          let msg = {
          ![](https://user-gold-cdn.xitu.io/2020/4/27/171bbc5de042ec98?w=1811&h=959&f=gif&s=4951066)
            data:'修煉愛情的辛酸,學(xué)會放好以前的渴望'
          }

          let apps = [
            {
              name'linjunjie'
              entry'//localhost:215',  // 改成自己子應(yīng)用的端口號
              container:'#subView'//節(jié)點(diǎn) id   //  沙盒模式 
              // render:render,  // 普通模式   
              activeRule: genActiveRule('/star'),
              props:msg
            }
          ]
             //注冊的子應(yīng)用 參數(shù)為數(shù)組
          registerMicroApps(apps,{
            beforeLoad: [
              app => {
                console.log(app)
                console.log('[LifeCycle] before load %c%s''color: green;', app.name);
              },
            ],
            beforeMount: [
              app => {
                console.log('[LifeCycle] before mount %c%s''color: green;', app.name);
              },
            ],
            afterUnmount: [
              app => {
                console.log('[LifeCycle] after unmount %c%s''color: green;', app.name);
              },
            ],
          });


          setDefaultMountApp('/star/linjunjie')

          //開啟沙盒模式
          start({ 
             sandbox :{strictStyleIsolationtrue}
          })

          當(dāng)微應(yīng)用信息注冊完之后,一旦瀏覽器的 url 發(fā)生變化,便會自動觸發(fā) qiankun 的匹配邏輯,所有 activeRule 規(guī)則匹配上的微應(yīng)用就會被插入到指定的 container 中,同時(shí)依次調(diào)用微應(yīng)用暴露出的生命周期鉤子。

          主應(yīng)用為子應(yīng)用準(zhǔn)備的 展示元素

          <template>
            <div id="app">
              <div id="nav">
                <!--//主應(yīng)用 為子應(yīng)用的跳轉(zhuǎn)dom-->
                <div @click="onChangePage('/star/linjunjie')" >林俊杰</div>
                <div @click="onChangePage('/star/zhangyixin')" >張藝興</div>
             
              </div>
          <!--//用來展子應(yīng)用的 內(nèi)容區(qū)-->
               <div id="subView" class="sub-content-wrap" v-html="content"></div>
            </div>

          </template>

          <script>

            import { mapState } from 'vuex';
            export default{
              data(){
                return {
               
                }
              },
              computed:{
              //獲取子應(yīng)用HTML 數(shù)據(jù)
                 ...mapState('microApp', ['content']),
                 ...mapState('microApp', ['mircoAppLoading']),
              },

              methods:{
              
                //定義跳轉(zhuǎn)方法
                onChangePage(url){
                  console.log(url)
                  
                  this.routerGo(url, '我喜愛的男明星')
                },
            
                routerGo(href = '/', title = null, stateObj = {}) {
                  window.history.pushState(stateObj, title, href); 
                },
              }
           }
          </script>



          子應(yīng)用配置

          關(guān)于子應(yīng)用的配置相對較簡單 , 不需要額外下載qiankun 主要將生命鉤子 導(dǎo)出即可

          導(dǎo)出響應(yīng)的生命鉤子

          導(dǎo)出 bootstrapmountunmount 三個(gè)生命周期鉤子,以供主應(yīng)用在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用。注意,實(shí)例化路由時(shí),判斷當(dāng)運(yùn)行在qiankun環(huán)境時(shí),路由要添加前綴,前綴與主應(yīng)用注冊子應(yīng)用函數(shù)genActiveRule("/subdemo")內(nèi)的參數(shù)一致

          'star' 值需要與主應(yīng)用的值對應(yīng) genActiveRule("/star") 中的值需要商定好 主應(yīng)用與微應(yīng)用都要使用

          如果 new VueRouter 不在main.js  中 配置 ,請將此配置移動到 main.js  方便管理

          import routes from './router' //將路由信息導(dǎo)出方便使用 

          let router = null;
          let instance = null;

          function render(props = {}{
            const { container } = props;
            router = new VueRouter({
              basewindow.__POWERED_BY_QIANKUN__ ? '/star' : '/',  
              mode'history',
              routes,
            });

            instance = new Vue({
              router,
              store,
              renderh => h(App),
            }).$mount(container ? container.querySelector('#app') : '#app');
          }

          if (!window.__POWERED_BY_QIANKUN__) {
            render();
          }


          export async function bootstrap({
            console.log('[vue] vue app bootstraped');
          }

          export async function mount(props{
           //props 包含主應(yīng)用傳遞的參數(shù)  也包括為子應(yīng)用 創(chuàng)建的節(jié)點(diǎn)信息
            console.log(props)
            render(props);
          }

          export async function unmount({
            instance.$destroy();
            instance = null;
            router = null;
          }

          配置微應(yīng)用的打包工具

          除了代碼中暴露出相應(yīng)的生命周期鉤子之外,為了讓主應(yīng)用能正確識別微應(yīng)用暴露出來的一些信息,微應(yīng)用的打包工具需要在vue.config.js 中 增加如下配置:

          const packageName = require('./package.json').name;

          module.exports = {
          output: {
          library: `${packageName}-[name]`,
          libraryTarget: 'umd',
          jsonpFunction: `webpackJsonp_${packageName}`,
          },
          };

          子應(yīng)用判斷

          子應(yīng)用中新建 publicPath.js  在main.js 引入
          if (window.__POWERED_BY_QIANKUN__) { 
          //處理資源
           __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; 
          }

          處理 資源加載問題

          配置 vue.config.js

          module.exports = {
            publicPath:`//localhost:${port}`,
          }

          vue.config.js 完整配置

          const path = require('path');
          const packageName = require('./package').name;

          function resolve(dir{
            return path.join(__dirname, dir);
          }

          const port = 7101// dev port
          module.exports = {

            publicPath:`//localhost:${port}`,
            outputDir'dist',
            assetsDir'static',
            filenameHashingtrue,
           
            devServer: {
              // host: '0.0.0.0',
              hot: true,
              historyApiFallbacktrue,//添加 重點(diǎn)
              port,
              overlay: {
                warningsfalse,
                errorstrue,
              },
              headers: {
                'Access-Control-Allow-Origin''*',
              },
            },

            configureWebpack: {
              resolve: {
                alias: {
                  '@': resolve('src'),
                },
              },
              output: {
                library`${packageName}-[name]`,
                libraryTarget'umd',
                jsonpFunction`webpackJsonp_${packageName}`,
              },
            },
          };



          采坑記錄

          當(dāng)前頁面為子應(yīng)用時(shí), 刷新頁面404

          以下方式均為主應(yīng)用配置

          • 方式一 刪除 mode 配置項(xiàng)

            mode: 'history', //   將此配置代碼刪除
          • 方式二 配置404  頁面

          如果沒有注釋掉mode: 'history'  此參數(shù) 將404 頁面重新導(dǎo)向  home首頁

          {
              path'*',
              name'indexNotFound',
              componentresolve => require(['@/components/home'], resolve),
              children: HomeChild,
          },

          子應(yīng)用 樣式隔離 開始沙箱模式 遇到的問題

          • 主應(yīng)用配置sandbox :{strictStyleIsolation: true}渲染模式由 render 模式 改為 containercontainer:'#subView', 此時(shí) 子應(yīng)用的 掛載 dom  為 <div id="subView"> </div>   謹(jǐn)記主 container :#+id

          • 子應(yīng)用配置 上文有提到  主要代碼 截取

            instance = new Vue({
              router,
              store,
              renderh => h(App),
            }).$mount(container ? container.querySelector('#app') : '#app'); //重點(diǎn)

          遇到的問題: 開啟沙箱模式,如果是 采用 render 模式會報(bào)錯(cuò) ,固選擇container 模式

          效果圖

          寫到這里,項(xiàng)目已經(jīng)構(gòu)建完成了 讓我們來看看效果吧

          這里是完整代碼 方便大家學(xué)習(xí) 代碼github地址:https://github.com/zxh1307/qiankun-vue

          項(xiàng)目問題

          • 為啥我項(xiàng)目啟動后看不到子應(yīng)用的效果

            將master 主應(yīng)用 main.js 中 注冊的 子應(yīng)用的端口號 改成自己項(xiàng)目的端口號即可

          結(jié)語

          開發(fā)中還有其他坑 忘記記錄了, 千萬記得項(xiàng)目部署子應(yīng)用資源跨域的問題 , 需要Nginx配置跨域問題.

          瀏覽 39
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人夜色激情福利av | 女人18片毛片60分钟播放在线 | 黄 色 视 频高潮 | 国产无套精品一区二区 | 日韩欧美毛片 |