如果动态添加的脚本是异步的,性能会更好吗

时间:2018-12-17 11:15:01

标签: javascript performance browser lazy-loading

关于此主题的几个问题如下:Is the "async" attribute/property useful if a script is dynamically added to the DOM?

但是所有这些问题仅着眼于在DOM上添加一个脚本标记,还是仅在彼此不依赖的脚本标记上添加

我们使用Three.js及其示例。由于Three.js是一个复杂的项目,因此很长一段时间以来,并不是整个示例等都是围绕ES模块构建的。因此,我们通过添加脚本标签来动态加载这些示例脚本。如其他问题所述,添加脚本标签会将其动态设置为异步。但是您可以覆盖此行为。这对我们来说很好,因为如果我们将脚本设置为async:false,则执行顺序得以保留(这有助于降低复杂性),基本上,我们要做的是以下操作(实际代码更多,但此处我想展示要点):

const attatch = (url, options = {}) => {
    return new Promise((resolve, reject) => {
        const element = document.createElement('script');
        element.async = options.async || false;
        element.src = url;
        if (options.id) {
            element.id = options.id;
        }
        element.onload = () => {
            resolve();
        };
        element.onerror = (error) => {
            reject(error);
        };
        starts.push(performance.now());
        document.getElementById('container').appendChild(element);
    });
};

Promise.all([
    attatch('./three/lib/rthree.js'),
    attatch('./three/lib/postprocessing/EffectComposer.js', {id: 'effect-composer-js'}),
    attatch('./three/lib/postprocessing/RenderPass.js', {id: 'render-pass-js'}),
    attatch('./three/lib/postprocessing/ShaderPass.js', {id: 'shader-pass-js'}),
    attatch('./three/lib/shaders/LuminosityHighPassShader.js', {id: 'luminosity-high-pass-shader-js'}),
    attatch('./three/lib/postprocessing/UnrealBloomPass.js', {id: 'unreal-bloom-pass-js'}),
    attatch('./three/lib/postprocessing/OutlinePass.js', {id: 'outline-pass-js'})
]).then(() => {
    // Run 3D content now
});

我做了一些基准测试,但没有发现将async设置为false之间有任何显着差异。但是我不确定我是否没有错过任何事情。特别是因为我还希望浏览器在加载脚本时构造UI,然后在一切就绪的情况下启动Three.js场景。由于在我们的真实应用中对这种变化进行基准测试并不容易,因此我创建了一个示例项目。由于我没有发现真正的差异,这让我想知道我是否测量不正确,或者是否真的没有性能差异。

您认为使用async:true而不是async:false可以显着改善性能,或者这充其量是微优化吗?附注:我们只对modern browsers

的结果感兴趣

1 个答案:

答案 0 :(得分:0)

您的结果对我来说很有意义。 dependencies { compile 'org.elasticsearch.client:elasticsearch-rest-high-level-client:6.5.3' } 会告诉浏览器在到达async标签时继续解析HTML,并在文件准备好后立即执行。由于您已经使用<script>异步加载Javascript文件,因此这不会阻止浏览器继续解析HTML,因此,是否使用Promises并不重要。我什至会删除它以简化源代码。