qiankun体验从0到1(hash模式)

因行情内卷严重,还是得要学习一下微前端,期待V3降临yyds~

直接开篇先创建2个Vue项目

// 主项目
vue create qiankun_main
// 子项目
vue create qiankun_child

? Please pick a preset:
  Default ([Vue 2] babel, eslint)  // 我比较不喜欢eslint所以你懂得
  Default (Vue 3 Preview) ([Vue 3] babel, eslint) // Vue3的目前我还没测试,以后有机会写下
> Manually select features // 手动配置部分自带依赖


? Please pick a preset: Manually select features
? Check the features needed for your project:
 (*) Choose Vue version
 (*) Babel
 ( ) TypeScript // 单纯我不会ts!不要内卷我!
 ( ) Progressive Web App (PWA) Support
 (*) Router
 (*) Vuex
 (*) CSS Pre-processors
>( ) Linter / Formatter // 我不爱eslint,可能因为我菜
 ( ) Unit Testing
 ( ) E2E Testing
 
? Choose a version of Vue.js that you want to start the project with
> 2.x
  3.x (Preview)

// 因为前面设置了Router,所以问要不要history,本次只做hash所以No!
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n
// 因为前面设置了CSS Pre-processors,我是用sass的!真香 ~
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
  Sass/SCSS (with dart-sass)
> Sass/SCSS (with node-sass) // 这个快,所以选这个~
  Less
  Stylus
// 自己配置yyds
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files  // 单独保存在各自的配置文件中
  In package.json // 保存在package.json文件中
// 是否记住当前配置方便下一次直接使用创建项目
? Save this as a preset for future projects? (y/N) y // 记住,方便操作再次操作
? Save preset as: vue-qiankun-preset // 为这个配置命名
/* 漫长的等待 */
$ cd qiankun_main
$ npm run serve
// 子项目安装,用到了前一次的配置
? Please pick a preset:
> vue-qiankun-preset ([Vue 2] node-sass, babel, router, vuex) // 咱们前一次的配置
  Default ([Vue 2] babel, eslint)
  Default (Vue 3 Preview) ([Vue 3] babel, eslint)
  Manually select features
复制代码
qiankun配置(本地主应用hash版)
// 安装qiankun(只需要主应用安装)
$ yarn add qiankun  # or npm i qiankun -S # or cnpm i qiankun -S
// 确保依赖包的完整
$ npm install # or cnpm install
复制代码

qiankun.js – 封装js

import {
    registerMicroApps,
    start
} from 'qiankun';

const getActiveRule = (hash) => (location) => location.hash.startsWith(hash);

// 注册微应用
registerMicroApps([{
    name: 'child', // 注册名
    entry: '//localhost:8082', // 子应用端口(本地)
    container: '#app', // 当前服务的APP.VUE ID
    activeRule: getActiveRule('#/child'), // 子应用根路由 hash(官方推荐history)
    // 这里也可以直接写 activeRule: '#/child',但是如果主应用是 history 模式或者主应用部署在非根目录,这样写不会生效
    props: { // 传入子应用的值
        /**
         * 个人习惯:传data 子应用取data
         */
        data: {
            say: '我是父应用来的招呼' 
        }
    }
}, ]);

// 启动我们可爱的微服务
start();
复制代码

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './qiankun' // 引用封装JS

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
复制代码
qiankun配置(本地子应用hash版 – 稍微比主应用麻烦点)
#### 子应用 qiankun_child
/* main.js */
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false;

let instance = null;

// 动态路由配置
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

// 非qiankun环境直接渲染
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// 父应用已经到了子应用时的生命周期(简单来说:父应用的路由目前等于子应用的activeRule) TODO:activeRule #/child = /child
export async function bootstrap() {
    console.log('[vue] vue app bootstraped');
}
// 父应用已经到了子应用具体配置的路由时的生命周期(简单来说:路由地址对应的是子应用的路由地址,前置为父应用的activeRule) TODO:activeRule #/child = /child/子应用路由
export async function mount(props) {
    store.commit("setQiankun", props);
    console.log('[vue] props from main framework', props);
    render(props);
}
// 父应用离开子应用时的生命周期(简单来说:路由不拼子应用里的)
export async function unmount() {
    instance.$destroy();
    instance.$el.innerHTML = '';
    instance = null;
}

function render(props = {}) {
  const { container } = props;
  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}
复制代码

vue.config.js – 需要自己创建

let v = '1.0.0'; // 版本号
module.exports = {
    configureWebpack: {
        output: { // 输出重构  打包编译后的 文件名称  【模块名称.版本号.js】
            library: `${v}-[name]`,
            libraryTarget: 'umd', // 把子应用打包成 umd 库格式
            jsonpFunction: `webpackJsonp_${v}`,
        },
    },
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        }
    }
}
复制代码

router/index.js 配置路由

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const apiName = window.__POWERED_BY_QIANKUN__ ? '/child' : '';

const routes = [
  {
    path: `${apiName}/index`,
    name: 'index',
    component: () => import('@/views/system/home')
  }
]

const router = new VueRouter({
  routes
})

export default router
复制代码

store/index.js 配置VUEX

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    qiankun: null
  },
  mutations: {
    setQiankun(state,v){
      state.qiankun = Object.assign({},v);
    }
  },
  actions: {
  },
  modules: {
  }
})
复制代码

home.vue

<template>
  <div>
      <div>子页面</div>
      <div>{{props}}</div>
  </div>
</template>

<script>
export default {
  created(){
    this.props = this.$store.state.qiankun.data.say;
  },
  data(){
    return{
      props: ''
    }
  }
}
</script>

<style lang="scss">

</style>
复制代码

效果图

主应用

主应用.png
主应用中输入子应用路由

子应用.png

下一篇应该一边学习一边更新部署服务后的配置hash版

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享