Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ttttttw opened this issue Jun 17, 2021 · 41 comments · Fixed by #2652
Closed

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

ttttttw opened this issue Jun 17, 2021 · 41 comments · Fixed by #2652

Comments

@ttttttw
Copy link

ttttttw commented Jun 17, 2021

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

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

image

@ttttttw ttttttw changed the title [Bug]请遵循下文模板提交问题,否则您的问题会被关闭 webpack5 使用模块联邦,抛出异常,生命周期未加载 Jun 17, 2021
@HULIANGA
Copy link

碰到一样的问题,mark

@ttttttw
Copy link
Author

ttttttw commented Aug 26, 2021

碰到一样的问题,mark

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

@HULIANGA
Copy link

碰到一样的问题,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
Copy link
Author

ttttttw commented Aug 26, 2021

碰到一样的问题,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
Copy link

碰到一样的问题,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生命周期会失败

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

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

@wudith
Copy link

wudith commented Aug 30, 2021

碰到一样的问题,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中引入的用途是什么呢

@ttttttw
Copy link
Author

ttttttw commented Aug 30, 2021

碰到一样的问题,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,所以用的一样的。

@HULIANGA
Copy link

碰到一样的问题,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的话更新一次要更新十几个微模块,想用联合模块来复用这些代码

@geweidong
Copy link

碰到一样的问题,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

@zhangchao828
Copy link

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

@HULIANGA
Copy link

碰到一样的问题,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
Copy link

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

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

@geweidong
Copy link

geweidong commented Sep 13, 2021

碰到一样的问题,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

@yuzhanglong
Copy link

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

@xyjxu
Copy link

xyjxu commented Dec 10, 2021

mark

@ttttttw
Copy link
Author

ttttttw commented Dec 10, 2021 via email

@rubickecho
Copy link

@wudith

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

@ttttttw
Copy link
Author

ttttttw commented Dec 30, 2021 via email

@hansonfang
Copy link

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

@ttttttw
Copy link
Author

ttttttw commented Mar 2, 2022 via email

@w123angmeng
Copy link

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

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

@ttttttw
Copy link
Author

ttttttw commented Aug 30, 2022 via email

@w123angmeng
Copy link

碰到一样的问题,mark

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

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

@w123angmeng
Copy link

碰到一样的问题,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 }
还是报错找不到子应用生命周期函数

@yuzhanglong
Copy link

碰到一样的问题,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 我就不知道了。

@SanMako
Copy link

SanMako commented Sep 30, 2022

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

@ttttttw
Copy link
Author

ttttttw commented Sep 30, 2022 via email

@w123angmeng
Copy link

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

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

@SanMako
Copy link

SanMako commented Sep 30, 2022

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

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

谢谢大佬

@vincenteof
Copy link

vincenteof commented Nov 5, 2022

子应用配置 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 就可以。

@ttttttw
Copy link
Author

ttttttw commented Nov 5, 2022 via email

@961998264
Copy link

子应用配置 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 就可以。

我按照这种逻辑来写。仍然带来问题。首先就是在mount函数中import.那么import会在主项目环境中执行的吧,import的资源直接就是404

@ttttttw
Copy link
Author

ttttttw commented Apr 3, 2023 via email

@vincenteof
Copy link

961998264

当然你子应用里得有 bootstrap 这个文件

@ttttttw
Copy link
Author

ttttttw commented May 17, 2023 via email

@gezhicui
Copy link

gezhicui commented Jul 4, 2023

有一个最终的解决方案吗 谁有qiankun+mf的最简demo能参考下

@ttttttw
Copy link
Author

ttttttw commented Jul 4, 2023 via email

@HelenSilas
Copy link

有一个最终的解决方案吗,麻烦发下demo 谢谢

@ttttttw
Copy link
Author

ttttttw commented Sep 4, 2023 via email

@Ahuzsp
Copy link

Ahuzsp commented Sep 27, 2024

qiankun+vue2项目,配置了模块联以后手动控制资源加载顺序可以解决
image

@ttttttw
Copy link
Author

ttttttw commented Sep 27, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.