From a74f236af978e2e9a4db58881d49fae5f78a56b6 Mon Sep 17 00:00:00 2001 From: yiludege Date: Sun, 7 Aug 2022 08:47:30 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B0=86=E5=AD=90=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=B8=AD=E7=9B=B8=E5=AF=B9=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E8=BD=AC=E6=8D=A2=E6=88=90=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/main-react/src/index.css | 2 +- examples/main-vue/src/App.vue | 2 +- examples/react16/src/Font.js | 16 +++- examples/react16/src/styles.css | 1 + .../__test__/integration/font.test.ts | 4 +- packages/wujie-core/src/effect.ts | 41 +++++----- packages/wujie-core/src/entry.ts | 13 ++- packages/wujie-core/src/iframe.ts | 8 +- packages/wujie-core/src/index.ts | 4 +- packages/wujie-core/src/plugin.ts | 81 +++++++++++++++++++ packages/wujie-core/src/sandbox.ts | 19 ++--- packages/wujie-core/src/shadow.ts | 40 +++------ packages/wujie-core/src/template.ts | 2 +- packages/wujie-core/src/utils.ts | 12 ++- packages/wujie-doc/docs/api/startApp.md | 4 +- packages/wujie-doc/docs/guide/plugin.md | 6 +- packages/wujie-doc/docs/question/README.md | 6 +- 17 files changed, 171 insertions(+), 90 deletions(-) create mode 100644 packages/wujie-core/src/plugin.ts diff --git a/examples/main-react/src/index.css b/examples/main-react/src/index.css index 8c3ac7e3..0bfb68d0 100644 --- a/examples/main-react/src/index.css +++ b/examples/main-react/src/index.css @@ -73,7 +73,7 @@ h3 { .content { flex: 1; height: 100vh; - overflow: scroll; + overflow: hidden scroll; width: 1px; } diff --git a/examples/main-vue/src/App.vue b/examples/main-vue/src/App.vue index d91e2b44..e30e4808 100644 --- a/examples/main-vue/src/App.vue +++ b/examples/main-vue/src/App.vue @@ -117,7 +117,7 @@ h3 { .content { flex: 1; height: 100vh; - overflow: scroll; + overflow: hidden scroll; width: 1px; } diff --git a/examples/react16/src/Font.js b/examples/react16/src/Font.js index ef6009fe..b739a64c 100644 --- a/examples/react16/src/Font.js +++ b/examples/react16/src/Font.js @@ -3,7 +3,7 @@ import { IconFont } from "tdesign-icons-react"; export default class Font extends React.Component { componentDidMount() { - console.log("react16 font mounted") + console.log("react16 font mounted"); } render() { return ( @@ -24,9 +24,17 @@ export default class Font extends React.Component {

IconFont 图标示例

TDesign icon

- - - +

+ + + +

+

相对地址

+

框架会将子应用的 css 文件中的相对地址换成绝对地址

+

比如 TDesign icon 的 css 文件地址为:

+

https://tdesign.gtimg.com/icon/0.1.1/fonts/index.css

+

index.css 文件中 @font-face 中 url('./t.woff') 最终转换为:

+

https://tdesign.gtimg.com/icon/0.1.1/fonts/t.woff

); diff --git a/examples/react16/src/styles.css b/examples/react16/src/styles.css index 8ec0ff46..a77f6a71 100644 --- a/examples/react16/src/styles.css +++ b/examples/react16/src/styles.css @@ -45,6 +45,7 @@ nav .active { text-align: left; max-width: 740px; margin: 0 auto; + overflow: hidden; } p, div.p { diff --git a/packages/wujie-core/__test__/integration/font.test.ts b/packages/wujie-core/__test__/integration/font.test.ts index ce8b3a70..68a86285 100644 --- a/packages/wujie-core/__test__/integration/font.test.ts +++ b/packages/wujie-core/__test__/integration/font.test.ts @@ -23,7 +23,7 @@ describe("main react startApp", () => { // 等待字体加载 await page.waitForResponse((response) => response.url().includes("https://tdesign.gtimg.com/icon/0.1.1/fonts")); // 等待字体装载 - await new Promise((resolve) => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 1000)); // 检查字体是否生效 expect(await page.evaluate(() => document.fonts.check("12px t", "E07F"))).toBe(true); }); @@ -50,7 +50,7 @@ describe("main vue startApp", () => { // 等待字体加载 await page.waitForResponse((response) => response.url().includes("https://tdesign.gtimg.com/icon/0.1.1/fonts")); // 等待字体装载 - await new Promise((resolve) => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 1000)); // 检查字体是否生效 expect(await page.evaluate(() => document.fonts.check("12px t", "E07F"))).toBe(true); }); diff --git a/packages/wujie-core/src/effect.ts b/packages/wujie-core/src/effect.ts index 13ad1a97..95cccfcc 100644 --- a/packages/wujie-core/src/effect.ts +++ b/packages/wujie-core/src/effect.ts @@ -10,7 +10,6 @@ import { isFunction, isHijackingTag, requestIdleCallback, - compose, error, warn, nextTick, @@ -21,6 +20,7 @@ import { import { insertScriptToIframe } from "./iframe"; import Wujie from "./sandbox"; import { getPatchStyleElements } from "./shadow"; +import { getCssLoader } from "./plugin"; import { WUJIE_DATA_ID, WUJIE_DATA_FLAG, WUJIE_TIPS_REPEAT_RENDER } from "./constant"; import { ScriptObject } from "./template"; @@ -56,13 +56,9 @@ function manualInvokeElementEvent(element: HTMLLinkElement | HTMLScriptElement, /** * 样式元素的css变量处理 */ -function handleStylesheetElementPatch(stylesheetElement: HTMLStyleElement, sandbox: Wujie, baseUrl?: string) { +function handleStylesheetElementPatch(stylesheetElement: HTMLStyleElement, sandbox: Wujie) { if (!stylesheetElement.innerHTML || sandbox.degrade) return; - const curUrl = getCurUrl(sandbox.proxyLocation as Location); - const [hostStyleSheetElement, fontStyleSheetElement] = getPatchStyleElements( - [stylesheetElement.sheet], - baseUrl ? baseUrl : curUrl - ); + const [hostStyleSheetElement, fontStyleSheetElement] = getPatchStyleElements([stylesheetElement.sheet]); if (hostStyleSheetElement) { sandbox.shadowRoot.head.appendChild(hostStyleSheetElement); } @@ -76,8 +72,9 @@ function handleStylesheetElementPatch(stylesheetElement: HTMLStyleElement, sandb */ function patchStylesheetElement( stylesheetElement: HTMLStyleElement, - cssLoader: (code: string) => string, - sandbox: Wujie + cssLoader: (code: string, url: string, base: string) => string, + sandbox: Wujie, + curUrl: string ) { const innerHTMLDesc = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML"); const innerTextDesc = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerText"); @@ -88,7 +85,7 @@ function patchStylesheetElement( return innerHTMLDesc.get.call(stylesheetElement); }, set: function (code: string) { - innerHTMLDesc.set.call(stylesheetElement, cssLoader(code)); + innerHTMLDesc.set.call(stylesheetElement, cssLoader(code, "", curUrl)); nextTick(() => handleStylesheetElementPatch(this, sandbox)); }, }, @@ -97,7 +94,7 @@ function patchStylesheetElement( return innerTextDesc.get.call(stylesheetElement); }, set: function (code: string) { - innerTextDesc.set.call(stylesheetElement, cssLoader(code)); + innerTextDesc.set.call(stylesheetElement, cssLoader(code, "", curUrl)); nextTick(() => handleStylesheetElementPatch(this, sandbox)); }, }, @@ -106,7 +103,7 @@ function patchStylesheetElement( return textContentDesc.get.call(stylesheetElement); }, set: function (code: string) { - textContentDesc.set.call(stylesheetElement, cssLoader(code)); + textContentDesc.set.call(stylesheetElement, cssLoader(code, "", curUrl)); nextTick(() => handleStylesheetElementPatch(this, sandbox)); }, }, @@ -116,7 +113,7 @@ function patchStylesheetElement( if (node.nodeType === Node.TEXT_NODE) { return rawAppendChild.call( stylesheetElement, - stylesheetElement.ownerDocument.createTextNode(cssLoader(node.textContent)) + stylesheetElement.ownerDocument.createTextNode(cssLoader(node.textContent, "", curUrl)) ); } else return rawAppendChild(node); }, @@ -141,8 +138,9 @@ function rewriteAppendOrInsertChild(opts: { return rawDOMAppendOrInsertBefore.call(this, element, refChild) as T; } - const { styleSheetElements, replace, fetch, plugins, iframe, lifecycles } = sandbox; + const { styleSheetElements, replace, fetch, plugins, iframe, lifecycles, proxyLocation } = sandbox; const iframeDocument = iframe.contentDocument; + const curUrl = getCurUrl(proxyLocation); // TODO 过滤可以开放 if (element.tagName) { @@ -164,14 +162,12 @@ function rewriteAppendOrInsertChild(opts: { // 记录js插入样式,子应用重新激活时恢复 const stylesheetElement = iframeDocument.createElement("style"); // 处理css-loader插件 - stylesheetElement.innerHTML = compose(plugins.map((plugin) => plugin.cssLoader))( - replace ? replace(content) : content, - src - ); + const cssLoader = getCssLoader({ plugins, replace }); + stylesheetElement.innerHTML = cssLoader(content, src, curUrl); styleSheetElements.push(stylesheetElement); rawDOMAppendOrInsertBefore.call(this, stylesheetElement, refChild); // 处理样式补丁 - handleStylesheetElementPatch(stylesheetElement, sandbox, href); + handleStylesheetElementPatch(stylesheetElement, sandbox); manualInvokeElementEvent(element, "load"); element = null; }, @@ -190,10 +186,9 @@ function rewriteAppendOrInsertChild(opts: { const stylesheetElement: HTMLLinkElement | HTMLStyleElement = newChild as any; styleSheetElements.push(stylesheetElement); const content = stylesheetElement.innerHTML; - const cssLoader = (content) => - compose(plugins.map((plugin) => plugin.cssLoader))(replace ? replace(content) : content); - content && (stylesheetElement.innerHTML = cssLoader(content)); - patchStylesheetElement(stylesheetElement, cssLoader, sandbox); + const cssLoader = getCssLoader({ plugins, replace }); + content && (stylesheetElement.innerHTML = cssLoader(content, "", curUrl)); + patchStylesheetElement(stylesheetElement, cssLoader, sandbox, curUrl); const res = rawDOMAppendOrInsertBefore.call(this, element, refChild); // 处理样式补丁 handleStylesheetElementPatch(stylesheetElement, sandbox); diff --git a/packages/wujie-core/src/entry.ts b/packages/wujie-core/src/entry.ts index 31bb58c4..dc966129 100644 --- a/packages/wujie-core/src/entry.ts +++ b/packages/wujie-core/src/entry.ts @@ -5,7 +5,15 @@ import processTpl, { ScriptBaseObject, StyleObject, } from "./template"; -import { defaultGetPublicPath, getInlineCode, requestIdleCallback, error, compose, getExcludes } from "./utils"; +import { + defaultGetPublicPath, + getInlineCode, + requestIdleCallback, + error, + compose, + getExcludes, + getCurUrl, +} from "./utils"; import { WUJIE_TIPS_NO_FETCH, WUJIE_TIPS_SCRIPT_ERROR_REQUESTED, WUJIE_TIPS_CSS_ERROR_REQUESTED } from "./constant"; import Wujie from "./sandbox"; import { plugin, loadErrorHandler } from "./index"; @@ -51,11 +59,12 @@ export async function processCssLoader( template: string, getExternalStyleSheets: () => StyleResultList ): Promise { + const curUrl = getCurUrl(sandbox.proxyLocation); /** css-loader */ const composeCssLoader = compose(sandbox.plugins.map((plugin) => plugin.cssLoader)); const processedCssList: StyleResultList = getExternalStyleSheets().map(({ src, contentPromise }) => ({ src, - contentPromise: contentPromise.then((content) => composeCssLoader(content, src)), + contentPromise: contentPromise.then((content) => composeCssLoader(content, src, curUrl)), })); const embedHTML = await getEmbedHTML(template, processedCssList); return sandbox.replace ? sandbox.replace(embedHTML) : embedHTML; diff --git a/packages/wujie-core/src/iframe.ts b/packages/wujie-core/src/iframe.ts index 0f589f19..d75342c4 100644 --- a/packages/wujie-core/src/iframe.ts +++ b/packages/wujie-core/src/iframe.ts @@ -9,8 +9,8 @@ import { isMatchSyncQueryById, warn, error, - compose, execHooks, + getCurUrl, } from "./utils"; import { documentProxyProperties, @@ -23,6 +23,7 @@ import { windowProxyProperties, windowRegWhiteList, } from "./common"; +import { getJsLoader } from "./plugin"; import { WUJIE_TIPS_EMPTY_CALLBACK, WUJIE_TIPS_SCRIPT_ERROR_REQUESTED, WUJIE_DATA_FLAG } from "./constant"; import { ScriptObjectLoader } from "./index"; @@ -611,8 +612,9 @@ export function insertScriptToIframe(scriptResult: ScriptObject | ScriptObjectLo const { src, module, content, crossorigin, crossoriginType, callback } = scriptResult as ScriptObjectLoader; const scriptElement = iframeWindow.document.createElement("script"); const nextScriptElement = iframeWindow.document.createElement("script"); - const { replace, plugins } = iframeWindow.__WUJIE; - let code = compose(plugins.map((plugin) => plugin.jsLoader))(replace ? replace(content) : content, src); + const { replace, plugins, proxyLocation } = iframeWindow.__WUJIE; + const jsLoader = getJsLoader({ plugins, replace }); + let code = jsLoader(content, src, getCurUrl(proxyLocation)); // 内联脚本 if (content) { diff --git a/packages/wujie-core/src/index.ts b/packages/wujie-core/src/index.ts index 35c9e3a3..2c3fe869 100644 --- a/packages/wujie-core/src/index.ts +++ b/packages/wujie-core/src/index.ts @@ -32,7 +32,7 @@ export interface plugin { /** 处理js加载前的loader */ jsBeforeLoaders?: Array; /** 处理js的loader */ - jsLoader?: (code: string, url: string) => string; + jsLoader?: (code: string, url: string, base: string) => string; /** 处理js加载后的loader */ jsAfterLoaders?: Array; /** css排除列表 */ @@ -40,7 +40,7 @@ export interface plugin { /** 处理css加载前的loader */ cssBeforeLoaders?: Array; /** 处理css的loader */ - cssLoader?: (code: string, url: string) => string; + cssLoader?: (code: string, url: string, base: string) => string; /** 处理css加载后的loader */ cssAfterLoaders?: Array; /** 子应用 window addEventListener 钩子回调 */ diff --git a/packages/wujie-core/src/plugin.ts b/packages/wujie-core/src/plugin.ts new file mode 100644 index 00000000..b7a8b92f --- /dev/null +++ b/packages/wujie-core/src/plugin.ts @@ -0,0 +1,81 @@ +import { plugin } from "./index"; +import { compose, getAbsolutePath } from "./utils"; + +interface loaderOption { + plugins: Array; + replace: (code: string) => string; +} + +/** + * 获取柯里化 cssLoader + */ +export function getCssLoader({ plugins, replace }: loaderOption) { + return (code: string, src: string = "", base: string): string => + compose(plugins.map((plugin) => plugin.cssLoader))(replace ? replace(code) : code, src, base); +} + +/** + * 获取柯里化 jsLoader + */ +export function getJsLoader({ plugins, replace }: loaderOption) { + return (code: string, src: string = "", base: string): string => + compose(plugins.map((plugin) => plugin.jsLoader))(replace ? replace(code) : code, src, base); +} + +/** + * 获取有效的 cssBeforeLoaders + */ +export function getCssBeforeLoaders(plugins: Array) { + return plugins + .map((plugin) => plugin.cssBeforeLoaders) + .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) + .filter((cssLoader) => typeof cssLoader === "object") + .reverse(); +} + +/** + * 获取有效的 cssAfterLoaders + */ +export function getCssAfterLoaders(plugins: Array) { + return plugins + .map((plugin) => plugin.cssAfterLoaders) + .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) + .filter((afterLoader) => typeof afterLoader === "object"); +} + +/** + * 获取有效的 jsBeforeLoaders + */ +export function getJsBeforeLoaders(plugins: Array) { + return plugins + .map((plugin) => plugin.jsBeforeLoaders) + .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) + .filter((preLoader) => typeof preLoader === "object"); +} + +/** + * 获取有效的 jsAfterLoaders + */ +export function getJsAfterLoaders(plugins: Array) { + return plugins + .map((plugin) => plugin.jsAfterLoaders) + .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) + .filter((afterLoader) => typeof afterLoader === "object"); +} + +/** + * 转换子应用css内的相对地址成绝对地址 + */ +function cssRelativePathResolve(code: string, src: string, base: string) { + const baseUrl = src ? getAbsolutePath(src, base) : base; + const urlReg = /(url\()([^)]*)(\))/g; + return code.replace(urlReg, (_m, pre, url, post) => { + const urlString = url.replace(/["']/g, ""); + const absoluteUrl = getAbsolutePath(urlString, baseUrl); + return pre + "'" + absoluteUrl + "'" + post; + }); +} + +export default { + cssLoader: cssRelativePathResolve, +}; diff --git a/packages/wujie-core/src/sandbox.ts b/packages/wujie-core/src/sandbox.ts index caaa78a0..0b761a3c 100644 --- a/packages/wujie-core/src/sandbox.ts +++ b/packages/wujie-core/src/sandbox.ts @@ -17,6 +17,7 @@ import { } from "./shadow"; import { proxyGenerator, localGenerator } from "./proxy"; import { ScriptResultList } from "./entry"; +import defaultPlugin, { getJsBeforeLoaders, getJsAfterLoaders } from "./plugin"; import { idToSandboxMap, addSandboxIdMap, @@ -25,7 +26,7 @@ import { rawDocumentQuerySelector, } from "./common"; import { EventBus, appEventObjMap, EventObj } from "./event"; -import { isFunction, wujieSupport, appRouteParse, requestIdleCallback, getCurUrl } from "./utils"; +import { isFunction, wujieSupport, appRouteParse, requestIdleCallback } from "./utils"; import { WUJIE_DATA_ATTACH_CSS_FLAG } from "./constant"; import { plugin, ScriptObjectLoader, loadErrorHandler } from "./index"; @@ -242,15 +243,9 @@ export default class Wujie { // 标志位,执行代码前设置 iframeWindow.__POWERED_BY_WUJIE__ = true; // 用户自定义代码前 - const beforeScriptResultList: ScriptObjectLoader[] = this.plugins - .map((plugin) => plugin.jsBeforeLoaders) - .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) - .filter((preLoader) => typeof preLoader === "object"); + const beforeScriptResultList: ScriptObjectLoader[] = getJsBeforeLoaders(this.plugins); // 用户自定义代码后 - const afterScriptResultList: ScriptObjectLoader[] = this.plugins - .map((plugin) => plugin.jsAfterLoaders) - .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) - .filter((afterLoader) => typeof afterLoader === "object"); + const afterScriptResultList: ScriptObjectLoader[] = getJsAfterLoaders(this.plugins); // 同步代码 const syncScriptResultList: ScriptResultList = []; // async代码无需保证顺序,所以不用放入执行队列 @@ -404,14 +399,12 @@ export default class Wujie { * 2、将@font-face定义到shadowRoot外部 */ public patchCssRules(): void { - const curUrl = getCurUrl(this.proxyLocation as Location); if (this.degrade) return; if (this.shadowRoot.host.hasAttribute(WUJIE_DATA_ATTACH_CSS_FLAG)) return; const [hostStyleSheetElement, fontStyleSheetElement] = getPatchStyleElements( Array.from(this.iframe.contentDocument.querySelectorAll("style")).map( (styleSheetElement) => styleSheetElement.sheet - ), - curUrl + ) ); if (hostStyleSheetElement) { this.shadowRoot.head.appendChild(hostStyleSheetElement); @@ -456,7 +449,7 @@ export default class Wujie { this.styleSheetElements = []; this.execQueue = []; this.lifecycles = lifecycles; - this.plugins = Array.isArray(plugins) ? plugins : []; + this.plugins = Array.isArray(plugins) ? [defaultPlugin, ...plugins] : [defaultPlugin]; // 创建目标地址的解析 const { urlElement, appHostPath, appRoutePath } = appRouteParse(url); diff --git a/packages/wujie-core/src/shadow.ts b/packages/wujie-core/src/shadow.ts index 68cfc5fd..ba81bd27 100644 --- a/packages/wujie-core/src/shadow.ts +++ b/packages/wujie-core/src/shadow.ts @@ -4,7 +4,8 @@ import { getExternalStyleSheets } from "./entry"; import Wujie from "./sandbox"; import { patchElementEffect } from "./iframe"; import { patchRenderEffect } from "./effect"; -import { getContainer, compose } from "./utils"; +import { getCssLoader, getCssBeforeLoaders, getCssAfterLoaders } from "./plugin"; +import { getContainer, getCurUrl } from "./utils"; const cssSelectorMap = { ":root": ":host", @@ -72,18 +73,12 @@ export function renderElementToContainer(element: Element, selectorOrElement: st */ async function processCssLoaderForTemplate(sandbox: Wujie, html: HTMLHtmlElement): Promise { const document = sandbox.iframe.contentDocument; - const { plugins, replace } = sandbox; - const cssLoader = (content, src) => - compose(plugins.map((plugin) => plugin.cssLoader))(replace ? replace(content) : content, src); - const cssBeforeLoaders = sandbox.plugins - .map((plugin) => plugin.cssBeforeLoaders) - .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) - .filter((cssLoader) => typeof cssLoader === "object") - .reverse(); - const cssAfterLoaders = sandbox.plugins - .map((plugin) => plugin.cssAfterLoaders) - .reduce((preLoaders, curLoaders) => preLoaders.concat(curLoaders), []) - .filter((afterLoader) => typeof afterLoader === "object"); + const { plugins, replace, proxyLocation } = sandbox; + const cssLoader = getCssLoader({ plugins, replace }); + const cssBeforeLoaders = getCssBeforeLoaders(plugins); + const cssAfterLoaders = getCssAfterLoaders(plugins); + const curUrl = getCurUrl(proxyLocation); + return await Promise.all([ Promise.all( getExternalStyleSheets(cssBeforeLoaders, sandbox.fetch, sandbox.lifecycles.loadError).map( @@ -94,7 +89,7 @@ async function processCssLoaderForTemplate(sandbox: Wujie, html: HTMLHtmlElement if (!content) return; const styleElement = document.createElement("style"); styleElement.setAttribute("type", "text/css"); - styleElement.appendChild(document.createTextNode(content ? cssLoader(content, src) : content)); + styleElement.appendChild(document.createTextNode(content ? cssLoader(content, src, curUrl) : content)); const head = html.querySelector("head"); head?.insertBefore(styleElement, html.querySelector("head")?.firstChild); }); @@ -108,7 +103,7 @@ async function processCssLoaderForTemplate(sandbox: Wujie, html: HTMLHtmlElement if (!content) return; const styleElement = document.createElement("style"); styleElement.setAttribute("type", "text/css"); - styleElement.appendChild(document.createTextNode(content ? cssLoader(content, src) : content)); + styleElement.appendChild(document.createTextNode(content ? cssLoader(content, src, curUrl) : content)); html.appendChild(styleElement); }); }), @@ -221,14 +216,10 @@ export function clearChild(root: ShadowRoot | Node): void { * 获取修复好的样式元素 * 主要是针对对root样式和font-face样式 */ -export function getPatchStyleElements( - rootStyleSheets: Array, - baseUrl: string -): Array { +export function getPatchStyleElements(rootStyleSheets: Array): Array { const rootCssRules = []; const fontCssRules = []; const rootStyleReg = /:root/g; - const fontStyleReg = /(url\()([^)]*)(\))/g; // 找出root的cssRules for (let i = 0; i < rootStyleSheets.length; i++) { @@ -241,14 +232,7 @@ export function getPatchStyleElements( } // 如果是font-face的cssRule if (cssRules[j].type === CSSRule.FONT_FACE_RULE) { - fontCssRules.push( - // 相对地址改绝对地址 - cssRuleText.replace(fontStyleReg, (_m, pre, url, post) => { - const urlString = url.replace(/["']/g, ""); - const absoluteUrl = new URL(urlString, baseUrl).href; - return pre + "'" + absoluteUrl + "'" + post; - }) - ); + fontCssRules.push(cssRuleText); } } } diff --git a/packages/wujie-core/src/template.ts b/packages/wujie-core/src/template.ts index e1374e7a..8ecb22be 100644 --- a/packages/wujie-core/src/template.ts +++ b/packages/wujie-core/src/template.ts @@ -245,7 +245,7 @@ export default function processTpl(tpl: String, baseURI: String, postProcessTemp if (!isPureCommentBlock && code) { scripts.push({ - src: null, + src: "", content: code, module: isModuleScript, crossorigin: !!isCrossOriginScript, diff --git a/packages/wujie-core/src/utils.ts b/packages/wujie-core/src/utils.ts index 05b5c13f..87a97908 100644 --- a/packages/wujie-core/src/utils.ts +++ b/packages/wujie-core/src/utils.ts @@ -170,10 +170,18 @@ export function fixElementCtrSrcOrHref( // TODO: innerHTML的处理 } -export function getCurUrl(proxyLocation: Location): string { - return proxyLocation.protocol + "//" + proxyLocation.host + proxyLocation.pathname; +export function getCurUrl(proxyLocation: Object): string { + const location = proxyLocation as Location; + return location.protocol + "//" + location.host + location.pathname; } +export function getAbsolutePath(url: string, base: string): string { + try { + return new URL(url, base).href; + } catch { + return url; + } +} /** * 获取需要同步的url */ diff --git a/packages/wujie-doc/docs/api/startApp.md b/packages/wujie-doc/docs/api/startApp.md index cd9ea09f..cf3bfa2c 100644 --- a/packages/wujie-doc/docs/api/startApp.md +++ b/packages/wujie-doc/docs/api/startApp.md @@ -224,13 +224,13 @@ interface plugin { /** 处理js加载前的loader */ jsBeforeLoaders: Array; /** 处理js的loader */ - jsLoader: (code: string, url: string) => string; + jsLoader: (code: string, url: string, base: string) => string; /** 处理js加载后的loader */ jsAfterLoaders: Array; /** 处理css加载前的loader */ cssBeforeLoaders: Array; /** 处理css的loader */ - cssLoader: (code: string, url: string) => string; + cssLoader: (code: string, url: string, base: string) => string; /** 处理css加载后的loader */ cssAfterLoaders: Array; /** 子应用 window addEventListener 钩子回调 */ diff --git a/packages/wujie-doc/docs/guide/plugin.md b/packages/wujie-doc/docs/guide/plugin.md index 5ad5861b..ce28b540 100644 --- a/packages/wujie-doc/docs/guide/plugin.md +++ b/packages/wujie-doc/docs/guide/plugin.md @@ -75,7 +75,8 @@ const plugins = [ const plugins = [ { // 将url为aaa.js的脚本中的aaa替换成bbb - jsLoader: (code, url) => { + // code 为脚本代码、url为脚本的地址(内联脚本为'')、base为子应用当前的地址 + jsLoader: (code, url, base) => { if (url === "aaa.js") return code.replace("aaa", "bbb"); }, }, @@ -163,7 +164,8 @@ const plugins = [ const plugins = [ { // 对css脚本动态的进行替换 - cssLoader: (code, url) => { + // code 为样式代码、url为样式的地址(内联样式为'')、base为子应用当前的地址 + cssLoader: (code, url, base) => { console.log("css-loader", url, code.slice(0, 50) + "..."); return code; }, diff --git a/packages/wujie-doc/docs/question/README.md b/packages/wujie-doc/docs/question/README.md index 37e7db18..44c0516b 100644 --- a/packages/wujie-doc/docs/question/README.md +++ b/packages/wujie-doc/docs/question/README.md @@ -38,7 +38,7 @@ ctx.set("Access-Control-Allow-Origin", ctx.headers.origin); **原因:** `@font-face`不会在`shadow`内部加载,[详见](https://github.com/mdn/interactive-examples/issues/887) -**解决方案:** 框架已解决,会将子应用的`@font-face`放到`shadow`外部执行,注意子应用的自定义字体名和主应用的自定义字体名不能重复,否则可能存在覆盖问题 +**已解决:** 框架会将子应用的`@font-face`放到`shadow`外部执行,注意子应用的自定义字体名和主应用的自定义字体名不能重复,否则可能存在覆盖问题 ## 4、冒泡系列组件(比如下拉框)弹出位置不正确 @@ -55,9 +55,7 @@ ctx.set("Access-Control-Allow-Origin", ctx.headers.origin); ## 6、css 样式内部的相对地址相对的是主应用的域名 -**原因:** 由于框架没有处理子应用样式内部的相对地址,而子应用样式是挂载在主应用容器中,导致相对地址错误 - -**解决方案:** 使用插件中的[css-loader](/guide/plugin.html#css-loader)在运行时将相对地址代码替换成绝对地址。 +**已解决:** 框架已处理,默认将相对地址转换成绝对地址 ## 7、子应用使用 module federation 引用远程模块报错