微前端该怎么理解呢?微小的前端吗?根据字面意思好像可以这么拆解,实际呢,在我们的前端应用中可以把一个大的项目,分为多个小应用,多个应用之间相互独立,互不影响,独立的技术栈,独立的部署环境,最终把这些独立的子应用,放入到我们的主应用中,称之为微前端,这是大面包的理解。
一、准备一个框架,作为项目的主应用
项目安装此处省略,大面包用vue项目作为主应用
二、安装qiankun
在主应用安装qiankun
npm i qiankun //默认安装到dep
三、在主应用使用qiankun
//App.vue
<div>
<div class="tab">
<router-link :to="item.path" v-for="item in routerPath" :key="item.name">
<span class="span" :class="{'active': $route.path === item.path}">{{item.name}}</span>
</router-link>
</div>
<!-- 页面渲染 -->
<router-view></router-view>
<div id="sub-container"></div>
</div>
//routerPath
routerPath: [
{
name: 'Home',
path: '/home'
},
{
name: 'Vue',
path: '/vue'
},
{
name: 'React',
path: '/react'
}
]
//main.js
//1.引入qiankun
import { registerMicroApps, start } from 'qiankun';
//路由为哈希时或许可以用到
//const getActiveRule = (hash) => (location) => location.hash.startsWith(hash);
//2.配置子应用
const apps = [
// 子应用1:qiankun-vue
{
// 子应用名称
name: "vueAPP",
// 子应用入口:默认会加载这个 html 并解析里里面的 js 然后动态的执行(子应用必须支持跨域)
entry: process.env.VUE_APP_SUB_VUE,
// 容器:将子应用挂载到 #sub-container 元素上
container: "#sub-container",
// 激活规则:访问 /vue 时将子应用挂载到 #sub-container 上
activeRule: '/vue',
// 传递属性
props: {
name: "大面包",
sex: "男",
},
},
// 子应用2:qiankun-react
{
// 子应用名称
name: "reactAPP",
// 子应用入口:默认会加载这个 html 并解析里里面的 js 然后动态的执行(子应用必须支持跨域)
entry: process.env.VUE_APP_SUB_REACT,
// 容器:将子应用挂载到 #sub-container 元素上
container: "#sub-container",
// 激活规则:访问 /react 时将子应用挂载到 #sub-container 上
activeRule: "/react",
// 给子应用传递属性
props: {
name: "Chess",
sex: "男",
},
},
];
//3.注册apps
registerMicroApps(apps);
//4.启动微前端
start();
四、新建一个vue子应用
//main.js
let instance = null;
function render() {
instance = new Vue({
router,
render: h => h(App),
}).$mount('#vue-app')
}
// 动态添加 publicPath
if (window.__POWERED_BY_QIANKUN__) {
//处理资源
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// 判断当前应用是否不在 qiankun 中渲染
if (!window.__POWERED_BY_QIANKUN__) {
// 如果不在 qiankun 中,则直接渲染
render();
}
// 需要导出 qiankun 内部的三个生命周期钩子,以供主应用在合适的时机调用。
// 第一次进入时;props 包含主应用传递的参数,也包括为子应用创建的节点信息。
export async function bootstrap() {
console.log("子应用 2 加载完成");
}
// 每次进入子应用时
export async function mount(props) {
render(props)
}
// 每次退出子应用时
export async function unmount() {
// 卸载子应用
instance.$destroy()
console.log("子应用 2 卸载完成");
}
//vue.config.js
devServer: {
port: 8000,
// 配置头信息
headers:{
// 设置访问此网站的域名
'Access-Control-Allow-Origin' : '*'
},
},
五、我们再来新建一个react的子应用
//1.首先准备一个react项目
//2.安装一个react-app-rewired重写配置文件
npm i react-app-rewired
//3.修改package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
}
//4.根目录下新建一个config.overrides.js
module.exports = {
webpack:(config) => {
config.output.library = 'reactApp';
config.output.libraryTarget = 'umd';
config.output.publicPath = 'http://localhost:3000/';
return config;
},
devServer:(configFunction) => {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost)
config.port = '3000'
config.headers = {
'Access-Control-Allow-Origin': '*'
}
return config
}
}
}
//修改index.js, 导入qiankun内部的三个生命周期钩子
function render() {
ReactDOM.render(
<Test />,
document.getElementById('root')
);
}
// 判断当前应用是否不在 qiankun 中渲染
if(!window.__POWERED_BY_QIANKUN__){
render();
}
export async function bootstrap(){
}
export async function mount() {
console.log('react')
render()
}
export async function unmount(){
ReactDOM.unmountComponentAtNode( document.getElementById('root')); // 卸载节点
}
此时我们的页面效果已经出来的
在搬砖的道路上砥砺前行~