1

我正在接管V2 Docusaurus网站

我们网站的一个特殊之处是我们需要加载office.jscss-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是 before patches.js fully loaded,因此onCssVarsPonyfillLoadonOfficejsLoad调用它们时还没有准备好。

实际上,我们应该确保patches.js总是在css-vars-ponyfill.min.jsoffice.js之前加载。有谁知道如何确保这一点?

此外,这种方法(即,围绕每个页面的内容包装一个组件以在上游进行一些操作)是否正确?

在此处输入图像描述

4

2 回答 2

1

以前的开发人员决定实现这种方式多次加载脚本,特别是多次加载patches.js

scripts-array我建议您尝试放弃此实现并在内部使用 Docusaurusdocusaurus.config.js来定义这些脚本,并在其中使用deferoffice.js定义css-vars-ponyfill.min.js每个脚本的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();
  })
}
于 2020-04-24T10:51:16.323 回答
0

TLDR;

如果您希望脚本按顺序执行,则需要添加以添加defer到您的标签中。<script>

您可以在此处阅读更多信息:https ://www.w3schools.com/tags/att_script_defer.asp


稍长一点的版本

不过,我想强调一些关于您的实施的事情

您在虚拟 DOM 环境中工作,您的组件可能会根据许多用例安装/卸载。我永远不会推荐任何人像这样加载文件:

<script 
    src="/lib/patches.js" 
    onload="(function(){console.log('patches.js fully loaded 1')}).call(this)">
</script>

相反,我建议在单个文件中定义方法并将其导出,这样我就可以在我的应用程序中使用我想使用的任何方法。这不仅会在每次挂载组件时终止文件加载,还会提高效率和执行力。

这种方法被称为模块化方法。看看这个https://stackoverflow.com/a/49616670/1681154如果你想了解更多关于模块化方法的信息,我在这里找到了一个很好的解释:https ://javascript.info/import-export 。

如果您不能分解模块,而是想使用您当前使用的方法,则需要使用defer以确保脚本按照其定义的相同顺序执行。

于 2020-04-15T05:18:12.020 回答