如何检测动态模块及其所有依赖项何时被加载?

时间:2017-08-29 12:04:40

标签: webpack ecmascript-6 dynamic-import

Webpack支持符合import()动态导入的ECMAScript proposal语法。此语法使用promises异步加载模块。

问题是,只要加载了特定模块,就会解决promise,而无需等待模块的依赖项加载(可以是任何类型的资产,包括JS和CSS)。

示例代码:

import('./myModule.js').then(myModule => {
    myModule.sayHello(); // This will be called before someCSS.css has been loaded
});

myModule.js

import './someCSS.css'; // <-- I need to know when this is loaded (there can be more than one asset)

export default class myModule {
    sayHello() {
        alert('Hello!');
    }
}

如何检测模块和所有相关资产何时加载?类似于异步资产的onload事件?

2 个答案:

答案 0 :(得分:0)

该方法返回Promise,它允许您确定脚本是否已加载或加载时发生错误(例如):

// utils.js
function insertJs({src, isModule, async, defer}) {
    const script = document.createElement('script');

    if(isModule){
      script.type = 'module';
    } else{
      script.type = 'application/javascript';
    }
    if(async){
      script.setAttribute('async', '');
    }
    if(defer){
      script.setAttribute('defer', '');
    }

    document.head.appendChild(script);

    return new Promise((success, error) => {
        script.onload = success;
        script.onerror = error;
        script.src = src;// start loading the script
    });
}

export {insertJs};
//An example of its use:

import {insertJs} from './utils.js'

// The inserted node will be:
// <script type="module" src="js/module-to-be-inserted.js"></script>
const src = './module-to-be-inserted.js';

insertJs({
  src,
  isModule: true,
  async: true
})
    .then(
        () => {
            alert(`Script "${src}" is successfully executed`);
        },
        (err) => {
            alert(`An error occured during the script "${src}" loading: ${err}`);
        }
    );
// module-to-be-inserted.js
alert('I\'m executed');

答案 1 :(得分:0)

可以使用document.styleSheets检查何时加载了所有样式表。只有在加载样式表后,CSSStyleSheet对象才会包含cssRules属性,因此您可以创建一个对其进行检查的承诺:

export function awaitStylesheets() {
    let interval;
    return new Promise(resolve => {
        interval = setInterval(() => {
            for (let i = 0; i < document.styleSheets.length; i++) {
                // A stylesheet is loaded when its object has a 'cssRules' property
                if (typeof document.styleSheets[i].cssRules === 'undefined') {
                    return;
                }
            }

            // Only reached when all stylesheets have been loaded
            clearInterval(interval);
            resolve();
        }, 10);
    });
}