qiankun vite无publicPath踩坑

684 阅读2分钟

1、vite子项目接入qiankun

qiankun项目子项目采用vite构建,官方没有文档,我们可以参考网上解决方案vite-plugin-qiankun, 它解决以下问题:

开发模式:在开发环境下,如果我们使用 vite 来构建 vue3 子应用,基于vite的构建机制,会在子应的 html 的入口文件的 script 标签上携带 type=module。而我们知道qiankun父应用引入子应用,本质上是将html做为入口文件,并通过import-html-entry这个库去加载子应用所需要的资源列表Js、css,然后通过eval直接执行,而基于vite构建的js中import、export并没有被转码,会导致直接报错(不允许在非 type=module 的 script 里面使用 import)

  • vite.config.ts
import { defineConfig } from 'vite'
import qiankun from 'vite-plugin-qiankun'

export default defineConfig((mode) => {
  return {
    plugins: [
      qiankun('subApp', { // 微应用名字,与主应用注册的微应用名字保持一致
        useDevMode: true,
      }),
    ],
  }
})
  • main.js
import { createApp } from 'vue'
import App from './App.vue'
import {
  renderWithQiankun,
  qiankunWindow,
  QiankunProps,
} from 'vite-plugin-qiankun/dist/helper'

const render = (props: QiankunProps = {}) => {
  const { container } = props
  const app: string | Element = container?.querySelector('#subApp') || '#subApp' // 避免 id 重复导致微应用挂载失败
  createApp(App).mount(app)
}

const initQianKun = () => {
  renderWithQiankun({
    bootstrap() {
      console.log('微应用:bootstrap')
    },
    mount(props) { // 获取主应用传入数据
      console.log('微应用:mount', props)
      render(props)
    },
    unmount(props) {
      console.log('微应用:unmount', props)
    },
    update(props) {
      console.log('微应用:update', props)
    },
  })
}

qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render() // 判断是否使用 qiankun ,保证项目可以独立运行

2、问题描述

生产模式下依旧不支持publicPath, 需要将vite.config.jsbase配置写死。 导致多环境部署不便捷。无法像在webpack结合window.INJECTED_PUBLIC_PATH_BY_QIANKUN + publicpath来解决

3、解决方案

  • 增加webpack配置,让生产环境运用webpack打包,开发环境使用vite开发
  • 将项目目录进行改造
├── tsconfig.json
├── package.json
├── vue.config.js
├── src
│    ├── main.ts
│    └── route.ts
├── vite
│    ├── tsconfig1.json
│    ├── package.json
│    ├── vite.config.js
│    ├── main.ts
│    ├── route.ts
│    ├── src
│         ├── App.vue
│         ├── components
│         ├── store
│         │   └── modules
│         └── views
│              ├── book
│              └── movie
└── README.md
  • vite/src/main.ts 采用 vite-plugin-qiankun插件; src/main.ts采用webpack
import './public-path';

import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'
import App from '@/App.vue';
import routes from './routes';
import pinia is from '@/store';

function render(){
  const router = createRouter({
    history: createWebHashHistory(),
    routes
  })
  createApp(App).use(router).use(pinia).mount('#app')
}
// 独立运行时
if (!(window as any).__POWERED_BY_QIANKUN__) {
  render()
}

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
  console.log('[vue] props from main framework', props);
  render(props);
}
export async function unmount() {
}
  • vite/route.ts 采用 import.mata.glob(["@/views/**"]); src/route.ts 采用require.context("@/views/",true,/.*\.vue/)
  • vite/tsconfig.json里面{@/*:./src/*},添加到gitignore不要提交到git仓库;tsconfig.json 里面{@/*: ./vite/src/*} ;
  • package.json 脚本设置
start:"cd ./vite && npm start",
build:"vue-cli-service build"

欢迎关注我的前端自检清单,我和你一起成长