微前端的概念、好处,为什么不用npm和iframe之类的问题,网上有很多,这里就不解释了。
个人理解就是:避免了“巨石应用”的出现,解决了项目与项目之间的代码重复。
single-spa官网:https://single-spa.js.org/
有中文版的页面,不过最好看英文版的,因为有些页面中文版的不全,这困扰了我很长时间。
以下是single-spa在vue3项目中基础功能的操作步骤。其他的功能会后期陆续更新。
- 安装single-spa
npm install --global create-single-spa
- 分别创建主项目、子项目、组件项目
create-single-spa base
共3个选项,1:子项目或者组件项目、2:我也不太懂、3:主项目
选择自己通过什么安装
1、是否使用ts
2、是否使用提供的模板
3、组织名称
输入后就开始安装了
安装成功
安装子项目与组件项目步骤相同
这里选择第一个
这里选择你使用的框架
这里选择你需要的框架版本和其他插件。
安装完成 - 分别启动三个项目
主项目用npm run start
子项目与组件项目用
npm run serve
主项目打开是这样的
组件项目与子项目打开是这样的
- 改造主项目
修改src下的index.ejs
在这里引入其他项目,根据不同环境配置不同的项目地址,现在就先写本地。这里要严格遵守JSON格式。
注意这一行,大概意思就是限制请求的url,我也不知道怎么改,我就直接注释掉了。
修改src下的**-root-config.js
把原先的registerApplication注释掉,写自己需要加载的项目并配置,
这个时候访问上面的路径就可以看到子项目的页面已经被加载过来了。 - 修改组件项目
修改src下的main.js文件
这里直接用了vue生成项目时就有的HelloWorld.vue文件。
引入并赋值给rootComponent属性,其他不用修改。 - 在子项目中引入组件项目
修改子项目的App.vue文件
参考:https://single-spa.js.org/docs/ecosystem-vue#parcels
这样我们就可以看到组件项目中的组件被引入到子项目中了。<template> <div> <img alt="Vue logo" src="./assets/logo.png" /> <HelloWorld msg="Welcome to Your Vue.js App" /> <p>--------------------------------------------------------</p> <Parcel v-on:parcelMounted="parcelMounted()" v-on:parcelUpdated="parcelUpdated()" :config="parcelConfig" :mountParcel="mountParcel" :wrapWith="wrapWith" :wrapClass="wrapClass" :wrapStyle="wrapStyle" :parcelProps="getParcelProps()" /> </div> </template> <script> import HelloWorld from "./components/HelloWorld.vue"; import Parcel from "single-spa-vue/dist/esm/parcel"; //引入parcel组件 import { mountRootParcel } from "single-spa"; //引入mountRootParcel方法 export default { name: "App", components: { HelloWorld, Parcel, }, data() { return { /* parcelConfig (object, required) The parcelConfig is an object, or a promise that resolves with a parcel config object. The object can originate from within the current project, or from a different microfrontend via cross microfrontend imports. It can represent a Vue component, or a React / Angular component. https://single-spa.js.org/docs/recommended-setup#cross-microfrontend-imports Vanilla js object: parcelConfig: { async mount(props) {}, async unmount(props) {} } // React component parcelConfig: singleSpaReact({...}) // cross microfrontend import is shown below */ parcelConfig: window.System.import("@hnw/el-components"), //这里的window是有必要的,不然会找不到System,参数就是在主项目中引入子项目时的名字; /* mountParcel (function, required) The mountParcel function can be either the current Vue application's mountParcel prop or the globally available mountRootParcel function. More info at http://localhost:3000/docs/parcels-api#mountparcel */ mountParcel: mountRootParcel, /* wrapWith (string, optional) The wrapWith string determines what kind of dom element will be provided to the parcel. Defaults to 'div' */ wrapWith: "div", /* wrapClass (string, optional) The wrapClass string is applied to as the CSS class for the dom element that is provided to the parcel */ wrapClass: "bg-red", /* wrapStyle (object, optional) The wrapStyle object is applied to the dom element container for the parcel as CSS styles */ wrapStyle: { outline: "1px solid red", }, }; }, methods: { // These are the props passed into the parcel getParcelProps() { return { text: `Hello world`, }; }, // Parcels mount asynchronously, so this will be called once the parcel finishes mounting parcelMounted() { console.log("parcel mounted"); }, parcelUpdated() { console.log("parcel updated"); }, }, }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
这样就完成了single-spa中最基础的功能。