对 Docusaurus 进行上游操作,确保加载文件的顺序正确
Undertake operations upstream to Docusaurus and ensure the correct order of loading files
我要接手 a website by V2 Docusaurus。
我们网站的一个特殊性是我们需要加载office.js and css-vars-ponyfill.min.js,并在一开始就进行一些操作。所以之前的开发者决定使用下面的方法。
在每个.mdx.md
页面中,他用一个组件包裹内容MainWrapper
:
<MainWrapper>
... ...
Real content
... ...
</MainWrapper>
MainWrapper/index.js
定义如下
function MainWrapper(props) {
return (<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded MainWrapper')}).call(this)" >
</script>
</Head>
<CssvarsWrapper></CssvarsWrapper>
<OfficejsWrapper></OfficejsWrapper>
{props.children}
</>)
}
export default MainWrapper;
CssvarsWrapper/index.js
定义如下
function CssvarsWrapper(props) {
return (<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded in CssvarsWrapper')}).call(this)">
</script>
{console.log("CssvarsWrapper > index.js > CssvarsWrapper")}
<script defer
src="https://unpkg.com/css-vars-ponyfill@2/dist/css-vars-ponyfill.min.js"
onload="(function(){console.log('css-vars-ponyfill.min.js fully loaded in CssvarsWrapper'); onCssVarsPonyfillLoad()}).call(this) ">
</script>
</Head>
{props.children}
</>)
}
OfficejsWrapper/index.js
定义如下
function OfficeWrapper(props) {
return (
<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded in OfficeWrapper')}).call(this)">
</script>
{console.log("OfficejsWrapper > index.js > OfficeWrapper")}
<script defer
src='https://appsforoffice.microsoft.com/lib/1/hosted/office.js'
onload="(function(){console.log('office.js fully loaded in OfficeWrapper'); onOfficejsLoad()}).call(this) ">
</script>
</Head>
{props.children}
</>
)
}
lib/Patches.js
包含实际操作:
console.log("in patches")
... ...
function onCssVarsPonyfillLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()")
cssVars({
onlyLegacy: false,
onComplete: function (cssText, styleElms, cssVariables, benchmark) {
}
});
}
function onOfficejsLoad() {
Office.onReady(function () {
console.log("office.js is ready.");
patch();
})
}
但是,我的测试表明,无论 defer
标记如何,此实现都不能始终遵循正确的文件加载顺序。例如,如下图所示,css-vars-ponyfill.min.js fully loaded in CssvarsWrapper
和 office.js fully loaded in OfficeWrapper
在 patches.js fully loaded
之前,因此 onCssVarsPonyfillLoad
和 onOfficejsLoad
在被调用时还没有准备好。
实际上,我们应该确保patches.js
总是在css-vars-ponyfill.min.js
和office.js
之前加载。有谁知道如何确保这一点?
此外,这种方法(即围绕每个页面的内容包装一个组件以在上游执行一些操作)是否正确?
TLDR;
如果您希望脚本按顺序执行,您需要添加 defer
到您的 <script>
标签。
您可以在此处阅读更多相关信息:https://www.w3schools.com/tags/att_script_defer.asp
稍微长一点的版本
尽管如此,我想强调一些关于您的实施的事情
您正在虚拟 DOM 环境中工作,您的组件可能 mount/unmount 取决于许多用例。我绝不会推荐任何人像这样加载文件:
<script
src="/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded 1')}).call(this)">
</script>
相反,我建议在单个文件中定义方法并将其导出,这样我就可以在我的应用程序中使用我想使用的任何方法。这不仅会在每次挂载组件时终止文件加载,还会提高效率和执行。
这种方法更像是模块化方法。检查一下 and if you want to read more about modular approach, I found a good explanation here: https://javascript.info/import-export。
如果您无力分解模块,而是想使用当前使用的方法,则需要使用 defer
来确保脚本按照定义的相同顺序执行。
以前的开发人员决定实现此加载脚本的方式多次,特别是它加载 patches.js
不止一次。
我建议您尝试放弃此实现并在 docusaurus.config.js
中使用 Docusaurus scripts-array
来定义这些脚本,并在 office.js
和 css-vars-ponyfill.min.js
上使用 defer
并为那里的每个脚本定义 onload
脚本。这是在 Docusaurus 中加载外部( 和内部 patches.js
)脚本的正确方法。
设置里面的脚本docusaurus.config.js
:
module.exports = {
...
scripts: [
{
src: '/lib/patches.js'
},
{
src: 'https://appsforoffice.microsoft.com/lib/1/hosted/office.js',
defer: true,
onload: "(() => { console.log('office.js loaded'); onOfficejsLoad(); })()"
},
{
src: 'https://unpkg.com/css-vars-ponyfill@2/dist/css-vars-ponyfill.min.js',
defer: true,
onload: "(() => { console.log('css-vars-ponyfill.min.js loaded'); onCssVarsPonyfillLoad(); })()"
}
],
}
我们在这两个脚本上使用 defer
,这意味着脚本将在文档被解析后但在触发 DOMContentLoaded
.
之前执行和加载
在本地 Docusaurus 项目上尝试此操作,我在清除缓存后每次都按预期顺序加载脚本:
in patches
office.js loaded
patches.js > onCssVarsPonyfillLoad()
css-vars-ponyfill.min.js loaded
patches.js > onCssVarsPonyfillLoad()
cssVars:onComplete
office.js is ready.
使用此 patches.js
文件:
console.log("in patches")
function onCssVarsPonyfillLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()");
cssVars({
onlyLegacy: false,
onComplete: function (cssText, styleElms, cssVariables, benchmark) {
console.log('cssVars:onComplete');
}
});
}
function onOfficejsLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()");
Office.onReady(function () {
console.log("office.js is ready.");
// patch();
})
}
我要接手 a website by V2 Docusaurus。
我们网站的一个特殊性是我们需要加载office.js and css-vars-ponyfill.min.js,并在一开始就进行一些操作。所以之前的开发者决定使用下面的方法。
在每个.mdx.md
页面中,他用一个组件包裹内容MainWrapper
:
<MainWrapper>
... ...
Real content
... ...
</MainWrapper>
MainWrapper/index.js
定义如下
function MainWrapper(props) {
return (<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded MainWrapper')}).call(this)" >
</script>
</Head>
<CssvarsWrapper></CssvarsWrapper>
<OfficejsWrapper></OfficejsWrapper>
{props.children}
</>)
}
export default MainWrapper;
CssvarsWrapper/index.js
定义如下
function CssvarsWrapper(props) {
return (<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded in CssvarsWrapper')}).call(this)">
</script>
{console.log("CssvarsWrapper > index.js > CssvarsWrapper")}
<script defer
src="https://unpkg.com/css-vars-ponyfill@2/dist/css-vars-ponyfill.min.js"
onload="(function(){console.log('css-vars-ponyfill.min.js fully loaded in CssvarsWrapper'); onCssVarsPonyfillLoad()}).call(this) ">
</script>
</Head>
{props.children}
</>)
}
OfficejsWrapper/index.js
定义如下
function OfficeWrapper(props) {
return (
<>
<Head>
<script defer
src="https://www.10studio.tech/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded in OfficeWrapper')}).call(this)">
</script>
{console.log("OfficejsWrapper > index.js > OfficeWrapper")}
<script defer
src='https://appsforoffice.microsoft.com/lib/1/hosted/office.js'
onload="(function(){console.log('office.js fully loaded in OfficeWrapper'); onOfficejsLoad()}).call(this) ">
</script>
</Head>
{props.children}
</>
)
}
lib/Patches.js
包含实际操作:
console.log("in patches")
... ...
function onCssVarsPonyfillLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()")
cssVars({
onlyLegacy: false,
onComplete: function (cssText, styleElms, cssVariables, benchmark) {
}
});
}
function onOfficejsLoad() {
Office.onReady(function () {
console.log("office.js is ready.");
patch();
})
}
但是,我的测试表明,无论 defer
标记如何,此实现都不能始终遵循正确的文件加载顺序。例如,如下图所示,css-vars-ponyfill.min.js fully loaded in CssvarsWrapper
和 office.js fully loaded in OfficeWrapper
在 patches.js fully loaded
之前,因此 onCssVarsPonyfillLoad
和 onOfficejsLoad
在被调用时还没有准备好。
实际上,我们应该确保patches.js
总是在css-vars-ponyfill.min.js
和office.js
之前加载。有谁知道如何确保这一点?
此外,这种方法(即围绕每个页面的内容包装一个组件以在上游执行一些操作)是否正确?
TLDR;
如果您希望脚本按顺序执行,您需要添加 defer
到您的 <script>
标签。
您可以在此处阅读更多相关信息:https://www.w3schools.com/tags/att_script_defer.asp
稍微长一点的版本
尽管如此,我想强调一些关于您的实施的事情
您正在虚拟 DOM 环境中工作,您的组件可能 mount/unmount 取决于许多用例。我绝不会推荐任何人像这样加载文件:
<script
src="/lib/patches.js"
onload="(function(){console.log('patches.js fully loaded 1')}).call(this)">
</script>
相反,我建议在单个文件中定义方法并将其导出,这样我就可以在我的应用程序中使用我想使用的任何方法。这不仅会在每次挂载组件时终止文件加载,还会提高效率和执行。
这种方法更像是模块化方法。检查一下
如果您无力分解模块,而是想使用当前使用的方法,则需要使用 defer
来确保脚本按照定义的相同顺序执行。
以前的开发人员决定实现此加载脚本的方式多次,特别是它加载 patches.js
不止一次。
我建议您尝试放弃此实现并在 docusaurus.config.js
中使用 Docusaurus scripts-array
来定义这些脚本,并在 office.js
和 css-vars-ponyfill.min.js
上使用 defer
并为那里的每个脚本定义 onload
脚本。这是在 Docusaurus 中加载外部( 和内部 patches.js
)脚本的正确方法。
设置里面的脚本docusaurus.config.js
:
module.exports = {
...
scripts: [
{
src: '/lib/patches.js'
},
{
src: 'https://appsforoffice.microsoft.com/lib/1/hosted/office.js',
defer: true,
onload: "(() => { console.log('office.js loaded'); onOfficejsLoad(); })()"
},
{
src: 'https://unpkg.com/css-vars-ponyfill@2/dist/css-vars-ponyfill.min.js',
defer: true,
onload: "(() => { console.log('css-vars-ponyfill.min.js loaded'); onCssVarsPonyfillLoad(); })()"
}
],
}
我们在这两个脚本上使用 defer
,这意味着脚本将在文档被解析后但在触发 DOMContentLoaded
.
在本地 Docusaurus 项目上尝试此操作,我在清除缓存后每次都按预期顺序加载脚本:
in patches
office.js loaded
patches.js > onCssVarsPonyfillLoad()
css-vars-ponyfill.min.js loaded
patches.js > onCssVarsPonyfillLoad()
cssVars:onComplete
office.js is ready.
使用此 patches.js
文件:
console.log("in patches")
function onCssVarsPonyfillLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()");
cssVars({
onlyLegacy: false,
onComplete: function (cssText, styleElms, cssVariables, benchmark) {
console.log('cssVars:onComplete');
}
});
}
function onOfficejsLoad() {
console.log("patches.js > onCssVarsPonyfillLoad()");
Office.onReady(function () {
console.log("office.js is ready.");
// patch();
})
}