Skip to content

Commit

Permalink
feat: add lifecycle check log at development environment (umijs#2604)
Browse files Browse the repository at this point in the history
  • Loading branch information
wanghangit committed Dec 12, 2023
1 parent fdb5f8a commit c65c0cf
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 13 deletions.
39 changes: 27 additions & 12 deletions packages/qiankun/src/core/loadApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import type { LoaderOpts } from '@qiankunjs/loader';
import { loadEntry } from '@qiankunjs/loader';
import type { Sandbox } from '@qiankunjs/sandbox';
import { createSandboxContainer } from '@qiankunjs/sandbox';
import { moduleResolver as defaultModuleResolver, transpileAssets, wrapFetchWithCache } from '@qiankunjs/shared';
import {
moduleResolver as defaultModuleResolver,
getValueType,
transpileAssets,
warn,
wrapFetchWithCache,
} from '@qiankunjs/shared';
import { concat, isFunction, mergeWith } from 'lodash';
import type { ParcelConfigObject } from 'single-spa';
import getAddOns from '../addons';
Expand Down Expand Up @@ -207,29 +213,38 @@ function getLifecyclesFromExports(
globalContext: WindowProxy,
globalLatestSetProp?: PropertyKey,
): MicroAppLifeCycles {
const validateExportLifecycle = (exports: ObjectType | undefined): boolean => {
const { bootstrap, mount, unmount } = exports ?? {};
return isFunction(bootstrap) && isFunction(mount) && isFunction(unmount);
const validateExportLifecycle = (exports: ObjectType | undefined, nextSourceName: string = ''): boolean => {
const validateLifecycleKeys = ['bootstrap', 'mount', 'unmount'];
const illegalKeys = validateLifecycleKeys.filter((key) => !isFunction(exports?.[key]));
const isIllegal = illegalKeys.length > 0;
if (process.env.NODE_ENV === 'development') {
if (isIllegal) {
const warnMsg = illegalKeys
.map((key) => `[${key} lifecycle] need Function but found ${getValueType(exports?.[key])}`)
.join('\n');
warn(
`search lifecycle error\n${warnMsg}\nplease check the exported lifecycle in ${appName}${
nextSourceName ? `,fallback to get from ${nextSourceName}` : ''
}`,
exports,
);
}
}
return !isIllegal;
};

if (validateExportLifecycle(scriptExports)) {
if (validateExportLifecycle(scriptExports, globalLatestSetProp ? 'latestSetProp' : `window['${appName}']`)) {
return scriptExports;
}

// fallback to sandbox latest set property if it had
if (globalLatestSetProp) {
const lifecycles = (globalContext as unknown as ObjectType)[globalLatestSetProp as never] as MicroAppLifeCycles;
if (validateExportLifecycle(lifecycles)) {
if (validateExportLifecycle(lifecycles, `window['${appName}']`)) {
return lifecycles;
}
}

if (process.env.NODE_ENV === 'development') {
console.warn(
`[qiankun] lifecycle not found from ${appName} entry exports, fallback to get from window['${appName}']`,
);
}

// fallback to globalContext variable who named with ${appName} while module exports not found
const globalVariableExports = (globalContext as unknown as ObjectType)[appName as never] as MicroAppLifeCycles;

Expand Down
2 changes: 1 addition & 1 deletion packages/qiankun/src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const version = '3.0.0-rc.11';
export const version = '3.0.0-rc.15';
21 changes: 21 additions & 0 deletions packages/shared/src/__tests__/util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect, it } from 'vitest';
import { getValueType } from '../utils';

it('should return value type', () => {
expect(getValueType(1)).toBe('Number');
expect(getValueType('1')).toBe('String');
expect(getValueType(true)).toBe('Boolean');
expect(getValueType(null)).toBe('Null');
expect(getValueType(undefined)).toBe('Undefined');
expect(getValueType({})).toBe('Object');
expect(getValueType([])).toBe('Array');
expect(getValueType(function () {})).toBe('Function');
expect(getValueType(Symbol())).toBe('Symbol');
expect(getValueType(new Date())).toBe('Date');
expect(getValueType(new RegExp(''))).toBe('RegExp');
expect(getValueType(new Error())).toBe('Error');
expect(getValueType(new Map())).toBe('Map');
expect(getValueType(new Set())).toBe('Set');
expect(getValueType(new WeakMap())).toBe('WeakMap');
expect(getValueType(new WeakSet())).toBe('WeakSet');
});
1 change: 1 addition & 0 deletions packages/shared/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// eslint-disable-next-line @typescript-eslint/unbound-method
export const { create, defineProperty, getOwnPropertyDescriptor, getOwnPropertyNames, freeze, keys } = Object;
export const hasOwnProperty = (caller: unknown, p: PropertyKey) => Object.prototype.hasOwnProperty.call(caller, p);
export const getValueType = (value: unknown) => Object.prototype.toString.call(value).slice(8, -1);

export class Deferred<T> {
promise: Promise<T>;
Expand Down

0 comments on commit c65c0cf

Please sign in to comment.