qiankun icon indicating copy to clipboard operation
qiankun copied to clipboard

webpack5 使用模块联邦,抛出异常,生命周期未加载

Open ttttttw opened this issue 3 years ago • 25 comments

webpack5 使用模块联邦,抛出异常,生命周期未加载

在webpack5 使用模块联邦时(子应用作为consume),要求webpack的entry要被额外包装一层,处理成动态引入,如果按照要求使用,那么这时候主应用不能检测到子应用的生命周期,如果只把生命周期也放在这一层,内部不加任何逻辑,是没问题的,但是生命周期中需要做渲染,那么就需要引入react,就会出现异常。请问有什么处理方案吗

image

ttttttw avatar Jun 17 '21 09:06 ttttttw

碰到一样的问题,mark

HULIANGA avatar Aug 26 '21 01:08 HULIANGA

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

ttttttw avatar Aug 26 '21 04:08 ttttttw

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。

1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true }

2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

HULIANGA avatar Aug 26 '21 09:08 HULIANGA

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。

1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true }

2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

ttttttw avatar Aug 26 '21 10:08 ttttttw

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

HULIANGA avatar Aug 26 '21 10:08 HULIANGA

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

wudith avatar Aug 30 '21 09:08 wudith

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

ttttttw avatar Aug 30 '21 14:08 ttttttw

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

我们项目的情况是拆分了很多qiankun微模块,各个微模块之间重复代码需要复用,用npm的话更新一次要更新十几个微模块,想用联合模块来复用这些代码

HULIANGA avatar Aug 31 '21 09:08 HULIANGA

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

补充一下:

  1. 只是配置experiments: { topLevelAwait: true }是不行的,如果用到babel的话,需要额外配置plugin(https://stackoverflow.com/questions/64815808/toplevelawait-invalid-with-babel-loader-await-is-only-allowed-within-async-fu)。
  2. 照这方法试了,还是不行,报错Uncaught Error: application 'app2' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in app2 entry

geweidong avatar Sep 06 '21 10:09 geweidong

既然使用了webpack5的模块联邦,那就不应该再使用qiankun了,模块联邦本身就可以实现微前端架构

zhangchao828 avatar Sep 07 '21 09:09 zhangchao828

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

补充一下:

  1. 只是配置experiments: { topLevelAwait: true }是不行的,如果用到babel的话,需要额外配置plugin(https://stackoverflow.com/questions/64815808/toplevelawait-invalid-with-babel-loader-await-is-only-allowed-within-async-fu)。
  2. 照这方法试了,还是不行,报错Uncaught Error: application 'app2' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in app2 entry

不好意思我漏写了一步,要在html-webpack-plugin里面改一下chunksSortMode,把入口js放最后面,因为mf生成的remoteEntry.js默认是在最后的, image 但是后面又发现了解决不了的问题 ,基座和微应用的页面共享同一个vue组件的时候,在这两个页面切换会报错,大致原因是基座和微应用都引入了一次vue,两次创建的vnode类型symbol(xxx)匹配不上。暂时放弃两者结合了,要么用qiankun要么用mf。不知道react会不会也有这个问题

HULIANGA avatar Sep 10 '21 02:09 HULIANGA

既然使用了webpack5的模块联邦,那就不应该再使用qiankun了,模块联邦本身就可以实现微前端架构

确实,感觉两者的设计思路就是相反的两个方向

HULIANGA avatar Sep 10 '21 02:09 HULIANGA

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

补充一下:

  1. 只是配置experiments: { topLevelAwait: true }是不行的,如果用到babel的话,需要额外配置plugin(https://stackoverflow.com/questions/64815808/toplevelawait-invalid-with-babel-loader-await-is-only-allowed-within-async-fu)。
  2. 照这方法试了,还是不行,报错Uncaught Error: application 'app2' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in app2 entry

不好意思我漏写了一步,要在html-webpack-plugin里面改一下chunksSortMode,把入口js放最后面,因为mf生成的remoteEntry.js默认是在最后的, image 但是后面又发现了解决不了的问题 ,基座和微应用的页面共享同一个vue组件的时候,在这两个页面切换会报错,大致原因是基座和微应用都引入了一次vue,两次创建的vnode类型symbol(xxx)匹配不上。暂时放弃两者结合了,要么用qiankun要么用mf。不知道react会不会也有这个问题

1.是的,需要在Hosts应用的webpack中加配置

chunks: ['app2','app'], // 让入口文件晚于remoteEntry加载
chunksSortMode: "manual"

2.我把Remotes应用入口文件也改成了异步导出,然后发现可以了,我的是React应用,现在在demo中能正常使用。

可以看一下我的demo代码: https://github.com/GeWeidong/federation-demos

geweidong avatar Sep 13 '21 06:09 geweidong

我认为比较好的解决方案:写一个 webpack plugin 然后 hook 到 html-webpack-plugin 写入标签之前的时机,在回调函数中为我们的入口 script(可以通过正则匹配) 属性添加 ‘entry’ 即可。

yuzhanglong avatar Oct 14 '21 03:10 yuzhanglong

mark

xyjxu avatar Dec 10 '21 09:12 xyjxu

谢谢,呵呵!~~

ttttttw avatar Dec 10 '21 09:12 ttttttw

@wudith

更好的去做代码共享,复用公共依赖。之前可能我们使用 external,cdn,等方式提取公共依赖,或者用单独 npm 包的方式抽取公共代码逻辑, 现在用模块联邦可以直接做到.

rubickecho avatar Dec 30 '21 07:12 rubickecho

谢谢,呵呵!~~

ttttttw avatar Dec 30 '21 07:12 ttttttw

"要求webpack的entry要被额外包装一层,处理成动态引入" 这个并不是MF必要的配置,而是webpack的建议:异步边界(asynchronous boundary) ,我目前没有使用这种在入口异步引用的方式,qiankun可以正常使用MF,代码中用到远程模块时,直接用 await import('remote/module1') 这种就行了

hansonfang avatar Mar 02 '22 09:03 hansonfang

谢谢,呵呵!~~

ttttttw avatar Mar 02 '22 09:03 ttttttw

我认为比较好的解决方案:写一个 webpack plugin 然后 hook 到 html-webpack-plugin 写入标签之前的时机,在回调函数中为我们的入口 script(可以通过正则匹配) 属性添加 ‘entry’ 即可。

尝试通过plugins设置入口 script,属性添加‘entry’后,依旧报错“找不到子应用生命周期” demo地址:https://github.com/w123angmeng/demo

w123angmeng avatar Aug 30 '22 07:08 w123angmeng

谢谢,呵呵!~~

ttttttw avatar Aug 30 '22 07:08 ttttttw

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

遇到同样问题,现在有解决方案吗,组件共享不用模块联邦,有什么好的替代方案吗?

w123angmeng avatar Aug 30 '22 07:08 w123angmeng

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

补充一下:

  1. 只是配置experiments: { topLevelAwait: true }是不行的,如果用到babel的话,需要额外配置plugin(https://stackoverflow.com/questions/64815808/toplevelawait-invalid-with-babel-loader-await-is-only-allowed-within-async-fu)。
  2. 照这方法试了,还是不行,报错Uncaught Error: application 'app2' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in app2 entry

不好意思我漏写了一步,要在html-webpack-plugin里面改一下chunksSortMode,把入口js放最后面,因为mf生成的remoteEntry.js默认是在最后的, image 但是后面又发现了解决不了的问题 ,基座和微应用的页面共享同一个vue组件的时候,在这两个页面切换会报错,大致原因是基座和微应用都引入了一次vue,两次创建的vnode类型symbol(xxx)匹配不上。暂时放弃两者结合了,要么用qiankun要么用mf。不知道react会不会也有这个问题

1.是的,需要在Hosts应用的webpack中加配置

chunks: ['app2','app'], // 让入口文件晚于remoteEntry加载
chunksSortMode: "manual"

2.我把Remotes应用入口文件也改成了异步导出,然后发现可以了,我的是React应用,现在在demo中能正常使用。

可以看一下我的demo代码: https://github.com/GeWeidong/federation-demos

项目是vue2.x demo地址:https://github.com/w123angmeng/demo.git 子仓库入口配置: const { bootstrap, mount, unmount } = await import('./bootstrap') export { bootstrap, mount, unmount } 还是报错找不到子应用生命周期函数

w123angmeng avatar Aug 31 '22 10:08 w123angmeng

碰到一样的问题,mark

没找到方案,避开了,放弃了模块联邦

解决了。 1、把入口改成:

const { bootstrap, mount, unmount, update } = await import('./main')
export { bootstrap, mount, unmount, update }

webpack要设置一下 experiments: { topLevelAwait: true } 2、webpack配置的output.library不能跟ModuleFederationPlugin里的name一样。调试了一下发现如果一样的话在import-html-entry里边获取qiankun生命周期会失败

问下这个是哪里看到的方案吗?还是怎么考虑到的?

自己调试找的办法。你可以试试你项目里能不能用

请教下,模块联邦在qiankun中引入的用途是什么呢

项目中一个特殊模块用到了模块联邦,webpack升级到了5,后来想把项目拆分成微前端。组内有其他项目用了qiankun,所以用的一样的。

补充一下:

  1. 只是配置experiments: { topLevelAwait: true }是不行的,如果用到babel的话,需要额外配置plugin(https://stackoverflow.com/questions/64815808/toplevelawait-invalid-with-babel-loader-await-is-only-allowed-within-async-fu)。
  2. 照这方法试了,还是不行,报错Uncaught Error: application 'app2' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in app2 entry

不好意思我漏写了一步,要在html-webpack-plugin里面改一下chunksSortMode,把入口js放最后面,因为mf生成的remoteEntry.js默认是在最后的, image 但是后面又发现了解决不了的问题 ,基座和微应用的页面共享同一个vue组件的时候,在这两个页面切换会报错,大致原因是基座和微应用都引入了一次vue,两次创建的vnode类型symbol(xxx)匹配不上。暂时放弃两者结合了,要么用qiankun要么用mf。不知道react会不会也有这个问题

1.是的,需要在Hosts应用的webpack中加配置

chunks: ['app2','app'], // 让入口文件晚于remoteEntry加载
chunksSortMode: "manual"

2.我把Remotes应用入口文件也改成了异步导出,然后发现可以了,我的是React应用,现在在demo中能正常使用。 可以看一下我的demo代码: https://github.com/GeWeidong/federation-demos

项目是vue2.x demo地址:https://github.com/w123angmeng/demo.git 子仓库入口配置: const { bootstrap, mount, unmount } = await import('./bootstrap') export { bootstrap, mount, unmount } 还是报错找不到子应用生命周期函数


我上面那个解法,react 是没有问题的,vue 我就不知道了。

yuzhanglong avatar Sep 01 '22 03:09 yuzhanglong

各位大佬们,现在这个问题有好的解决办法了吗? @w123angmeng

SanMako avatar Sep 30 '22 08:09 SanMako

谢谢,呵呵!~~

ttttttw avatar Sep 30 '22 08:09 ttttttw

各位大佬们,现在这个问题有好的解决办法了吗? @w123angmeng

  1. 子仓库入口改成 import('./bootstrap') ;
  2. 公共组件项目 MF配置 share配置注释掉; 通过以上处理,qiankun + MF 能实现组件共享,但第三方依赖共享还是有问题(配置share报错);

w123angmeng avatar Sep 30 '22 08:09 w123angmeng

各位大佬们,现在这个问题有好的解决办法了吗? @w123angmeng

  1. 子仓库入口改成 import('./bootstrap') ;
  2. 公共组件项目 MF配置 share配置注释掉; 通过以上处理,qiankun + MF 能实现组件共享,但第三方依赖共享还是有问题(配置share报错);

谢谢大佬

SanMako avatar Sep 30 '22 09:09 SanMako

子应用配置 mf 以后,只需要把用到 remote 的逻辑放在异步边界里就行了,其余的逻辑可以不用改,也可以不用开 topLevelAwait。

import '../public-path'

async function bootstrapWithoutQiankun() {
  if (!window.__POWERED_BY_QIANKUN__) {
    const { render } = await import('./bootstrap')
    render({})
  }
}

bootstrapWithoutQiankun()

const umountHandlerRef: { current?: () => void } = { current: undefined }

export async function bootstrap() {
  console.log('[react18] react app bootstrapped')
}

export async function mount(props: any) {
  const { render, unmount } = await import('./bootstrap')
  render({})
  umountHandlerRef.current = unmount
}

export async function unmount() {
  console.log('[react18] react app unmount')
  umountHandlerRef.current?.()
}

我这边用 mf 共享了 react 组件,所以把 render 的逻辑放 bootstrap 就可以。

vincenteof avatar Nov 05 '22 09:11 vincenteof