Skip to content

Commit

Permalink
Release 2.4.0 (#306)
Browse files Browse the repository at this point in the history
* fix: 🐛 error component render error (#313)

* fix: 🐛 unexpectable sandbox's cleaning up when load module (#311)

* feat: script attributes (#282)

* test: 💍 fix slient pass (#315)

* feat: 🎸 support symbol key for index (#316)
  • Loading branch information
maoxiaoke authored Jun 16, 2021
1 parent 692b7f8 commit 718199b
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 99 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = deepmerge(tslint, {
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/interface-name-prefix': 1,
'no-unused-expressions': 'off',
},
settings: {
react: {
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

See [https://github.com/ice-lab/icestark/releases](https://github.com/ice-lab/icestark/releases) for what has changed in each version of icestark.

## 2.4.0

- [feat] support appending extra attributes for scripts when using `loadScriptMode = script`. ([#276](https://github.com/ice-lab/icestark/issues/276))
- [fix] unexpectable sandbox's cleaning up when load modules. ([#293](https://github.com/ice-lab/icestark/issues/293))
- [fix] missing `ErrorComponent` causes React rendering's error. ([#312](https://github.com/ice-lab/icestark/issues/312))

## 2.3.2

- [refact] compatible with sandbox spell error.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/stark",
"version": "2.3.2",
"version": "2.4.0",
"description": "Icestark is a JavaScript library for multiple projects, Ice workbench solution.",
"scripts": {
"install:deps": "rm -rf node_modules && rm -rf ./packages/*/node_modules && yarn install && lerna exec -- npm install",
Expand Down
5 changes: 5 additions & 0 deletions packages/icestark-data/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## 0.1.3

- [feat] support `Symbol` key for index. ([#298](https://github.com/ice-lab/icestark/issues/298))
2 changes: 1 addition & 1 deletion packages/icestark-data/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/stark-data",
"version": "0.1.2",
"version": "0.1.3",
"description": "icestark-data is a JavaScript library for icestark, used for communication.",
"scripts": {
"build": "rm -rf lib && tsc",
Expand Down
32 changes: 17 additions & 15 deletions packages/icestark-data/src/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { setCache, getCache } from './cache';

const eventNameSpace = 'event';

type StringSymbolUnion = string | symbol;

interface Hooks {
emit(key: string, value: any): void;
on(key: string, callback: (value: any) => void): void;
off(key: string, callback?: (value: any) => void): void;
has(key: string): boolean;
emit(key: StringSymbolUnion, value: any): void;
on(key: StringSymbolUnion, callback: (value: any) => void): void;
off(key: StringSymbolUnion, callback?: (value: any) => void): void;
has(key: StringSymbolUnion): boolean;
}

class Event implements Hooks {
Expand All @@ -19,11 +21,11 @@ class Event implements Hooks {
this.eventEmitter = {};
}

emit(key: string, ...args) {
emit(key: StringSymbolUnion, ...args) {
const keyEmitter = this.eventEmitter[key];

if (!isArray(keyEmitter) || (isArray(keyEmitter) && keyEmitter.length === 0)) {
warn(`event.emit: no callback is called for ${key}`);
warn(`event.emit: no callback is called for ${String(key)}`);
return;
}

Expand All @@ -32,12 +34,11 @@ class Event implements Hooks {
});
}

on(key: string, callback: (value: any) => void) {
if (typeof key !== 'string') {
warn('event.on: key should be string');
on(key: StringSymbolUnion, callback: (value: any) => void) {
if (typeof key !== 'string' && typeof key !== 'symbol') {
warn('event.on: key should be string / symbol');
return;
}

if (callback === undefined || typeof callback !== 'function') {
warn('event.on: callback is required, should be function');
return;
Expand All @@ -50,14 +51,15 @@ class Event implements Hooks {
this.eventEmitter[key].push(callback);
}

off(key: string, callback?: (value: any) => void) {
if (typeof key !== 'string') {
warn('event.off: key should be string');
off(key: StringSymbolUnion, callback?: (value: any) => void) {
if (typeof key !== 'string' && typeof key !== 'symbol') {
warn('event.off: key should be string / symbol');
return;

}

if (!isArray(this.eventEmitter[key])) {
warn(`event.off: ${key} has no callback`);
warn(`event.off: ${String(key)} has no callback`);
return;
}

Expand All @@ -69,7 +71,7 @@ class Event implements Hooks {
this.eventEmitter[key] = this.eventEmitter[key].filter(cb => cb !== callback);
}

has(key: string) {
has(key: StringSymbolUnion) {
const keyEmitter = this.eventEmitter[key];
return isArray(keyEmitter) && keyEmitter.length > 0;
}
Expand Down
59 changes: 32 additions & 27 deletions packages/icestark-data/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import { setCache, getCache } from './cache';

const storeNameSpace = 'store';

type StringSymbolUnion = string | symbol;

// eslint-disable-next-line @typescript-eslint/interface-name-prefix
interface IO {
set(key: any, value?: any): void;
get(key?: string): void;
set(key: string | symbol | object, value?: any): void;
get(key?: StringSymbolUnion): void;
}

interface Hooks {
on(key: string, callback: (value: any) => void, force?: boolean): void;
off(key: string, callback?: (value: any) => void): void;
has(key: string): boolean;
on(key: StringSymbolUnion, callback: (value: any) => void, force?: boolean): void;
off(key: StringSymbolUnion, callback?: (value: any) => void): void;
has(key: StringSymbolUnion): boolean;
}

class Store implements IO, Hooks {
Expand All @@ -27,16 +30,16 @@ class Store implements IO, Hooks {
this.storeEmitter = {};
}

_getValue(key: string) {
_getValue(key: StringSymbolUnion) {
return this.store[key];
}

_setValue(key: string, value: any) {
_setValue(key: StringSymbolUnion, value: any) {
this.store[key] = value;
this._emit(key);
}

_emit(key) {
_emit(key: StringSymbolUnion) {
const keyEmitter = this.storeEmitter[key];

if (!isArray(keyEmitter) || (isArray(keyEmitter) && keyEmitter.length === 0)) {
Expand All @@ -49,39 +52,41 @@ class Store implements IO, Hooks {
});
}

get(key?: string) {
get(key?: StringSymbolUnion) {
if (key === undefined) {
return this.store;
}

if (typeof key !== 'string') {
warn(`store.get: key should be string`);
if (typeof key !== 'string' && typeof key !== 'symbol') {
warn(`store.get: key should be string / symbol`);
return null;
}

return this._getValue(key);
}

set(key: any, value?: any) {
if (typeof key !== 'string') {
if (!isObject(key)) {
warn('store.set: key should be string / object');
return;
}
set<T>(key: string | symbol | object, value?: T) {
if (typeof key !== 'string'
&& typeof key !== 'symbol'
&& !isObject(key)) {
warn('store.set: key should be string / symbol / object');
return;
}

if (isObject(key)) {
Object.keys(key).forEach(k => {
const v = key[k];

this._setValue(k, v);
});
} else {
this._setValue(key as StringSymbolUnion, value);
}

this._setValue(key, value);
}

on(key: string, callback: (value: any) => void, force?: boolean) {
if (typeof key !== 'string') {
warn('store.on: key should be string');
on(key: StringSymbolUnion, callback: (value: any) => void, force?: boolean) {
if (typeof key !== 'string' && typeof key !== 'symbol') {
warn('store.on: key should be string / symbol');
return;
}

Expand All @@ -101,14 +106,14 @@ class Store implements IO, Hooks {
}
}

off(key: string, callback?: (value: any) => void) {
if (typeof key !== 'string') {
warn('store.off: key should be string');
off(key: StringSymbolUnion, callback?: (value: any) => void) {
if (typeof key !== 'string' && typeof key !== 'symbol') {
warn('store.off: key should be string / symbol');
return;
}

if (!isArray(this.storeEmitter[key])) {
warn(`store.off: ${key} has no callback`);
warn(`store.off: ${String(key)} has no callback`);
return;
}

Expand All @@ -120,7 +125,7 @@ class Store implements IO, Hooks {
this.storeEmitter[key] = this.storeEmitter[key].filter(cb => cb !== callback);
}

has(key: string) {
has(key: StringSymbolUnion) {
const keyEmitter = this.storeEmitter[key];
return isArray(keyEmitter) && keyEmitter.length > 0;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/icestark-data/tests/event.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('event', () => {
};

event.on([]);
expect(warnMockFn).toBeCalledWith('event.on: key should be string');
expect(warnMockFn).toBeCalledWith('event.on: key should be string / symbol');

event.on('testOn');
expect(warnMockFn).toBeCalledWith('event.on: callback is required, should be function');
Expand All @@ -33,7 +33,7 @@ describe('event', () => {
};

event.off([]);
expect(warnMockFn).toBeCalledWith('event.off: key should be string');
expect(warnMockFn).toBeCalledWith('event.off: key should be string / symbol');

event.off('testOff');
expect(warnMockFn).toBeCalledWith('event.off: testOff has no callback');
Expand Down
8 changes: 4 additions & 4 deletions packages/icestark-data/tests/store.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('store', () => {
expect(store.get()).toStrictEqual({});

store.get([]);
expect(warnMockFn).toBeCalledWith('store.get: key should be string');
expect(warnMockFn).toBeCalledWith('store.get: key should be string / symbol');

expect(store.get('test')).toBeUndefined();
});
Expand All @@ -27,7 +27,7 @@ describe('store', () => {
};

store.set([]);
expect(warnMockFn).toBeCalledWith('store.set: key should be string / object');
expect(warnMockFn).toBeCalledWith('store.set: key should be string / symbol / object');

const testArray = [];
const testObj = {};
Expand All @@ -50,7 +50,7 @@ describe('store', () => {
};

store.on([]);
expect(warnMockFn).toBeCalledWith('store.on: key should be string');
expect(warnMockFn).toBeCalledWith('store.on: key should be string / symbol');

store.on('testOn');
expect(warnMockFn).toBeCalledWith('store.on: callback is required, should be function');
Expand All @@ -75,7 +75,7 @@ describe('store', () => {
};

store.off([]);
expect(warnMockFn).toBeCalledWith('store.off: key should be string');
expect(warnMockFn).toBeCalledWith('store.off: key should be string / symbol');

store.off('testOff');
expect(warnMockFn).toBeCalledWith('store.off: testOff has no callback');
Expand Down
4 changes: 2 additions & 2 deletions src/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ export default class AppRouter extends React.Component<AppRouterProps, AppRouter

private unmounted: boolean = false;

private err: string = ''; // js assets load err
private err: string | Error = ''; // js assets load err

private appKey: string = '';

static defaultProps = {
onRouteChange: () => {},
// eslint-disable-next-line react/jsx-filename-extension
ErrorComponent: ({ err }) => <div>{ err || 'Error' }</div>,
ErrorComponent: ({ err }: { err: string | Error}) => <div>{ typeof err === 'string' ? err : err?.message }</div>,
LoadingComponent: <div>Loading...</div>,
NotFoundComponent: <div>NotFound</div>,
shouldAssetsRemove: () => true,
Expand Down
27 changes: 21 additions & 6 deletions src/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import Sandbox, { SandboxConstructor, SandboxProps } from '@ice/sandbox';
import * as isEmpty from 'lodash.isempty';
import { NOT_LOADED, NOT_MOUNTED, LOADING_ASSETS, UNMOUNTED, LOAD_ERROR, MOUNTED } from './util/constant';
import { matchActivePath, MatchOptions, PathData, PathOptions } from './util/matchPath';
import { createSandbox, getUrlAssets, getEntryAssets, appendAssets, loadAndAppendCssAssets, emptyAssets, Assets } from './util/handleAssets';
import {
createSandbox,
getUrlAssets,
getEntryAssets,
loadAndAppendCssAssets,
loadAndAppendJsAssets,
emptyAssets,
Assets,
} from './util/handleAssets';
import { setCache } from './util/cache';
import { loadBundle } from './util/loader';
import { globalConfiguration, StartConfiguration } from './start';
import { getLifecyleByLibrary, getLifecyleByRegister } from './util/getLifecycle';

export type ScriptAttributes = string[] | ((url: string) => string[]);

interface ActiveFn {
(url: string): boolean;
}
Expand Down Expand Up @@ -44,6 +54,10 @@ export interface BaseConfig extends PathOptions {
props?: object;
cached?: boolean;
title?: string;
/**
* custom script attributes,only effective when scripts load by `<scrpit />`
*/
scriptAttributes?: ScriptAttributes;
}

interface LifeCycleFn {
Expand Down Expand Up @@ -146,8 +160,8 @@ export async function loadAppModule(appConfig: AppConfig) {

let lifecycle: ModuleLifeCycle = {};
onLoadingApp(appConfig);
const appSandbox = createSandbox(appConfig.sandbox);
const { url, container, entry, entryContent, name } = appConfig;
const appSandbox = createSandbox(appConfig.sandbox) as Sandbox;
const { url, container, entry, entryContent, name, scriptAttributes = [] } = appConfig;
const appAssets = url ? getUrlAssets(url) : await getEntryAssets({
root: container,
entry,
Expand All @@ -167,7 +181,10 @@ export async function loadAppModule(appConfig: AppConfig) {
await loadAndAppendCssAssets(appAssets);
lifecycle = await loadBundle(appAssets.jsList, appSandbox);
} else {
await appendAssets(appAssets, appSandbox, fetch);
await Promise.all([
loadAndAppendCssAssets(appAssets),
loadAndAppendJsAssets(appAssets, { sandbox: appSandbox, fetch, scriptAttributes }),
]);

lifecycle =
getLifecyleByLibrary() ||
Expand All @@ -180,8 +197,6 @@ export async function loadAppModule(appConfig: AppConfig) {

onFinishLoading(appConfig);

// clear appSandbox
appSandbox?.clear();
return combineLifecyle(lifecycle, appConfig);
}

Expand Down
Loading

0 comments on commit 718199b

Please sign in to comment.