Skip to content

Commit c2bebd5

Browse files
authored
feat(sandbox): add disableLinkTransformToStyle sandbox config (#668)
* feat(sandbox): add disableLinkTransformToStyle sandbox config * chore: fix unit test * chore: fix unit test * chore: fix unit test * chore: fix e2e test * chore: fix e2e test
1 parent 01cf465 commit c2bebd5

File tree

16 files changed

+85
-55
lines changed

16 files changed

+85
-55
lines changed

Diff for: cypress/e2e/1-the-whole-process/visit-sub-app.spec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('whole process app render', () => {
1616
},
1717
sandbox: {
1818
snapshot: false,
19-
}
19+
},
2020
},
2121
});
2222

@@ -148,8 +148,8 @@ describe('whole process app render', () => {
148148
cy.wait(4000);
149149
cy.contains('[data-test=title]', HomeTitle)
150150
.then(() => {
151-
cy.get('[data-test=vite-count-btn]').dblclick();
152-
cy.contains('button', 'count is: 2');
151+
cy.get('[data-test=vite-count-btn]').click({ force: true });
152+
cy.contains('button', 'count is: 1');
153153
})
154154
.then(() => {
155155
win.Garfish.router.push({ path: '/vue2/home' });

Diff for: dev/app-main/src/constant.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const localApps: AppInfo = [
1717
activeWhen: '/react17',
1818
sandbox: {
1919
fixStaticResourceBaseUrl: false,
20+
disableLinkTransformToStyle: false,
2021
},
2122
// 子应用的入口地址,可以为 HTML 地址和 JS 地址
2223
// 注意:entry 地址不可以与主应用+子应用激活地址相同,否则刷新时将会直接返回子应用内容

Diff for: dev/app-react-17/public/a.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.hello {
2+
color: red;
3+
}

Diff for: dev/app-react-17/public/b.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.world {
2+
color: blue;
3+
}

Diff for: dev/app-react-17/public/index.html

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
<head>
44
<meta charset="UTF-8">
55
<title>app react v17</title>
6+
<link rel="stylesheet" href="http://localhost:8091/a.css" />
7+
<script>
8+
let link = document.createElement('link');
9+
link.rel = 'stylesheet';
10+
link.setAttribute('rel','stylesheet');
11+
link.setAttribute('href','http://localhost:8091/b.css');
12+
document.head.appendChild(link);
13+
</script>
614
</head>
715
<body>
816
<img data-test="img-pre-fix-app-17" src="/img" />

Diff for: packages/browser-vm/__tests__/dynamic-link.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ describe('Sandbox: dynamic link', () => {
4242
[linkOrder3]: {
4343
'Content-Type': styleType,
4444
timeConsuming: 300,
45-
}
45+
},
4646
},
4747
});
4848

@@ -90,7 +90,7 @@ describe('Sandbox: dynamic link', () => {
9090
go(`
9191
const dynamicLink = document.createElement('link');
9292
dynamicLink.href = "${withSuffix}";
93-
dynamicLink.rel = 'stylesheet';
93+
dynamicLink.setAttribute('rel', 'stylesheet');
9494
dynamicLink.onload = function () {
9595
expect(document.body).toMatchSnapshot();
9696
jestDone();
@@ -106,7 +106,7 @@ describe('Sandbox: dynamic link', () => {
106106
go(`
107107
const dynamicLink = document.createElement('link');
108108
dynamicLink.href = "${withoutSuffix}";
109-
dynamicLink.rel = 'stylesheet';
109+
dynamicLink.setAttribute('rel', 'stylesheet');
110110
dynamicLink.onload = function () {
111111
expect(document.body).toMatchSnapshot();
112112
jestDone();
@@ -122,7 +122,7 @@ describe('Sandbox: dynamic link', () => {
122122
go(`
123123
const dynamicLink = document.createElement('link');
124124
dynamicLink.href = "${withoutSuffixAndContentType}";
125-
dynamicLink.rel = 'stylesheet';
125+
dynamicLink.setAttribute('rel', 'stylesheet');
126126
dynamicLink.onload = function () {
127127
expect(document.body).toMatchSnapshot();
128128
jestDone();

Diff for: packages/browser-vm/src/dynamicNode/processor.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,12 @@ export class DynamicNodeProcessor {
368368
this.monitorChangesOfStyle();
369369
}
370370
// The link node of the request css needs to be changed to style node
371-
else if (this.is('link')) {
371+
else if (
372+
this.is('link') &&
373+
this.sandbox.options.disableLinkTransformToStyle !== true
374+
) {
372375
parentNode = this.findParentNodeInApp(context, 'head');
373-
if (this.el.rel === 'stylesheet' && this.el.href) {
376+
if (this.el.getAttribute('rel') === 'stylesheet' && this.el.href) {
374377
convertedNode = this.addDynamicLinkNode((styleNode) => {
375378
this.nativeAppend.call(parentNode, styleNode);
376379
});

Diff for: packages/browser-vm/src/pluginify.ts

+3
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ function createOptions(Garfish: interfaces.Garfish) {
134134
fixOwnerDocument: Boolean(appInfo.sandbox?.fixOwnerDocument),
135135
disableWith: Boolean(appInfo.sandbox?.disableWith),
136136
disableElementtiming: Boolean(appInfo.sandbox?.disableElementtiming),
137+
disableLinkTransformToStyle: Boolean(
138+
appInfo.sandbox?.disableLinkTransformToStyle,
139+
),
137140
strictIsolation: Boolean(appInfo.sandbox?.strictIsolation),
138141
excludeAssetFilter: appInfo.sandbox?.excludeAssetFilter,
139142
// 缓存模式,不收集副作用

Diff for: packages/browser-vm/src/sandbox.ts

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export class Sandbox {
9797
fixStaticResourceBaseUrl: true,
9898
disableWith: false,
9999
strictIsolation: false,
100+
disableLinkTransformToStyle: false,
100101
disableCollect: false,
101102
el: () => null,
102103
styleScopeId: () => '',

Diff for: packages/browser-vm/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface SandboxOptions {
2727
disableWith?: boolean;
2828
strictIsolation?: boolean;
2929
disableElementtiming?: boolean;
30+
disableLinkTransformToStyle?: boolean;
3031
disableCollect?: boolean;
3132
modules?: Array<Module>;
3233
excludeAssetFilter?: (url: string) => boolean;

Diff for: packages/core/src/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ export const createDefaultOptions = () => {
125125
disableWith: false,
126126
strictIsolation: false,
127127
disableElementtiming: false,
128+
disableLinkTransformToStyle: false,
128129
fixOwnerDocument: false,
129130
},
130131
// global hooks

Diff for: packages/core/src/interface.ts

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export namespace interfaces {
8181
disableWith?: boolean;
8282
strictIsolation?: boolean;
8383
disableElementtiming?: boolean;
84+
disableLinkTransformToStyle?: boolean;
8485
fixOwnerDocument?: boolean;
8586
excludeAssetFilter?: (url: string) => boolean;
8687
}

Diff for: packages/core/src/module/app.ts

+8
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,14 @@ export class App {
765765
},
766766

767767
link: (node) => {
768+
if (
769+
this.appInfo.sandbox &&
770+
typeof this.appInfo.sandbox === 'object' &&
771+
this.appInfo.sandbox.disableLinkTransformToStyle
772+
) {
773+
return DOMApis.createElement(node);
774+
}
775+
768776
if (DOMApis.isCssLinkNode(node)) {
769777
const styleManager = this.resources.link.find((manager) =>
770778
manager.isSameOrigin(node),

Diff for: packages/core/src/module/resource.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { interfaces } from '../interface';
1010

1111
// Fetch `script`, `link` and `module meta` elements
1212
function fetchStaticResources(
13-
appName: string,
13+
appInfo: AppInfo,
1414
loader: Loader,
1515
entryManager: TemplateManager,
1616
sandboxConfig: false | interfaces.SandboxConfig | undefined,
@@ -50,7 +50,7 @@ function fetchStaticResources(
5050
// we have a preload mechanism, so we don’t need to deal with it.
5151
return loader
5252
.load<JavaScriptManager>({
53-
scope: appName,
53+
scope: appInfo.name,
5454
url: fetchUrl,
5555
crossOrigin,
5656
defaultContentType: type,
@@ -63,7 +63,7 @@ function fetchStaticResources(
6363
jsManager.setDefferAttribute(toBoolean(defer));
6464
return jsManager;
6565
} else {
66-
warn(`[${appName}] Failed to load script: ${fetchUrl}`);
66+
warn(`[${appInfo.name}] Failed to load script: ${fetchUrl}`);
6767
}
6868
})
6969
.catch(() => null);
@@ -86,20 +86,26 @@ function fetchStaticResources(
8686
.findAllLinkNodes()
8787
.map((node) => {
8888
if (!entryManager.DOMApis.isCssLinkNode(node)) return;
89+
if (
90+
appInfo.sandbox &&
91+
typeof appInfo.sandbox === 'object' &&
92+
appInfo.sandbox.disableLinkTransformToStyle
93+
)
94+
return;
8995
const href = entryManager.findAttributeValue(node, 'href');
9096
if (href) {
9197
const fetchUrl = entryManager.url
9298
? transformUrl(entryManager.url, href)
9399
: href;
94100
return loader
95-
.load<StyleManager>({ scope: appName, url: fetchUrl })
101+
.load<StyleManager>({ scope: appInfo.name, url: fetchUrl })
96102
.then(({ resourceManager: styleManager }) => {
97103
if (styleManager) {
98104
styleManager.setDep(node);
99105
styleManager?.correctPath();
100106
return styleManager;
101107
} else {
102-
warn(`${appName} Failed to load link: ${fetchUrl}`);
108+
warn(`${appInfo.name} Failed to load link: ${fetchUrl}`);
103109
}
104110
})
105111
.catch(() => null);
@@ -155,7 +161,7 @@ export async function processAppResources(loader: Loader, appInfo: AppInfo) {
155161
if (entryManager instanceof loader.TemplateManager) {
156162
isHtmlMode = true;
157163
const [js, link, modules] = await fetchStaticResources(
158-
appInfo.name,
164+
appInfo,
159165
loader,
160166
entryManager,
161167
appInfo.sandbox,

0 commit comments

Comments
 (0)