I'm taking over a website by V2 Docusaurus.
One particularity of our website is that we need to load office.js and css-vars-ponyfill.min.js, and do some operations in the very beginning. So the previous developer decided to use the following approach.
In every .mdx.md
page, he wrapped the content by a component MainWrapper
:
<MainWrapper>
... ...
Real content
... ...
</MainWrapper>
MainWrapper/index.js
is defined as follows
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
is defined as follows
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
is defined as follows
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
contains real operations:
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();
})
}
However, my test showed that this implementation cannot always respect a correct order of loading of files, regardless of the defer
tag. For example, as the following screenshot shows, css-vars-ponyfill.min.js fully loaded in CssvarsWrapper
and office.js fully loaded in OfficeWrapper
were before patches.js fully loaded
, as a consequence onCssVarsPonyfillLoad
and onOfficejsLoad
were not ready when they were called.
Actually, we should ensure that patches.js
is always loaded before css-vars-ponyfill.min.js
and office.js
. Does anyone know how to ensure that?
Additionally, is this approach (i.e., wrapping a component around content of every page to do some operations upstream) correct?
The way the previous developer decided to implement this loads scripts multiple times and particular it loads patches.js
more than once.
I suggest you try to ditch this implementation and use Docusaurus scripts-array
inside docusaurus.config.js
to define these scripts and use defer
on office.js
and css-vars-ponyfill.min.js
and define the onload
script for each script there. That's the proper way to load external (and internal like patches.js
) scripts in Docusaurus.
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(); })()"
}
],
}
We use defer
on these two scripts and that means that the scripts will be executed and loaded after the document has been parsed, but before firing DOMContentLoaded
.
Trying this on a local Docusaurus project I got the scripts loading on the expected order every single time after clearing the cache:
in patches
office.js loaded
patches.js > onCssVarsPonyfillLoad()
css-vars-ponyfill.min.js loaded
patches.js > onCssVarsPonyfillLoad()
cssVars:onComplete
office.js is ready.
using this patches.js
file:
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();
})
}