1.说明
vue2项目由vite+js搭建
vue3项目由vite+ts搭建
使用federation去完成二者之间的交互
2.步骤
1.使用vite搭建vue2项目
- 创建项目名称及选择开发语言
npm init vite@latest
- vite创建的项目默认支持vue3,安装vue2及相关插件
npm install vue -S
npm install vue-template-compiler
npm install vite-plugin-vue2 --dev
相关版本如下
- 修改vite.config.js
import { createVuePlugin } from 'vite-plugin-vue2'
export default {
plugins: [createVuePlugin()]
}
- 修改main.js及页面
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
<template>
<div>vite+vue2</div>
</template>
- npm run dev启动项目即可
2.vue2项目配置vite-plugin-federation
- 安装@originjs/vite-plugin-federation
npm i @originjs/vite-plugin-federation
- 创建Button组件并配置federation
....
import federation from "@originjs/vite-plugin-federation";
.....
federation({
name: 'vue2App',//远程模块名称
filename: 'remoteEntry.js',//远程模块入口文件,本地模块可通过vite.config.ts的remotes引入
exposes: {//远程模块对外暴露的组件列表,远程模块必填
'./Button': './src/components/Button.vue',
},
}),
<template>
<div>
<button>哈哈哈哈哈哈哈</button>
</div>
</template>
- npm run build 打包vue2项目
- vue2中vite.config.js完整配置
import { createVuePlugin } from 'vite-plugin-vue2'
import federation from "@originjs/vite-plugin-federation";
// import topLevelAwait from 'vite-plugin-top-level-await'
export default {
plugins: [
createVuePlugin(),
federation({
name: 'vue2App',//远程模块名称
filename: 'remoteEntry.js',//远程模块入口文件,本地模块可通过vite.config.ts的remotes引入
exposes: {//远程模块对外暴露的组件列表,远程模块必填
'./Button': './src/components/Button.vue',
},
// shared: ["vue"],//本地模块和远程模块共享的依赖。开启需放开topLevelAwait
}),
// topLevelAwait({
// // The export name of top-level await promise for each chunk module
// promiseExportName: '__tla',
// // The function to generate import names of top-level await promise in each chunk module
// promiseImportName: i => `__tla_${i}`
// }),
],
build: {
polyfillModulePreload: false,
assetsInlineLimit: 40960,
target: 'es2020',
minify: false,
cssCodeSplit: false,
rollupOptions: {
output: {
minifyInternalExports: false
}
}
}
}
3.使用vite+ts搭建vue3项目
此处不在赘述,参考官网cn.vuejs.org/guide/quick…
4.vue3项目配置vite-plugin-federation
- 安装federation并配置
......
import federation from "@originjs/vite-plugin-federation";
......
federation({
name: "vite-host",
filename: "remoteEntry.js",
remotes: {
remote1: "http://127.0.0.1:5174/dist/assets/remoteEntry.js",
},
// shared: ["vue"]
}),
......
- vite.config.js完整配置
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import federation from "@originjs/vite-plugin-federation";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),
federation({
name: "vite-host",
filename: "remoteEntry.js",
remotes: {
remote1: "http://127.0.0.1:5174/dist/assets/remoteEntry.js",
},
// shared: ["vue"]
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
target: 'es2022',
minify: false,
cssCodeSplit: true,
rollupOptions: {
output: {
minifyInternalExports: false
}
}
},
})
- 使用vue2组件
<script setup lang="ts">
import { vue2ToVue3 } from './Vue2ToVue3';
import Button from 'remote1/Button';
const Vue2Button = vue2ToVue3(Button, 'vue2Button')
</script>
<template>
<div id="vue2Button"></div>
<vue2-button />
</template>
<style scoped>
</style>
- Vue2ToVue3
import Vue2 from './Vue2.js' // 2.6.14版本的vue源码
function bindSlotContext (target = {}, context) {
return Object.keys(target).map(key => {
const vnode = target[key];
vnode.context = context;
return vnode;
});
}
export function vue2ToVue3 (WrapperComponent, wrapperId) {
let vm;
return {
mounted () {
const slots = bindSlotContext(this.$slots, this.__self);
vm = new Vue2({
render: createElement => {
return createElement(
WrapperComponent,
{
on: this.$attrs,
attrs: this.$attrs,
props: this.$props,
scopedSlots: this.$scopedSlots,
},
slots,
);
},
});
vm.$mount(`#${wrapperId}`);
},
props: WrapperComponent.props,
render () {
vm && vm.$forceUpdate();
},
};
}
- 启动vue3项目,即可看见效果
3.结尾
只是简单的实现了vue3引入vue2简单的Button组件,具体实践中使用会有什么问题,还不清楚