Skip to content

Commit

Permalink
📝 add faq about how to make global event listener works well (#2734)
Browse files Browse the repository at this point in the history
  • Loading branch information
bravepg committed Oct 20, 2023
1 parent 3e133bd commit 46e4921
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 36 deletions.
88 changes: 63 additions & 25 deletions docs/faq/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,35 @@ To solve the exception, try the following steps:

6. If the development environment is OK but the production environment is not, check whether the `index.html` and `entry js` of the micro app are returned normally, for example, `404.html` is returned.

7. If you're using webpack5 and not using module federation, please see [here](https://github.com/umijs/qiankun/issues/1092#issuecomment-1109673224)
7. If you're using webpack5 and not using module federation, please see [here](https://github.com/umijs/qiankun/issues/1092#issuecomment-1109673224)

8. If you are using webpack5 and using module federation, you need to expose the life cycle function in the index file, and then expose the life cycle function externally in the bootstrap file.
```js
const promise = import("index");
export const bootstrap = () => promise.then(m => m.bootstrap());
export const mount = () => promise.then(m => m.mount());
export const unmount = () => promise.then(m => m.unmount());
```

```js
const promise = import('index');
export const bootstrap = () => promise.then((m) => m.bootstrap());
export const mount = () => promise.then((m) => m.mount());
export const unmount = () => promise.then((m) => m.unmount());
```

9. Check whether the main app and micro-app use AMD or CommonJS. Check method: run the main app and the micro-app independently, and enter the following code in the console: `(typeof exports === 'object' && typeof module === 'object') || (typeof define === 'function' && define.amd) || typeof exports === 'object'`,If it returns `true`,that it is caused by this reason, and there are mainly the following two solutions:

- Solution 1: Modify the `libraryTarget` of the micro-app `webpack` to `'window'`.
- Solution 1: Modify the `libraryTarget` of the micro-app `webpack` to `'window'`.

```diff
const packageName = require('./package.json').name;
module.exports = {
output: {
library: `${packageName}-[name]`,
- libraryTarget: 'umd',
+ libraryTarget: 'window',
jsonpFunction: `webpackJsonp_${packageName}`,
},
};
```

- Solution 2: The micro-app is not bundle with `umd`, directly mount the life cycle function to the `window` in the entry file, refer to[Micro app built without webpack](/guide/tutorial#micro-app-built-without-webpack).

```diff
const packageName = require('./package.json').name;
module.exports = {
output: {
library: `${packageName}-[name]`,
- libraryTarget: 'umd',
+ libraryTarget: 'window',
jsonpFunction: `webpackJsonp_${packageName}`,
},
};
```
- Solution 2: The micro-app is not bundle with `umd`, directly mount the life cycle function to the `window` in the entry file, refer to[Micro app built without webpack](/guide/tutorial#micro-app-built-without-webpack).

10. If it still not works after the steps above, this is usually due to browser compatibility issues. Try to **set the webpack `output.library` of the broken sub app the same with your main app registration for your app**, such as:

Such as here is the main configuration:
Expand Down Expand Up @@ -150,14 +151,17 @@ How to determine the completion of the container DOM loading? The vue app can be
If it still reports an error, check whether the container DOM is placed on a routing page of the main app, please refer to [How to load micro apps on a routing page of the main app](#How to load micro apps on a routing page of the main app)

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

![](https://user-images.githubusercontent.com/22413530/109919189-41563d00-7cf3-11eb-8328-711228389d63.png)

The first line is just a helper info printed by qiankun via `console.error` to help users identify which js file threw the error faster. It is not an exception thrown by qiankun itself.

**The actual exception info is in the second line.**

For example in the error above, it means the child app itself threw an exception when executing http://localhost:9100/index.bundle.js. **And the actual exception message is `Uncaught TypeError: Cannot read property 'call' of undefined` in the second line.**

Exceptions from the child app itself can be debugged and fixed with the following steps:

1. Based on the specific exception message, check if the js file that errors has syntax errors, like missing semicolons, depending on uninitialized variables etc.
2. Whether it depends on global variables provided by the main app, but the main app did not initialize them.
3. Compatibility issues. The child app js itself has syntax compatibility issues in the current runtime environment.
Expand Down Expand Up @@ -261,6 +265,8 @@ To solve the error, choose one of the options listed below:

## Why dynamic imported assets missing?

The reason is that webpack does not use the correct `publicPath` when loading the resource.

Two way to solve that:

### 1. With webpack live public path config
Expand Down Expand Up @@ -508,6 +514,8 @@ Yes it is.

Since qiankun get assets which imported by sub app via fetch, these static resources must be required to support [cors](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).

If it is your own script, you can support it by developing server-side cross-domain. If it is a 3-legged script and cannot add cross-domain headers to it, you can drag the script to the local and have your own server serve support cross-domain.

See [Enable Nginx Cors](https://enable-cors.org/server_nginx.html).

## How to solve that micro apps loaded failed due to abnormal scripts inserted dynamically by carriers
Expand Down Expand Up @@ -682,6 +690,10 @@ import 'core-js/web/url';

**We recommend that you use @babel/preset-env plugin directly to polyfill IE automatically, all the instructions for @babel/preset-env you can found in [babel official document](https://babeljs.io/docs/en/babel-preset-env).**

<Alert type="info">
You can also check out<a href="https://www.yuque.com/kuitos/gky7yw/qskte2" target="_blank">this article</a>to learn more about IE compatibility.
</Alert>

## Error `Here is no "fetch" on the window env, you need to polyfill it`

Qiankun use `window.fetch` to get resources of the micro applications, but [some browsers does not support it](https://caniuse.com/#search=fetch), you should get the [polyfill](https://github.com/github/fetch) in the entry.
Expand Down Expand Up @@ -725,9 +737,9 @@ router.beforeEach((to, from, next) => {

It is not feasible to use the router instance of micro-application directly to jump between micro-applications or micro-applications to main application page, such as the `Link` component in react-router or router-link in vue, because the router instance jump of micro-applications is based on the 'base' of routes. There are such ways to jump:

1. ` history. PushState () ` : [MDN usage introduction] (https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState)
2. Direct use of native a full address label, such as: ` < a href = "http://localhost:8080/app1" > app1 < / a > `
3. Modify the location href jump, such as: ` window. The location. The href = 'http://localhost:8080/app1' `
1. `history. PushState ()` : [MDN usage introduction] (https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState)
2. Direct use of native a full address label, such as: `< a href = "http://localhost:8080/app1" > app1 < / a >`
3. Modify the location href jump, such as: `window. The location. The href = 'http://localhost:8080/app1'`

## After the microapp file is updated, the old version of the file is still accessed

Expand Down Expand Up @@ -832,3 +844,29 @@ As the requests to pull micro-app entry are all cross-domain, when your micro-ap
},
});
```

- If you are through [umi plugin](https://umijs.org/zh-CN/plugins/plugin-qiankun) to use qiankun,then you only need to enable the credentials configuration for the corresponding microapp:

```diff
export default {
qiankun: {
master: {
apps: [
{
name: 'app',
entry: '//app.alipay.com/entry.html',
+ credentials: true,
}
]
}
}
}
```

## How to solve the problem that adding event handlers to window objects by subapplication does not take effect

Since the window object accessed by the sub-application is the object after being proxed by qiankun, it is invalid to add an event handler directly to the window object, and you can solve the problem by adding an event listener to the window by addEventListener:

```js
window.addEventListener('eventName', eventHandler);
```
33 changes: 22 additions & 11 deletions docs/faq/README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ qiankun 抛出这个错误是因为无法从微应用的 entry js 中识别出
6. 如果开发环境可以,生产环境不行,检查微应用的 `index.html` 和 `entry js` 是否正常返回,比如说返回了 `404.html`。

7. 如果你正在使用 webpack5,但没用使用模块联邦,请看[这个 issues](https://github.com/umijs/qiankun/issues/1092#issuecomment-1109673224)。

8. 如果你正在使用 webpack5,并且使用了使用模块联邦。需要在 index 文件中暴露生命周期函数,然后在 bootstrap 文件向外暴露生命周期函数。
```js
const promise = import("index");
export const bootstrap = () => promise.then(m => m.bootstrap());
export const mount = () => promise.then(m => m.mount());
export const unmount = () => promise.then(m => m.unmount());
```

```js
const promise = import('index');
export const bootstrap = () => promise.then((m) => m.bootstrap());
export const mount = () => promise.then((m) => m.mount());
export const unmount = () => promise.then((m) => m.unmount());
```

9. 检查主应用和微应用是否使用了 AMD 或 CommonJS 模块化。检查方法:单独运行微应用和主应用,在控制台输入如下代码:`(typeof exports === 'object' && typeof module === 'object') || (typeof define === 'function' && define.amd) || typeof exports === 'object'`,如果返回 `true`,则说明是这种情况,主要有以下两个解决办法:

- 解决办法1:修改微应用 `webpack` 的 `libraryTarget` 为 `'window'` 。
- 解决办法 1:修改微应用 `webpack``libraryTarget``'window'`

```diff
const packageName = require('./package.json').name;
Expand All @@ -56,10 +56,10 @@ qiankun 抛出这个错误是因为无法从微应用的 entry js 中识别出
},
};
```
- 解决办法2:微应用不打包成 umd ,直接在入口文件把生命周期函数挂载到 window 上,参考[非 webpack 构建的微应用](/zh/guide/tutorial#非-webpack-构建的微应用)。

- 解决办法 2:微应用不打包成 umd ,直接在入口文件把生命周期函数挂载到 window 上,参考[非 webpack 构建的微应用](/zh/guide/tutorial#非-webpack-构建的微应用)。

10. 如果在上述步骤完成后仍有问题,通常说明是浏览器兼容性问题导致的。可以尝试 **将有问题的微应用的 webpack `output.library` 配置成跟主应用中注册的 `name` 字段一致**,如:
10. 如果在上述步骤完成后仍有问题,通常说明是浏览器兼容性问题导致的。可以尝试 **将有问题的微应用的 webpack `output.library` 配置成跟主应用中注册的 `name` 字段一致**,如:

假如主应用配置是这样的:

Expand Down Expand Up @@ -151,6 +151,7 @@ qiankun 抛出这个错误是因为微应用加载后容器 DOM 节点不存在
如果仍然报错,检查容器 DOM 是否放在了主应用的某个路由页面,请参考[如何在主应用的某个路由页面加载微应用](#如何在主应用的某个路由页面加载微应用)。

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

![](https://user-images.githubusercontent.com/22413530/109919189-41563d00-7cf3-11eb-8328-711228389d63.png)

其中第一行只是 qiankun 通过 `console.error` 打印出来的一个辅助信息,目的是帮助用户更快的知道是哪个 js 报错了,并不是 qiankun 本身发生了异常。
Expand All @@ -160,6 +161,7 @@ qiankun 抛出这个错误是因为微应用加载后容器 DOM 节点不存在
比如上图这样一个报错,指的是子应用在执行 `http://localhost:9100/index.bundle.js` 时,这个 js 本身抛异常了。**而具体的异常信息就是第二行的 `Uncaught TypeError: Cannot read property 'call' of undefined`**

子应用本身的异常,可以尝试通过以下步骤排查解决:

1. 根据具体的异常信息,检查报错的 js 是否有语法错误,比如少了分号、依赖了未初始化的变量等。
2. 是否依赖了主应用提供的全局变量,但实际主应用并未初始化。
3. 兼容性问题。子应用这个 js 本身在当前运行环境存在语法兼容性问题。
Expand Down Expand Up @@ -638,6 +640,7 @@ export const mount = async () => render();
```js {2,3,7}
registerMicroApps([
// 自定义 activeRule
{ name: 'reactApp', entry: '//localhost:7100', container, activeRule: () => isReactApp() },
{ name: 'react15App', entry: '//localhost:7102', container, activeRule: () => isReactApp() },
{ name: 'vueApp', entry: '//localhost:7101', container, activeRule: () => isVueApp() },
Expand Down Expand Up @@ -859,3 +862,11 @@ export async function mount(props) {
}
}
```
## 如何解决子应用给 window 对象添加事件处理函数不生效的问题
由于子应用访问的 window 对象是被 qiankun 代理后的对象,因此直接给 window 对象添加事件处理函数是无效的,可以通过 addEventListener 给 window 添加事件监听器来解决该问题:
```js
window.addEventListener('eventName', eventHandler);
```

1 comment on commit 46e4921

@vercel
Copy link

@vercel vercel bot commented on 46e4921 Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.