初入微前端---qiankun学习这一篇就够了,并在vite中使用qiankun
Posted 陈Joys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初入微前端---qiankun学习这一篇就够了,并在vite中使用qiankun相关的知识,希望对你有一定的参考价值。
目录
https://github.com/qq2084470563/qiankun-samples
原因
最近公司由于一个奇怪的需求,需要将一个项目嵌入到另一个项目中,其中一个项目是react的,另一个则是vue的,最开始我的提议是将项目重构到系统,但是这样会产生非常严重的问题,一方面是本来运行就慢的vue项目(每次跑起来都要30s,非常影响开发),更加雪上加霜了,另外实际给下来的时间并不多,所以,在没有时间,尽量不重新塞进东西,初期定稿使用最基本的技术,通过ifram嵌入,但是在前几日,看到群友讨论到了微前端的哪个框架好,一下就点醒我了,话不多说就直接上车了。
Why Not iframe?
如果说在不考虑性能体验的情况下来说,用iframe是最佳,也是最简单的方式了。
对于iframe来说,最大也是最硬的特性就是硬隔离,所有的样式,js都是完全隔离,这种沙箱隔离是很难去突破的,从而导致应用上下文不共享,带来的开发体验和使用体验的不好。
通常情况下,我们iframe的页面我们一般会通过message事件去进行通信,这也是iframe的最优实现通信。
- 其中最为关键的问题的就是慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
- 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
- url不共享,用iframe外面一个url,iframe一个url,且不能使用外部的浏览器回退,前进键。
- UI不会共享,页面的dom结构不共享,样式什么的做起来不方便,假如现在要设计屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中,内部遮罩是不可能出来的。
qiankun
为什么选择这个框架,这个框架是蚂蚁基于 single-spa 进行二次封装,乾坤是基于single-spa的二次开发,它在 single-spa 基础上添加更多的功能,并且做了不错的封装,大大降低了入门微前端的门槛。
使用qiankun部署项目
创建一个文件夹,在里面创建一个主项目,作为基座,这个项目中不用考虑用什么,只是做为一个基座容器,然后创建嵌入的子项目。
打开我们的基座项目main-service 添加项目依赖,载入乾坤的包,
yarn add qiankun
按个人习惯,或者根据自己团队改造一下初始代码,我这里按自己的习惯去修改结构。
接下来进入主体,开始编写我们的主应用main-service 创建一个qiankun 文件,具体Api参考qiankun官网。
- 搭建微应用的列表,进行注册。
- 不要忘记钩子函数注册一下,方便自己查看挂哪里了
- 启动qiankun,通过startapi。
import
registerMicroApps,
runAfterFirstMounted,
setDefaultMountApp,
start,
from 'qiankun'
// 引入vue实例
import isLoading from '@/App'
/**
* 加载动画运行
* @param loading
*
*/
function loader(loading: boolean)
isLoading.value = loading
// if(instance && instance.$children)
const microApps = [
name: 'sub-react',
developer: 'react',
entry: '//localhost:40001',
activeRule: '/sub-react',
,
name: 'sub-vite-react',
developer: 'vite-react',
entry: '//localhost:40002',
activeRule: '/sub-vite-react',
,
]
const apps = microApps.map((item) =>
return
...item,
loader, // 给子应用配置加上loader方法
container: '#sub-container',
props:
developer: item.developer, // 下发基础路由
routerBase: item.activeRule, // 下发基础路由
,
configuration:
strictStyleIsolation: true,
,
)
registerMicroApps(apps,
beforeMount: [
(app): any =>
console.log('开始挂载:', app.name)
,
],
afterMount: [
(app): any =>
console.log(app.name, '挂载成功了')
,
],
afterUnmount: [
(app): any =>
console.log('贾维斯卸载 ', app.name)
,
],
)
/**
* 设置默认进入的子应用
*/
// setDefaultMountApp('/sub-vite2-react')
start()
runAfterFirstMounted(() =>
console.log('贾维斯开机')
)
export microApps
export default apps
这一段代码很简单,只要就是创建一个subapp的列表,并且注册,运行我们的qiankun,之所以如此简便是因为蚂蚁对single-spa高度封装,简便操作,并提供api,提高效率。
接下来主项目引入路由。
- 引入router 。
- 编写路由文件
yarn add vue-router
const menuRoutes: MyRouteType[] = [
path: '/index',
key: '/index',
name: 'Index',
component: () => Promise.resolve(Main),
,
]
const routes: MyRouteType[] = [
path: '/',
key: '/',
redirect: '/index',
,
path: '/:pathMatch(.*)',
key: '*',
redirect: '/404',
,
]
microApps.forEach((item) =>
menuRoutes.push(
path: item.activeRule,
key: item.name,
name: item.name,
component: () => Promise.resolve(Sub),
)
)
routes.push(...menuRoutes)
const router = createRouter(
history: createWebHistory(),
routes,
)
路由中主要是引入qiankun的路由进行配置,在关键的页面组件中写挂载的元素
在子路由的页面去暴露根元素
import defineComponent from 'vue'
export const Sub = defineComponent(
setup()
return () =>
return <div id='sub-container'></div>
,
)
其实到这里,主应用可以说基本的完成了,接下来先部署子应用。
Create-react-app 子应用
假如说我们有一个情况,当前应用是一个以前技术栈的老项目,我们需要在不抛弃老项目,老技术的情况下去上新的模块,那么我们该怎么操作呢?
- 在
src
目录新增public-path.js
- 设置
history
模式路由的base
- 在子应用 sub-react中暴露钩子函数。
- 安装插件
@rescripts/cli
,当然也可以选择其他的插件,例如react-app-rewired
。 - 修改webpack文件保证dev还是prod环境都可跑通。
按照官网的走,新增public-path.js文件里加上配置做为子应用是根路径,并且配合webpack使用。
if (window.__POWERED_BY_QIANKUN__)
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
接下来在子项目中暴露钩子函数让父应用调用 main.js 。
修改渲染函数执行
function render()
ReactDOM.render(
<App />,
document.getElementById('root')
);
if (!window.__POWERED_BY_QIANKUN__)
render();
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap()
console.log('react app bootstraped');
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props)
console.log(props);
storeTest(props);
render();
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount()
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
/**
* 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
*/
export async function update(props)
console.log('update props', props);
暴露了钩子函数后,我们接下来就要配置webpack,因为react中webpack是藏起来的,需要执行命令编辑
yarn eject
但是这个操作是不可逆的,展开的文件不仅复杂,看着那么多文件也难受,所以说我们使用第三方库去配置webpack以及devserver,qiankun的官方使用了 @rescripts/cli 同时也推荐了其他的,翻找一下资料,发现这个库好久没更新了,也没看到文档,所以我选择使用react-app-rewired,从npm官网看起来这个稍微友好一点。
引入第三方库
yarn add react-app-rewired -D
编辑配置文件 config-overrides.js 在根路径,跨域是必须要写的否则父应用无法fetch到微应用。
const name = require('./package.json')
console.log(name)
module.exports =
webpack: function (config, env)
if (Array.isArray(config.entry))
config.entry = config.entry.filter(
(e) => !e.includes('webpackHotDevClient')
)
// config.entry = config.entry.includes('webpackHotDevClient')
config.output.library = `$name-[name]`
config.output.libraryTarget = 'umd'
config.output.chunkLoadingGlobal = `webpackJsonp_$name`
// 写项目启动的源,否则图片无法显示
config.output.publicPath = 'http://localhost:40001/'
return config
,
devServer: (configFunction) =>
return function (proxy, allowedHost)
const config = configFunction(proxy, allowedHost)
config.open = false
config.hot = false
config.headers =
'Access-Control-Allow-Origin': '*',
// Return your customised Webpack Development Server config.
return config
,
修改package.json里面的执行脚本。
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test",
+ "test": "react-app-rewired test",
- "eject": "react-scripts eject"
如此我们的项目就已经可以嵌入了,效果大概是下图,千万别忘记配置环境中的端口,要和主应用的端口匹配。
当然这样写下来其实是存在一个问题,子页面的样式元素可能会影响外部,这是因为qiankun默认子应用的之间隔离,但是没有隔离主子应用,
只需要开启严格模式 ,即可确保不影响全局。
在vite中使用qiankun
在这里我为什么要当拿出来vite的项目去说呢,从现在环境来看vite大火,vite拥有在开发环境下极快的编译速度,热更新监听,但是碍于vite发展时间不长,所以生态方面来说不够成熟,有些功能还是比较尴尬的。
为何vite中不能到生命周期钩子函数呢?具体原因是什么呢?
vite
构建的js
内容必须在type=module
的script
脚本里;qiankun
的源码依赖之一import-html-entry
则不支持type=module
这个属性qiankun
是通过eval
来执行这些js
的内容,而vite
里面import/export
没有被转码, 所以直接接入会报错:不允许在非type=module
的script
里面使用import
大概就是这个原因,自己写的时候都是这样报错,那我们该如何巧妙的将两种融合起来呢。翻阅各种资料,并且查看qiankun的isssues找到了两个解决方法.
方法一(不太推荐):
因为vite使用的rollup,所以我们使用可以使用rollup插件 rollup/plugin-html,然后修改vite.config.js中build的配置,把vite默认输出的target模式修改一下,将module改为esnext。
因为配置的是build配置所以有缺点
:
- 可以实现生产环境接入,开发环境不行;
vite
没有动态publicPath
的支持;所以Vite.config
中base
配置需要写死vite
code-splitting(
代码分割)功能并不支持iife
和umd
两种格式,导致路由无法懒加载;- 图片资源只会被打包成
base64
,无论图片大小
具体可以详细步骤可以查看issues的提交。
https://github.com/umijs/qiankun/issues/1268
方法二(推荐):
vite-plugin-qiankun
插件; github文档。
在不改变原有的东西在这个基础上以插件的形式融合进去。优点:
- 保留
vite
构建es
模块的优势 - 一键配置,不影响已有的
vite
配置 - 支持
vite
开发环境
安装插件
除了qiankun插件还需要一个一个react热更新的插件,这是因为开发环境作为子应用时与热更新插件(可能与其他修改html的插件也会存在冲突)有冲突,所以需要额外的调试配置,于是换个方式实现热更新。
yarn add vite-plugin-qiankun
yarn add @vitejs/plugin-react-refresh
修改vite.config.js配置:
import defineConfig from 'vite'
import qiankun from 'vite-plugin-qiankun'
import reactRefresh from '@vitejs/plugin-react-refresh'
// useDevMode 开启时与热更新插件冲突
const useDevMode = true
// https://vitejs.dev/config/
export default ( mode ) =>
const __DEV__ = mode === 'development'
return defineConfig(
plugins: [
...(useDevMode ? [] : [reactRefresh()]),
qiankun('sub-vite-react',
useDevMode: true,
),
],
server:
port: 40002,
host: '0.0.0.0',
// 设置源是因为图片资源会找错位置所以通过这个让图片等资源不会找错
origin: '//localhost:40002',
cors: true,
headers:
'Access-Control-Allow-Origin': '*',
,
,
base: __DEV__ ? '/' : '//localhost:40002',
)
修改main.ts暴露钩子函数:
js只要把类型标注删一下就可以了
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
// vite-plugin-qiankun helper
import
renderWithQiankun,
qiankunWindow,
QiankunProps,
from 'vite-plugin-qiankun/dist/helper'
let root: ReactDOM.Root | null = null
function render(props: QiankunProps)
const container = props
const root = ReactDOM.createRoot(
(container
? container.querySelector('#root')
: document.getElementById('root')) as HTMLElement
)
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
return root
renderWithQiankun(
mount(props)
console.log('vite-react 上线了')
root = render(props)
,
bootstrap()
console.log('bootstrap')
,
unmount(props)
console.log('vite-react 下线了')
const container = props
root?.unmount()
,
update(props)
console.log('vite-react更新了', props)
,
)
if (!qiankunWindow.__POWERED_BY_QIANKUN__)
root = render()
配置好了启动所有项目就可以看到所有项目了。
结尾
一直一直写发现我们的子类越来越多了,每次启动我我们都要到各个路径启动项目然后才能看到全貌所有我们需要定义一个指令能够在最外层把所有指令逐个配置启动,和全部一起启动。
初始化文件
yarn init
下载依赖包
yarn add yarn-run-all
修改package.json
"scripts":
+ "install": " npm-run-all -s install:*",
+ "install:main":"cd main_service && yarn ",
+ "install:sub-react":"cd sub-service/sub-react && yarn",
+ "install:sub-vite-react":"cd sub-service/sub-vite-react && yarn",
+ "start": "npm-run-all -p start:*",
+ "start:main": "cd main_service && yarn dev",
+ "start:sub-react": "cd sub-service/sub-react && yarn start",
+ "start:sub-vite-react": "cd sub-service/sub-vite-react && yarn dev"
,
配置好后我们使用指令安装依赖,和启动就好了,便利团队开发。
最后
qiankun项目的基本部署就这样,但是其实不难发现这里一直将微应用部署到主应用中,但是还没说过具体的应用键传值,但是其实如此部署之后发现其实项目是在同一个地址里,也就是说有共通的localStorage,sessionStorage,以及cookie。那么在复杂场景中肯定需要通信,但是由于篇幅太长了,所以这里重点是使用qiankun的部署。
应用间传值:
github地址:
https://github.com/qq2084470563/qiankun-samples
前端开发框架工具汇总,看这一篇就够了!
孔子说:“工欲善其事,必先利其器”,学习WEB前端开发也是一样。在开发过程中,经常我们会遇到很多繁杂精细的麻烦问题,虽然知道要去按照步骤解决,但总归耗费大量的时间。
再加上最近很多小伙伴问小渡:有没有好用的前端开发工具推荐呢?小渡今天就特地整理了一批好用的web前端开发框架和他们的特点,帮助大家根据不同的需求,不同的业务场景,做出最合适的选择,让开发变得高效,快速。
有了这些工具在手,就可以从繁重的工作任务中解脱出来,有大把的时间去王者峡谷散步打野浪一圈了。
前方干货来袭!还不准备好小板凳认真做笔记~
1、Alertify.js
网站:http://alertifyjs.com/
AlertifyJS是一个用于开发浏览器对话框和通知的JavaScript框架,它不仅提供了默认浏览器对话框的替代,更使得创建自己的界面变得非常简单。
2-AngularJS1.X
网站:angularjs.org
angularjs是一个javascript框架。通过script脚本引入,是一个用Javascript编写的库。angularjs通过指令扩展了HTML,通过表达式绑定数据到HTML中。
AngularJS主要考虑的是构建CRUD(增删改查)应用。幸运的是,至少90%的WEB应用都是CRUD应用。
优点:
1、一些大公司正在使用的流行框架
2、开发现代Web应用程序的解决方案
3、是标准MEAN栈(MongoDB,Express.JS,AngularJS,NodeJS)的一部分,有许多文章和教程可用
缺点:
1、学习曲线陡峭
2、大的代码库
3、无法升级到Angular2.x
3-Angular4.X
网站:angular.io
其实关于为什么从2直接跳跃到了4,其实很简单,原因是,Angular2这个framework有点大,core分了好几个libraries,都分别属于不同的npmpackage。
所有的libraries本来都乖乖的按照一个方式命名,非得有个人要起幺蛾子,就是那个叫angular/router的货,人家都是2.3.0,这个幺蛾子非得叫3.3.0。
Angular团队本来计划好的Angular3 就会有一系列的3.x.x加上一个4.x.x。估计是为了照顾router的情绪吧,决定全体改成4得了。并没有什么隐形关卡哦。
优点:
1、开发现代Web应用程序的解决方案;
2、是标准MEAN栈的一部分,尽管只有少量的教程可用;
3、对于熟悉静态类型语言(如C#和Java)的开发人员,TypeScript提供了一些优势。
缺点:
1、学习曲线陡峭;
2、大的代码库;
3、不能从Angular1.x升级;
4、与1.x相比,Angular2.x较难理解。
4-REACT
网站:facebook.github.io/react/
React是一个用于创建用户界面的开源JavaScript库,旨在解决开发单页应用程序时遇到的挑战。
优点:
1、小巧,高效,快捷灵活;
2、简单的组件模型;
3、良好的文档和在线资源;
4、可实现服务器端渲染;
5、目前受欢迎,经历了快速增长。
缺点:
1、需要学习新的概念和语法;
2、构建工具很重要;
3、需要其它类库或框架提供model和Controller部分;
4、与修改DOM的代码和其它类库不兼容。
5-Vue.js
网站:vuejs.org
通常,大家不信任年轻的程序员是因为他们缺乏经验。然而,很多新技术却吸引了大量的程序员,因为它们弥补了以前工具的缺点。这就是Vue.js成功的地方。
程序员让Vue.js尽可能简单,并让接近88%的用户对其感到满意。Vue用于阿里巴巴、百度和WizzAir等。
优点:
1、可以快速使用,并且日益普及;
2、很容易提高高水平开发人员的满意度;
3、依赖性小,性能好。
缺点:
1、一个较新的项目– 风险可能会更大;
2、部分依赖开发人员进行更新;
3、相比于其它框架,资源较少;
6-Backbone.js
网站:backbonejs.org
backbone作为一个老牌js框架为大规模前端开发提供了新的开发思路:前端MVC模式。
这个模式也是前端开发演变过程中的一个重要里程碑,也为MVVM和Redux等开发思路奠定了基础,后来的react,vue无不是在backbone的影响下开创出来的经典模式。
优点:
1、体积小,重量轻,复杂度低;
2、不添加HTML逻辑;
3、文件丰富;
4、采用了许多应用,包括Trello、WordPress.com、LinkedIn和Groupon。
缺点:
1、与AngularJS等其它框架相比,抽象度较低;
2、需要额外的组件来实现数据绑定等功能;
3、最新的框架已经不采用MVC架构了。
7-Ember.js
网站:emberjs.com
这是一个用于创建web应用的JavaScript MVC框架,采用基于字符串的Handlebars模板,支持双向绑定、观察者模式、计算属性(依赖其他属性动态变化)、自动更新模板、路由控制、状态机等。
优点:
1、为客户端应用程序提供了单一解决方案;
2、开发人员可以立刻提高开发效率– 它使用jQuery;
3、良好的向后兼容性和升级选项;
4、采用了现代Web开发标准。
缺点:
1、大型分配式;
2、与其它正在向较小组件结构发展的框架相比,它十分的庞大。
8-Knockout.js
网站:knockoutjs.com
Knockout.js是一个基于MVVM模式的轻量级的前端框架,能够友好地处理数据模型和界面DOM的绑定。
最重要的是,它的绑定是双向的,也就是说数据模型变化了,界面DOM上的数据也会跟着发生变化,反过来,界面DOM上的数据变化了,数据模型也会相应这个变化。
这样能够大大减少我们的前端代码量,并且使得我们界面易于维护,再也不用写一大堆事件监控数据模型和界面DOM的变化了。
优点:
1、小而轻便,无依赖;
2、优秀的浏览器支持;
3、良好的文档资源。
缺点:
1、较大的项目可能变得很复杂;
2、发展已经放缓;
3、使用情况似乎在减弱。
9-Aurelia
网站:https://aurelia.io/
一种相对较新的,轻量级的跨平台框架,下一代 JavaScript 客户端框架,利用简单的约定来激发你的创造力。
凭借其强大的专注于开发经验, Aurelia 可以使您不仅创造惊人的应用程序,同时也享受这个过程。它经过精心设计,是可插拔和可定制的。
优点:
1、双向绑定,可扩展的html,Web Component等;
2、嵌套路由。
缺点:
1、UI等组件太少;
2、不提供数据层。
10-Keras.js
网站:
https://transcranial.github.io/keras-js/
Keras.js是另外一个热门的开源框架,它使你能够在浏览器中运行机器学习模型,使用WebGL来提供GPU模式的支持。
优点:
1、API简单,易用。
2、文档齐全,并且文档内容组织地很好。
3、扩展性好。后端支持Tensorflow, theano,mxnet,cntk. 而且自定义层也比较好写。
4、使用人群分布很广。
缺点:
1、速度慢。后端如果使用mxnet或cntk,速度会快些;如果使用Tensorflow或theano,速度很慢。
2、程序占用GPU内存比较多。
//////////
目前最为流程的框架是React,同时其它的框架也在向着流行的趋势发展。如果需要一个安全的、通用的Web应用程序,可以考虑使用Vue.js。
当然,web框架工具还有很多,也许小渡无法告诉你哪个是最好的,但是最适合自己的、项目的,就是最好的。多用多学多练习,才更适合你们哦!
以上是关于初入微前端---qiankun学习这一篇就够了,并在vite中使用qiankun的主要内容,如果未能解决你的问题,请参考以下文章