@qiankunjs/shared 0.0.1-rc.3 → 0.0.1-rc.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cjs/assets-transpilers/index.d.ts +8 -0
  2. package/dist/cjs/assets-transpilers/index.js +14 -0
  3. package/dist/cjs/assets-transpilers/index.js.map +1 -1
  4. package/dist/cjs/assets-transpilers/script.d.ts +2 -2
  5. package/dist/cjs/assets-transpilers/script.js +110 -74
  6. package/dist/cjs/assets-transpilers/script.js.map +1 -1
  7. package/dist/cjs/assets-transpilers/types.d.ts +11 -2
  8. package/dist/cjs/assets-transpilers/types.js +1 -2
  9. package/dist/cjs/assets-transpilers/types.js.map +1 -1
  10. package/dist/cjs/assets-transpilers/utils.d.ts +1 -0
  11. package/dist/cjs/assets-transpilers/utils.js +6 -3
  12. package/dist/cjs/assets-transpilers/utils.js.map +1 -1
  13. package/dist/cjs/error/QiankunError.js +1 -2
  14. package/dist/cjs/error/QiankunError.js.map +1 -1
  15. package/dist/cjs/utils.d.ts +8 -0
  16. package/dist/cjs/utils.js +89 -28
  17. package/dist/cjs/utils.js.map +1 -1
  18. package/dist/esm/assets-transpilers/index.d.ts +8 -0
  19. package/dist/esm/assets-transpilers/index.js +8 -0
  20. package/dist/esm/assets-transpilers/index.js.map +1 -1
  21. package/dist/esm/assets-transpilers/script.d.ts +2 -2
  22. package/dist/esm/assets-transpilers/script.js +110 -73
  23. package/dist/esm/assets-transpilers/script.js.map +1 -1
  24. package/dist/esm/assets-transpilers/types.d.ts +11 -2
  25. package/dist/esm/assets-transpilers/types.js.map +1 -1
  26. package/dist/esm/assets-transpilers/utils.d.ts +1 -0
  27. package/dist/esm/assets-transpilers/utils.js +4 -0
  28. package/dist/esm/assets-transpilers/utils.js.map +1 -1
  29. package/dist/esm/utils.d.ts +8 -0
  30. package/dist/esm/utils.js +78 -12
  31. package/dist/esm/utils.js.map +1 -1
  32. package/package.json +5 -7
  33. package/src/assets-transpilers/index.ts +0 -40
  34. package/src/assets-transpilers/link.ts +0 -130
  35. package/src/assets-transpilers/script.ts +0 -175
  36. package/src/assets-transpilers/types.ts +0 -22
  37. package/src/assets-transpilers/utils.ts +0 -16
  38. package/src/common.ts +0 -3
  39. package/src/error/QiankunError.ts +0 -5
  40. package/src/error/index.ts +0 -1
  41. package/src/index.ts +0 -9
  42. package/src/module-resolver/__tests__/index.ts +0 -75
  43. package/src/module-resolver/index.ts +0 -92
  44. package/src/module-resolver/types.ts +0 -9
  45. package/src/typings.d.ts +0 -13
  46. package/src/utils.ts +0 -29
@@ -1,130 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-04-26
4
- */
5
- import type { MatchResult } from '../module-resolver';
6
- import { getEntireUrl } from '../utils';
7
- import { preTranspile as preTranspileScript } from './script';
8
- import type { AssetsTranspilerOpts, BaseTranspilerOpts } from './types';
9
- import { Mode } from './types';
10
- import { createReusingObjectUrl } from './utils';
11
-
12
- type PreTranspileResult =
13
- | { mode: Mode.REUSED_DEP_IN_SANDBOX; result: { src: string } & MatchResult }
14
- | { mode: Mode.NONE; result?: never };
15
- const preTranspileStyleSheetLink = (
16
- link: Partial<Pick<HTMLLinkElement, 'href' | 'rel'>>,
17
- baseURI: string,
18
- opts: BaseTranspilerOpts,
19
- ): PreTranspileResult => {
20
- const { sandbox, moduleResolver } = opts;
21
- const { href, rel } = link;
22
-
23
- if (sandbox) {
24
- // filter preload links
25
- if (href && rel === 'stylesheet') {
26
- const linkHref = getEntireUrl(href, baseURI);
27
-
28
- const matchedAssets = moduleResolver?.(linkHref);
29
- if (matchedAssets) {
30
- return {
31
- mode: Mode.REUSED_DEP_IN_SANDBOX,
32
- result: { src: linkHref, ...matchedAssets },
33
- };
34
- }
35
- }
36
- }
37
-
38
- return {
39
- mode: Mode.NONE,
40
- };
41
- };
42
-
43
- const postProcessPreloadLink = (link: HTMLLinkElement, baseURI: string, opts: AssetsTranspilerOpts): void => {
44
- const { as, href } = link;
45
- switch (as) {
46
- case 'script': {
47
- const { mode, result } = preTranspileScript({ src: href }, baseURI, opts);
48
-
49
- switch (mode) {
50
- /**
51
- * While the assets are transpiling in sandbox, it means they will be evaluated with manual fetching,
52
- * thus we need to set the attribute `as` to fetch instead of script or style to avoid preload cache missing.
53
- * see https://stackoverflow.com/questions/52635660/can-link-rel-preload-be-made-to-work-with-fetch/63814972#63814972
54
- */
55
- case Mode.REMOTE_ASSETS_IN_SANDBOX: {
56
- link.as = 'fetch';
57
- break;
58
- }
59
-
60
- case Mode.REUSED_DEP_IN_SANDBOX: {
61
- const { url } = result;
62
- link.href = createReusingObjectUrl(href, url, 'text/javascript');
63
-
64
- break;
65
- }
66
- }
67
-
68
- break;
69
- }
70
-
71
- case 'style': {
72
- const { mode, result } = preTranspileStyleSheetLink({ href, rel: 'stylesheet' }, baseURI, opts);
73
-
74
- switch (mode) {
75
- case Mode.REUSED_DEP_IN_SANDBOX: {
76
- const { url } = result;
77
- link.href = createReusingObjectUrl(href, url, 'text/css');
78
- break;
79
- }
80
- }
81
-
82
- break;
83
- }
84
-
85
- default:
86
- break;
87
- }
88
- };
89
-
90
- export default function transpileLink(
91
- link: HTMLLinkElement,
92
- baseURI: string,
93
- opts: AssetsTranspilerOpts,
94
- ): HTMLLinkElement {
95
- const hrefAttribute = link.getAttribute('href');
96
- const { mode, result } = preTranspileStyleSheetLink(
97
- {
98
- href: hrefAttribute || undefined,
99
- rel: link.rel,
100
- },
101
- baseURI,
102
- opts,
103
- );
104
-
105
- switch (mode) {
106
- case Mode.REUSED_DEP_IN_SANDBOX: {
107
- const { src, version, url } = result;
108
- link.dataset.href = src;
109
- link.dataset.version = version;
110
- link.href = createReusingObjectUrl(src, url, 'text/css');
111
-
112
- return link;
113
- }
114
-
115
- case Mode.NONE:
116
- default: {
117
- if (hrefAttribute) {
118
- link.href = getEntireUrl(hrefAttribute, baseURI);
119
-
120
- if (link.rel === 'preload') {
121
- postProcessPreloadLink(link, baseURI, opts);
122
- }
123
-
124
- return link;
125
- }
126
-
127
- return link;
128
- }
129
- }
130
- }
@@ -1,175 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-03-16
4
- */
5
-
6
- import type { MatchResult } from '../module-resolver';
7
- import { getEntireUrl } from '../utils';
8
- import type { AssetsTranspilerOpts } from './types';
9
- import { Mode } from './types';
10
- import { createReusingObjectUrl } from './utils';
11
-
12
- const isValidJavaScriptType = (type?: string): boolean => {
13
- const handleTypes = [
14
- 'text/javascript',
15
- 'module',
16
- 'application/javascript',
17
- 'text/ecmascript',
18
- 'application/ecmascript',
19
- ];
20
- return !type || handleTypes.indexOf(type) !== -1;
21
- };
22
-
23
- const getCredentials = (crossOrigin: string | null): RequestInit['credentials'] | undefined => {
24
- switch (crossOrigin) {
25
- case 'anonymous':
26
- return 'same-origin';
27
- case 'use-credentials':
28
- return 'include';
29
- default:
30
- return undefined;
31
- }
32
- };
33
-
34
- type PreTranspileResult =
35
- | { mode: Mode.REMOTE_ASSETS_IN_SANDBOX; result: { src: string } }
36
- | { mode: Mode.REUSED_DEP_IN_SANDBOX; result: { src: string } & MatchResult }
37
- | { mode: Mode.INLINE_CODE_IN_SANDBOX; result: { code: string } }
38
- | { mode: Mode.NONE; result?: never };
39
-
40
- export const preTranspile = (
41
- script: Partial<Pick<HTMLScriptElement, 'src' | 'type' | 'textContent'>>,
42
- baseURI: string,
43
- opts: AssetsTranspilerOpts,
44
- ): PreTranspileResult => {
45
- const { sandbox, moduleResolver } = opts;
46
-
47
- const { src, type } = script;
48
-
49
- if (sandbox) {
50
- if (src) {
51
- const entireUrl = getEntireUrl(src, baseURI);
52
- const matchedScript = moduleResolver?.(entireUrl);
53
- if (matchedScript) {
54
- return {
55
- mode: Mode.REUSED_DEP_IN_SANDBOX,
56
- result: { src: entireUrl, ...matchedScript },
57
- };
58
- }
59
-
60
- return {
61
- mode: Mode.REMOTE_ASSETS_IN_SANDBOX,
62
- result: { src: entireUrl },
63
- };
64
- }
65
-
66
- if (isValidJavaScriptType(type)) {
67
- const rawNode = opts.rawNode as HTMLScriptElement;
68
- const scriptNode = script.textContent ? script : rawNode.childNodes[0];
69
-
70
- const code = scriptNode.textContent;
71
- if (code) {
72
- return {
73
- mode: Mode.INLINE_CODE_IN_SANDBOX,
74
- result: {
75
- code,
76
- },
77
- };
78
- }
79
- }
80
- }
81
-
82
- return { mode: Mode.NONE };
83
- };
84
-
85
- export default function transpileScript(
86
- script: HTMLScriptElement,
87
- baseURI: string,
88
- opts: AssetsTranspilerOpts,
89
- ): HTMLScriptElement {
90
- // Can't use script.src directly, because it will be resolved to absolute path by browser with Node.baseURI
91
- // Such as <script src="./foo.js"></script> will be resolved to http://localhost:8000/foo.js while read script.src
92
- const srcAttribute = script.getAttribute('src');
93
- const { sandbox, fetch } = opts;
94
-
95
- const { mode, result } = preTranspile(
96
- {
97
- src: srcAttribute || undefined,
98
- type: script.type,
99
- textContent: script.textContent,
100
- },
101
- baseURI,
102
- opts,
103
- );
104
-
105
- switch (mode) {
106
- case Mode.REMOTE_ASSETS_IN_SANDBOX: {
107
- const { src } = result;
108
-
109
- // We must remove script src to avoid self execution as we need to fetch the script content and transpile it
110
- script.removeAttribute('src');
111
- script.dataset.src = src;
112
-
113
- const syncMode = !script.hasAttribute('async');
114
- const priority: Priority = syncMode ? 'high' : 'low';
115
- const credentials = getCredentials(script.crossOrigin);
116
-
117
- void fetch(src, { credentials, priority })
118
- .then((res) => res.text())
119
- .then((code) => {
120
- const codeFactory = sandbox!.makeEvaluateFactory(code, src);
121
-
122
- // HTMLScriptElement default fetchPriority is 'auto', we should set it to 'high' to make it execute earlier while it's not async script
123
- if (syncMode) {
124
- script.fetchPriority = 'high';
125
- }
126
-
127
- script.src = URL.createObjectURL(new Blob([codeFactory], { type: 'text/javascript' }));
128
- });
129
-
130
- return script;
131
- }
132
-
133
- case Mode.INLINE_CODE_IN_SANDBOX: {
134
- const rawNode = opts.rawNode as HTMLScriptElement;
135
- const scriptNode = script.textContent ? script : rawNode.childNodes[0];
136
- const { code } = result;
137
-
138
- scriptNode.textContent = sandbox!.makeEvaluateFactory(code, baseURI);
139
- // mark the script have consumed
140
- script.dataset.consumed = 'true';
141
-
142
- return script;
143
- }
144
-
145
- case Mode.REUSED_DEP_IN_SANDBOX: {
146
- const { url, version, src } = result;
147
-
148
- script.dataset.src = src;
149
- script.dataset.version = version;
150
-
151
- const syncMode = !script.getAttribute('async');
152
- // HTMLScriptElement default fetchPriority is 'auto', we should set it to 'high' to make it execute earlier while it's not async script
153
- if (syncMode) {
154
- script.fetchPriority = 'high';
155
- }
156
-
157
- // When the script hits the dependency reuse logic, the current script is not executed, and an empty script is returned directly
158
- script.src = createReusingObjectUrl(src, url, 'text/javascript');
159
-
160
- return script;
161
- }
162
-
163
- case Mode.NONE:
164
- default: {
165
- if (srcAttribute) {
166
- script.src = getEntireUrl(srcAttribute, baseURI);
167
- return script;
168
- }
169
-
170
- return script;
171
- }
172
- }
173
-
174
- // TODO find entry exports
175
- }
@@ -1,22 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-08-26
4
- */
5
- import type { Sandbox } from '@qiankunjs/sandbox';
6
- import type { BaseLoaderOpts } from '../common';
7
-
8
- import type { MatchResult } from '../module-resolver';
9
-
10
- export type BaseTranspilerOpts = BaseLoaderOpts & {
11
- moduleResolver?: (url: string) => MatchResult | undefined;
12
- sandbox?: Sandbox;
13
- };
14
-
15
- export type AssetsTranspilerOpts = BaseTranspilerOpts & { rawNode: Node };
16
-
17
- export enum Mode {
18
- REMOTE_ASSETS_IN_SANDBOX = 'RAIS',
19
- REUSED_DEP_IN_SANDBOX = 'RDIS',
20
- INLINE_CODE_IN_SANDBOX = 'ICIS',
21
- NONE = 'NONE',
22
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-10-09
4
- */
5
- import { memoize } from 'lodash';
6
-
7
- export const createReusingObjectUrl = memoize(
8
- (src: string, url: string, type: 'text/javascript' | 'text/css'): string => {
9
- return URL.createObjectURL(
10
- new Blob([`/* ${src} is reusing the execution result of ${url} */`], {
11
- type,
12
- }),
13
- );
14
- },
15
- (src, url, type) => `${src}#${url}#${type}`,
16
- );
package/src/common.ts DELETED
@@ -1,3 +0,0 @@
1
- export type BaseLoaderOpts = {
2
- fetch: typeof window.fetch;
3
- };
@@ -1,5 +0,0 @@
1
- export class QiankunError extends Error {
2
- constructor(message: string) {
3
- super(`[qiankun]: ${message}`);
4
- }
5
- }
@@ -1 +0,0 @@
1
- export { QiankunError } from './QiankunError';
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-05-06
4
- */
5
- export * from './assets-transpilers';
6
- export * from './utils';
7
- export * from './module-resolver';
8
- export * from './common';
9
- export * from './error';
@@ -1,75 +0,0 @@
1
- import { describe, it } from 'vitest';
2
-
3
- import { moduleResolver } from '../index';
4
-
5
- describe('default module resolver', () => {
6
- const mainAppContainer = document.createElement('div');
7
- mainAppContainer.innerHTML = `
8
- <script type="dependencymap">
9
- {
10
- "dependencies": {
11
- "moment": {
12
- "url": "https://unpkg.com/2.1.1/moment.js",
13
- "version": "2.1.1",
14
- "range": "^2.0.1"
15
- },
16
- "lodash": {
17
- "url": "https://unpkg.com/4.0.2/lodash.js",
18
- "version": "4.0.2",
19
- "range": "~4.0.1"
20
- },
21
- "antd": {
22
- "url": "https://unpkg.com/4.0.2/antd",
23
- "version": "4.0.2",
24
- "range": "~4.0.1"
25
- }
26
- }
27
- }
28
- </script>
29
- `;
30
-
31
- it('should works well', ({ expect }) => {
32
- const microAppContainer = document.createElement('div');
33
- microAppContainer.innerHTML = `
34
- <script type="dependencymap">
35
- {
36
- "dependencies": {
37
- "moment": {
38
- "url": "https://unpkg.com/2.0.1/moment.js",
39
- "version": "2.0.1",
40
- "range": "^2.0.1"
41
- },
42
- "lodash": {
43
- "url": "https://unpkg.com/4.0.1/lodash.js",
44
- "version": "4.0.1",
45
- "range": "~4.0.1"
46
- },
47
- "antd": {
48
- "url": "https://unpkg.com/4.0.1/antd",
49
- "version": "4.0.1",
50
- "range": "4.0.1"
51
- }
52
- }
53
- }
54
- </script>
55
- `;
56
-
57
- const result1 = moduleResolver('https://unpkg.com/4.0.1/antd', microAppContainer, mainAppContainer);
58
- expect(result1).toBeUndefined();
59
-
60
- const result2 = moduleResolver('https://unpkg.com/4.0.1/lodash.js', microAppContainer, mainAppContainer);
61
- expect(result2).toStrictEqual({
62
- version: '4.0.2',
63
- url: 'https://unpkg.com/4.0.2/lodash.js',
64
- });
65
-
66
- const result3 = moduleResolver('https://unpkg.com/2.0.1/moment.js', microAppContainer, mainAppContainer);
67
- expect(result3).toStrictEqual({
68
- version: '2.1.1',
69
- url: 'https://unpkg.com/2.1.1/moment.js',
70
- });
71
-
72
- const result4 = moduleResolver('https://unpkg.com/4.0.2/antd', microAppContainer, mainAppContainer);
73
- expect(result4).toBeUndefined();
74
- });
75
- });
@@ -1,92 +0,0 @@
1
- import satisfies from 'semver/functions/satisfies';
2
- import type { MatchResult } from './types';
3
-
4
- declare global {
5
- interface HTMLElement {
6
- __matched_deps__?: string[];
7
- }
8
- }
9
-
10
- type Dependency = {
11
- url: string;
12
- version: string;
13
- range: string;
14
- peerDeps?: string[];
15
- };
16
-
17
- type NormalizedDependency = {
18
- name: string;
19
- } & Dependency;
20
-
21
- type DependencyMap = {
22
- dependencies: Record<string, Dependency>;
23
- };
24
-
25
- export type { MatchResult } from './types';
26
-
27
- export function moduleResolver(
28
- url: string,
29
- microAppContainer: HTMLElement,
30
- mainAppContainer: HTMLElement,
31
- ): MatchResult | undefined {
32
- const dependencyMapSelector = 'script[type=dependencymap]';
33
-
34
- const microAppDependenciesString = microAppContainer.querySelector(dependencyMapSelector)?.innerHTML;
35
- if (microAppDependenciesString) {
36
- const { dependencies } = JSON.parse(microAppDependenciesString) as DependencyMap;
37
- const normalizedDependencies = normalizeDependencies(dependencies);
38
- const microAppDependency = normalizedDependencies.find((v) => v.url === url);
39
-
40
- if (microAppDependency) {
41
- const mainAppDependencyMapString = mainAppContainer.querySelector(dependencyMapSelector)?.innerHTML;
42
-
43
- if (mainAppDependencyMapString) {
44
- const mainAppDependencyMap = JSON.parse(mainAppDependencyMapString) as DependencyMap;
45
- const matchedDeps = (microAppContainer.__matched_deps__ ??= []);
46
- const matchedDep = findDependency(
47
- microAppDependency,
48
- normalizeDependencies(mainAppDependencyMap.dependencies),
49
- matchedDeps,
50
- );
51
-
52
- if (matchedDep) {
53
- matchedDeps.push(matchedDep.name);
54
- return matchedDep;
55
- }
56
- }
57
- }
58
- }
59
-
60
- return undefined;
61
- }
62
-
63
- function findDependency(
64
- dependency: NormalizedDependency,
65
- mainAppDependencies: NormalizedDependency[],
66
- matchedDependencies: string[],
67
- ): MatchResult | undefined {
68
- const matched = mainAppDependencies.find(
69
- (mainAppDependency) =>
70
- mainAppDependency.name === dependency.name &&
71
- satisfies(mainAppDependency.version, dependency.range) &&
72
- // peer dependencies must be cached before
73
- (dependency.peerDeps || []).every((peerDep) => matchedDependencies.indexOf(peerDep) !== -1),
74
- );
75
-
76
- if (matched) {
77
- return {
78
- name: matched.name,
79
- version: matched.version,
80
- url: matched.url,
81
- };
82
- }
83
-
84
- return undefined;
85
- }
86
-
87
- function normalizeDependencies(dependencies: DependencyMap['dependencies']): NormalizedDependency[] {
88
- return Object.keys(dependencies).map((name) => ({
89
- name,
90
- ...dependencies[name],
91
- }));
92
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-08-26
4
- */
5
- export type MatchResult = {
6
- name: string;
7
- version: string;
8
- url: string;
9
- };
package/src/typings.d.ts DELETED
@@ -1,13 +0,0 @@
1
- declare module 'semver/functions/satisfies' {
2
- export default function satisfies(version: string, range: string): boolean;
3
- }
4
-
5
- type Priority = 'high' | 'low' | 'auto';
6
-
7
- interface HTMLScriptElement {
8
- fetchPriority?: Priority;
9
- }
10
-
11
- interface RequestInit {
12
- priority?: Priority;
13
- }
package/src/utils.ts DELETED
@@ -1,29 +0,0 @@
1
- /**
2
- * @author Kuitos
3
- * @since 2023-04-26
4
- */
5
-
6
- // eslint-disable-next-line @typescript-eslint/unbound-method
7
- export const { create, defineProperty, getOwnPropertyDescriptor, getOwnPropertyNames, freeze, keys } = Object;
8
- export const hasOwnProperty = (caller: unknown, p: PropertyKey) => Object.prototype.hasOwnProperty.call(caller, p);
9
-
10
- export class Deferred<T> {
11
- promise: Promise<T>;
12
-
13
- resolve!: (value: T | PromiseLike<T>) => void;
14
-
15
- reject!: (reason?: unknown) => void;
16
-
17
- constructor() {
18
- this.promise = new Promise((resolve, reject) => {
19
- this.resolve = resolve;
20
- this.reject = reject;
21
- });
22
- }
23
- }
24
-
25
- export function getEntireUrl(uri: string, baseURI: string): string {
26
- const publicPath = new URL(baseURI, window.location.href);
27
- const entireUrl = new URL(uri, publicPath.toString());
28
- return entireUrl.toString();
29
- }