美文网首页
高性能JavaScript - 加载和执行

高性能JavaScript - 加载和执行

作者: _树先生_ | 来源:发表于2019-12-12 22:07 被阅读0次

    ### 无阻塞的脚本

    减少`JavaScript`文件大小,并限制`HTTP`请求数,仅仅是创建响应迅速的Web应用的第一步。Web应用功能越丰富,所需的`JavaScript`代码就越多,所以精简源代码并不总是可行。尽管下载单个较大的`JavaScript`文件只会产生一次HTTP请求,却会锁死浏览器一大段时间。为避免这种情况,我们需要向页面中逐步加载`JavaScript`代码,这样做在某种程度上来说不会阻塞浏览器。

    无阻塞脚本的秘诀在于,在页面加载完成后才加载`JavaScript`代码。即在`window`对象的`load`事件触发后再下载脚本。

    ### 延迟的脚本

    ```

    <script type="text/javascript" src="./init.js" defer="defer"></script>

    <script src="./init.js" async="async" />

    ```

    - [defer](http://www.w3school.com.cn/tags/att_script_defer.asp) 只有 Internet Explorer 支持 defer 属性。

    - [async](http://www.w3school.com.cn/tags/att_script_async.asp) async 属性是 HTML5 中的新属性。

    ### 动态脚本元素

    ```

    var script = document.createElement('script');

    script.type = "text/javascript";

    script.src = "./init.js";

    document.getElementsByTagName("head")[0].appendChild(script);

    ```

    ### XMLHttpRequest 脚本注入

    ```

    var xhr = new XMLHttpRequest();

    xhr.open("get", "./init.js", true);

    xhr.onreadystatechange = function () {

        /**

        * Uninitialized (0) - 初始化状态

        * Open (1) - open() 方法已调用,但是 send() 方法未调用;请求还没有被发送

        * Sent (2) - Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。

        * Receiving (3) - 所有响应头部都已经接收到。响应体开始接收但未完成。

        * Loaded (4) - HTTP 响应已经完全接收。

        */

        if (xhr.readyState == 4) {

            var status = xhr.status; // HTTP状态码

            if (status >= 200 && status < 300 || status == 304) {

                var script = document.createElement('script');

                script.type = "text/javascript";

                script.text = xhr.responseText;

                document.body.appendChild(script);

            }

        }

    }

    xhr.send(null);

    ```

    ### 推荐的无阻塞模式

    ```

    /**

    * 加载脚本

    * url [String] 要加载的脚本地址

    * callback [Function] 加载成功后的回调函数

    */

    function loadScript (url, callback) {

        var script = document.createElement('script');

        script.type = "text/javascript";

        if (script.readyState) { // IE浏览器方案

            script.onreadystatechange = function () {

                /**

                * uninitialized: 初始状态

                * loading: 开始下载

                * loaded: 下载完成

                * interactive: 数据下载完成但尚不可用

                * complete: 所有数据已准备就绪

                */

                var readyState = script.readyState;

                if (readyState == "loaded" || readyState == "complete") {

                    script.onreadystatechange = null;

                    callback();

                }

            }

        } else {

            script.onload = function () {

                callback();

            }

        }

        script.src = url;

        document.getElementsByTagName("head")[0].appendChild(script);

    }

    loadScript("./init.js", function () {

        Application.init();

    })

    ```

    ### 小结

        每次遇到`<script>`标签都会阻塞浏览器的其他进程,如界面渲染;页面需要等待代码下载并执行完成,才可以渲染。推荐一下几种优化方案:

        1、将所有的`<script>`标签放在`</body>`闭合标签前;确保在脚本执行前页面已经渲染完成。

        2、合并脚本。减少`<script>`标签使 加载 和 响应都变得更快。

        3、无阻塞下载方法:

            - 使用`<script>`标签的`defer`属性

            - 使用动态创建`<script>`元素来下载并执行代码。

            - 使用`XHR`对象下载代码并注入页面执行

    相关文章

      网友评论

          本文标题:高性能JavaScript - 加载和执行

          本文链接:https://www.haomeiwen.com/subject/ytvmqqtx.html