分享

微前端:接入qiankun踩坑之旅

 丝录小馆 2023-05-17 发布于天津
 

对于微前端这个概念,作为常年码字的猿猴们已经不再陌生,可以说目前已经是一个非常成熟的领域了。

近两年,很多成熟方案可选用,例如qiankun、micro-app、EMP 方案。基于当前文档搜索和应用范围来说,qiankun是目前应用比较广泛的方案。

01 qiankun现状

qiankun 方案是基于 single-spa 的微前端方案。

优点如下:

  • html entry 的方式引入子应用,相比 js entry 极大的降低了应用改造的成本;

  • 完备的沙箱方案,js 沙箱做了 SnapshotSandbox、LegacySandbox、ProxySandbox 三套渐进增强方案,css 沙箱做了 strictStyleIsolation、experimentalStyleIsolation 两套适用不同场景的方案;

  • 做了静态资源预加载能力;

  • 可以不用关注子项目的框架结构,能够兼容vue、react、angular甚至jsp等老项目

不足之处也是显而易见:

  • 适配成本比较高,工程化、生命周期、静态资源路径、路由等都要做一系列的适配工作;

  • css 沙箱采用严格隔离会有各种问题,js 沙箱在某些场景下执行性能下降严重;

  • 无法同时激活多个子应用,也不支持子应用保活;

  • 无法支持 vite 等 esmodule 脚本运行

02 qiankun有哪些坑?

qiankun虽有官方文档说明,参考地址如下:

https://qiankun.umijs.org/zh/guide/tutorialbr

以你为有了这个地址,就可以为所欲为了么? “No”

在应用过程中会有很多问题出现,能参考的文档并不完善,基于对于几种框架现有方案考虑,我们的项目选择了vue作为主项目,接入了已存在的react、vue2、vue3等子项目,对于网络参考较少的相应问题,我做了一个简单罗列,希望可以为你提供参考,不要跌进同一个坑里:

  Q1 生命周期报错:

Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry

你以为真的是子项目生命周期出了问题,于是按照官网一波操作猛如虎,enter一下,发现未必生效,是因为注入js的地方被占用了,答案如下,去掉红框部分,将jsonlint格式移至utilsli即可:

Q2 接入vue3时,报错如下:

[import-html-entry]: error occurs while excuting xxx script http://xxx.xxx.xxx/x.js

查找文档时,网上大神告诉你,改一下你报错的js就好了,于是你发现并没有找到这个报了错的js,连这个文件都没有,大大脑袋里全是问号。

排查发现主子项目里main.js里都包含了babel-polyfill这个引入,导致了冲突,去掉其中一个,只引入一次就ok了,至于如何改造,自己衡量:

import 'babel-polyfill'import Es6Promise from 'es6-promise'require('es6-promise').polyfill()Es6Promise.polyfill()

Q3 父子项目样式覆盖问题:

1)父、子项目class重名

2)添加沙箱隔离:

sandbox: {        experimentalStyleIsolation: true,  //沙箱默认开启        strictStylelsolation: v.strictStylelsolation//基于shadow DOM的样式隔离,开启严格的样式隔离      },

Q4 微应用加载失败:

'xxxxx' died in status NOT_MOUNTED // 微应用加载失败

在路由和子项目接受参数正确的前提下还有问题,就要警惕你在脚手架中的组件注册和引入了,正确写法如下:

main.js

const requireComponents = require.context('@/components', false, /\.vue/);requireComponents.keys().forEach(fileName => {  // 组件实例  const reqCom = requireComponents(fileName);  // 截取路径作为组件名  var reqComName = reqCom.name || fileName.replace(/\.\/(.*)\.vue/, '$1');
// 组件挂载 Vue.component(reqComName, reqCom.default || reqCom);})

Q5 Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema:

ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. - configuration.output has an unknown property 'jsonpFunction'. These properties are valid:   object { assetModuleFilename?, asyncChunks?, auxiliaryComment?, charset?, chunkFilename?, chunkFormat?, chunkLoadTimeout?, chunkLoading?, chunkLoadingGlobal?, clean?, compareBeforeEmit?, crossOriginLoading?, cssChunkFilename?, cssFilename?, devtoolFallbackModuleFilenameTemplate?, devtoolModuleFilenameTemplate?, devtoolNamespace?, enabledChunkLoadingTypes?, enabledLibraryTypes?, enabledWasmLoadingTypes?, environment?, filename?, globalObject?, hashDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateGlobal?, hotUpdateMainFilename?, iife?, importFunctionName?, importMetaName?, library?, libraryExport?, libraryTarget?, module?, path?, pathinfo?, publicPath?, scriptType?, sourceMapFilename?, sourcePrefix?, strictModuleErrorHandling?, strictModuleExceptionHandling?, trustedTypes?, umdNamedDefine?, uniqueName?, wasmLoading?, webassemblyModuleFilename?, workerChunkLoading?, workerWasmLoading? }   -> Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.   Did you mean output.chunkLoadingGlobal (BREAKING CHANGE since webpack 5)?    at validate (E:\item\ipc_protal\tssc-customer\node_modules\webpack\node_modules\schema-utils\dist\validate.js:105:11)    at validateSchema (E:\item\ipc_protal\tssc-customer\node_modules\webpack\lib\validateSchema.js:78:2)    at create (E:\item\ipc_protal\tssc-customer\node_modules\webpack\lib\webpack.js:111:24)    at webpack (E:\item\ipc_protal\tssc-customer\node_modules\webpack\lib\webpack.js:158:32)    at f (E:\item\ipc_protal\tssc-customer\node_modules\webpack\lib\index.js:64:16)    at serve (E:\item\ipc_protal\tssc-customer\node_modules\@vue\cli-service\lib\commands\serve.js:185:22)    at processTicksAndRejections (internal/process/task_qu

webpack 需要配置output 为了父应用辨识资源

我这里写的都是在配置中需要注意的是:

publicPath:需要写绝对路径,否则父应用获取静态资源时会异常

如果是你使用的是webpack4,配置jsonpFunction

如果你使用的是webpack5,配置chunkLoadingGlobal

   写在最后:

其余常用的还有iframe接入方案,采用qiankun来加载子应用,具有成本低、速度快、原生隔离、功能强大等一系列优点,在满足用户核心诉求的同时让使用微前端的体验就像使用普通组件一样简单,极大的降低了使用门槛,但同时也存在诸多问题,有需要的小伙伴们慎用。

END

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多