记一次微前端开发与部署

1.基座 – vue3

  • index.html文件设置约定的id,如id=”base”
<body>
    <div id="base"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
复制代码
  • 入口文件main.ts引入qiankun框架并进行注册子应用等等
import { createApp } from 'vue'
import App from './App.vue'
import store from './store/index'
import router from './router/index'
import '@/styles/index.less'
import { registerMicroApps, start } from 'qiankun'
const isSubAppHome = function isSubAppHome(path:string):boolean {
  if (path === '/') {
    return true
}
    return path.indexOf('/home') === 0
}
const apps = [
    {
      name: 'subapp-home', // 应用的名字
      entry: 'http://www.xxx.com/child/home', // 默认会加载这个html 解析里面的js 动态的执行 (子应用必须支持跨域)fetch
      container: '#container', // 容器名(此项目页面中定义的容器id,用于把对应的子应用放到此容器中,进下一步骤设置id)
      activeRule: (location: { pathname: string }) => isSubAppHome(location.pathname), // 激活的路径
      props: { a: 1 } // 传递的值(可选)
    }
  ]
  registerMicroApps(apps); // 注册应用
  start(); //启动


const app = createApp(App)
app.use(store).use(router)
app.mount('#base') // 这里设置上一步的id
复制代码
  • 修改App.vue文件,设置子应用挂载的容器
<template>
  <div class="main-container">
    <Header  />
    <div class="microservices-container">
    <-- 这里设置子应用挂载的容器-->
      <div id="container"></div>
    </div>
    <router-view />
    <Footer />
  </div>
</template>
复制代码

至此基座就搭建完成

子应用home- vue2

  • vue.config.js
const packageName = require('./package.json').name;

module.exports = {
publicPath: '/child/home/',// 这里官方文档没写,但是我没写失败
  output: {
    library: `${packageName}-[name]`,// 固定配置
    libraryTarget: 'umd',// 固定配置
    jsonpFunction: `webpackJsonp_${packageName}`, // 固定配置
  },
  devServer: {
    port: 8080,
    headers: {
            //因为qiankun内部请求都是fetch来请求资源,所以子应用必须允许跨域
            'Access-Control-Allow-Origin': '*'
        }
    }
};
复制代码

publicPath: '/child/home/'这个没搞明白为啥必须写

  • main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index.js'
Vue.config.productionTip = false
let instance = null
if (!window.__POWERED_BY_QIANKUN__) { // 默认独立运行
  new Vue({
    router,
    render: h => h(App),
  }).$mount('#app')

}
// 父应用加载子应用,子应用必须暴露三个接口:bootstrap、mount、unmount
// 子组件的协议就ok了
export async function bootstrap() {
}
export async function mount(props) {
  console.log(props, '====')
  new Vue({
    router,
    render: h => h(App),
  }).$mount('#app')

}
export async function unmount() {
  instance.$destroy();
}
复制代码

官方文档:”新增 public-path.js 文件,用于修改运行时的 publicPath“,但我没有设置也能正常访问

打包

打包后的目录结构

aaa.png

基座打包为vite做跟目录,子应用放在child文件夹下面,如子应用打包为home

微前端的部署

nginx 配置

server {
        listen       80;
        server_name  localhost;
        location / {
            root   /root/node/vite; //vite的绝对路径
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        location /child/home { // 基座配置的entry
            root    /root/node/vite;
            index  index.html index.htm;
            try_files $uri $uri/ /child/home/index.html;
        }
        location /api {
            proxy_pass http:/xxxxxx/api;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_set_header   Host              $http_host;
            proxy_set_header   X-Real-IP         $remote_addr;
            proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;

        }
        # angular 和 react 的history 配置同上
        }
复制代码

个人理解:当访问基座配置的对应activeRule时,乾坤会请求entry,这时在nginx的代理会找到子应用,乾坤会把子应用挂载到container这个基座的id上,这样就看到了

  • 子应用用于修改运行时的 publicPath这个一定要吗,我没写也没报错
  • 子应用router的base需要吗
  • 子应用打包配置有啥用呢,为啥我要加上publicPath: ‘/child/home/’

附一份上传打包后的文件脚本

'use strict'
const Client = require('ssh2-sftp-client') 
const config = {
  path: {
    // 远程地址
    romotePath:'/root/node/vite/',
    // 本地地址
    localPath: './dist'
  },
  romote: {
    // 服务器 ip 地址
    host: 'xxxx.xxx.xxx.xxx',
    // 端口号,默认是 22
    port: '22',
    // 登录的用户名
    username: 'root',
    // 登录密码
    password: 'xxx'
  }
}

function main(localPath, romotePath) {
  // 实例化
  const sftp = new Client()
  sftp
    .connect(config.romote)
    .then(() => {
      console.log('----------------------------- 连接成功,上传中... -----------------------------')
      return sftp.uploadDir(localPath, romotePath)
    })
    .then(data => {
      console.log('----------------------------- 上传完成,及时清除缓存 ----------------------------')
    })
    .catch(err => {
      console.log('----------------------------- TMD失败了!出事了!快看看怎么回事! -----------------------------')
      console.log(err)
    })
    .finally(() => {
      // 断开连接
      sftp.end()
    })
}

main(
  config.path.localPath,
  config.path.romotePath
)
复制代码

不要忘记安装ssh2-sftp-client模块

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