How to defer inline Javascript?

前端 未结 5 1935
盖世英雄少女心
盖世英雄少女心 2020-11-28 23:25

I have the following html code:




    
    Document</         
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-5408099190056760"
     data-ad-slot="7305827575"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>        </div>
                      <div class="relativetags">
              相关标签:
       </div>
      </div>
      
      <div class="fly-panel detail-box" id="flyReply">
        <fieldset class="layui-elem-field layui-field-title" style="text-align: center;">
          <legend>5条回答</legend>        </fieldset>

        <ul class="jieda" id="jieda">
                         				            <li data-id="111">
            <a name="item-1111111111"></a>
           
            <div class="detail-about detail-about-reply">
                              <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-29.html">
                <img src="https://www.e-learn.cn/qa/data/avatar/000/00/00/small_000000029.jpg" alt=" ">
              </a>
              <div class="fly-detail-user">
                <a href="https://www.e-learn.cn/qa/u-29.html" class="fly-link">
                  <cite>甜味超标 </cite>       
                </a>
              </div>
                            <div class="detail-hits">
                <span>2020-11-28 23:42</span>
              </div>
            </div>
            <div class="detail-body jieda-body photos">
                                                                       
<h2>Defer/async script tags are not good enough</h2>

<p>There is a common knowledge that you should use <code><script src=".." async defer></code> (or set <code>script.async = true</code> before assigning <code>src</code>, when you do it from JS) and/or put your scripts at the very bottom of the page, so that as much as possible of the page gets loaded and rendered to the user, as fast as possible.</p>

<p>defer.js (note: <strong>I am the author of this script</strong>) is written in plain JavaScript, making lazy-loading other contents more fast and performant. You can defer any javascript files as well as inline script blocks efficiently.</p>

<p><img src="https://raw.githubusercontent.com/shinsenter/defer.js/master/docs/assets/defer-script.jpg" alt="Defer loading of JavaScript"></p>

<p>If your page is just an HTML page enhanced with some JavaScript, then you're good with just <code><script async></code>. It takes time for browser to parse and execute those scripts, and each UI change may reflow your layout, make your load speed more slow, no one likes staring at a blank white page; users are impatient and will leave quickly.</p>

<p>In various cases, using <code>async</code> or <code>defer</code> does not deliver faster page speed than defer.js does.</p>
                                                                        <div class="appendcontent">
                                                        </div>
            </div>
            <div class="jieda-reply">
              <span class="jieda-zan button_agree" type="zan" data-id='528021'>
                <i class="iconfont icon-zan"></i>
                <em>0</em>
              </span>
                 <span type="reply" class="showpinglun" data-id="528021">
                <i class="iconfont icon-svgmoban53"></i>
               讨论(0)
              </span>
              
                                                   
              <div class="jieda-admin">
                                                            </div>
            </div>
                      <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_528021">
                    <div class="areabox clearfix">

<form class="layui-form" action="">
               
            <div class="layui-form-item">
    <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
    <div class="layui-input-block" style="margin-left:90px;">
         <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                        <input type='hidden' value='0' name='replyauthor' />
    </div>
    <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="528021">提交评论 </span></div>
  </div>
  
</form>
                    </div>
                    <hr>
                    <ul class="my-comments-list nav">
                        <li class="loading">
                        <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                         加载中...
                        </li>
                    </ul>
                </div>
          </li>
          	          <li data-id="111">
            <a name="item-1111111111"></a>
           
            <div class="detail-about detail-about-reply">
                              <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-136.html">
                <img src="https://www.e-learn.cn/qa/data/avatar/000/00/01/small_000000136.jpg" alt=" ">
              </a>
              <div class="fly-detail-user">
                <a href="https://www.e-learn.cn/qa/u-136.html" class="fly-link">
                  <cite>不要未来只要你来 </cite>       
                </a>
              </div>
                            <div class="detail-hits">
                <span>2020-11-28 23:49</span>
              </div>
            </div>
            <div class="detail-body jieda-body photos">
                                                                       
<p>From MDN docs:  </p>

<blockquote>
  <p><strong>defer</strong><br>
  This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing <code>DOMContentLoaded</code>. <strong><em>The defer attribute should only be used on external scripts.</em></strong>  </p>
</blockquote>

<p>This is called an IIFE <em>(Immediately Invoked Function Expression)</em> which gets executed before DOM is available. So, in that case <code>jQuery</code> is undefined because it it not in the DOM.  </p>
                                                                        <div class="appendcontent">
                                                        </div>
            </div>
            <div class="jieda-reply">
              <span class="jieda-zan button_agree" type="zan" data-id='528019'>
                <i class="iconfont icon-zan"></i>
                <em>0</em>
              </span>
                 <span type="reply" class="showpinglun" data-id="528019">
                <i class="iconfont icon-svgmoban53"></i>
               讨论(0)
              </span>
              
                                                   
              <div class="jieda-admin">
                                                            </div>
            </div>
                      <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_528019">
                    <div class="areabox clearfix">

<form class="layui-form" action="">
               
            <div class="layui-form-item">
    <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
    <div class="layui-input-block" style="margin-left:90px;">
         <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                        <input type='hidden' value='0' name='replyauthor' />
    </div>
    <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="528019">提交评论 </span></div>
  </div>
  
</form>
                    </div>
                    <hr>
                    <ul class="my-comments-list nav">
                        <li class="loading">
                        <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                         加载中...
                        </li>
                    </ul>
                </div>
          </li>
          	          <li data-id="111">
            <a name="item-1111111111"></a>
           
            <div class="detail-about detail-about-reply">
                              <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-12.html">
                <img src="https://www.e-learn.cn/qa/data/avatar/000/00/00/small_000000012.jpg" alt=" ">
              </a>
              <div class="fly-detail-user">
                <a href="https://www.e-learn.cn/qa/u-12.html" class="fly-link">
                  <cite>[愿得一人] </cite>       
                </a>
              </div>
                            <div class="detail-hits">
                <span>2020-11-28 23:53</span>
              </div>
            </div>
            <div class="detail-body jieda-body photos">
                                                                       
<p>You can create a Base64 URL out of the script and put it into the src!</p>

<pre><code><script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
        defer>
</script>
</code></pre>

<p>I built a quick test to see it in action.
You should see an alert with <code>Hello world!</code> last if <code>defer</code> is working:</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code><script defer>
  alert('Why no defer?!?');
</script>

<!-- alert('Hello world!'); -->
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
        defer></script>

<script>
  alert('Buh-bye world!');
</script></code></pre>
</div>
</div>
</p>

<p>Doing it manually is a little laborious so if you have the luxury of compiling your HTML in some way (Handlebars, Angular, etc.) then that helps a lot.</p>

<p>I'm currently using:</p>

<pre><code><script src="data:text/javascript;base64,{{base64 "alert('Hello world!');"}}"
        defer>
</script>
</code></pre>
                                                                        <div class="appendcontent">
                                                        </div>
            </div>
            <div class="jieda-reply">
              <span class="jieda-zan button_agree" type="zan" data-id='528018'>
                <i class="iconfont icon-zan"></i>
                <em>0</em>
              </span>
                 <span type="reply" class="showpinglun" data-id="528018">
                <i class="iconfont icon-svgmoban53"></i>
               讨论(0)
              </span>
              
                                                   
              <div class="jieda-admin">
                                                            </div>
            </div>
                      <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_528018">
                    <div class="areabox clearfix">

<form class="layui-form" action="">
               
            <div class="layui-form-item">
    <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
    <div class="layui-input-block" style="margin-left:90px;">
         <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                        <input type='hidden' value='0' name='replyauthor' />
    </div>
    <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="528018">提交评论 </span></div>
  </div>
  
</form>
                    </div>
                    <hr>
                    <ul class="my-comments-list nav">
                        <li class="loading">
                        <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                         加载中...
                        </li>
                    </ul>
                </div>
          </li>
          	          <li data-id="111">
            <a name="item-1111111111"></a>
           
            <div class="detail-about detail-about-reply">
                              <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-13.html">
                <img src="https://www.e-learn.cn/qa/data/avatar/000/00/00/small_000000013.jpg" alt=" ">
              </a>
              <div class="fly-detail-user">
                <a href="https://www.e-learn.cn/qa/u-13.html" class="fly-link">
                  <cite>傲寒 </cite>       
                </a>
              </div>
                            <div class="detail-hits">
                <span>2020-11-28 23:56</span>
              </div>
            </div>
            <div class="detail-body jieda-body photos">
                                                                       
<h1>defer loading with plain text Data URI - Chrome and FF</h1>

<p>#noLib #vanillaJS</p>

<p><strong>suggest not to use on Cross Browser PRODuction</strong> </p>

<p>until MS IE dies and MS Edge will adopt the Chromium open source ;)</p>

<h2>the only way to defer script is <strong>external file</strong> or <strong>Data_URI</strong> (without using event DOMContentLoaded)</h2>

<h3>defer</h3>

<p>spec script#attr-defer (MDN web docs): "This attribute must not be used if the src attribute is absent (i.e. for inline scripts), in this case it would have no effect.)"</p>

<h3>Data_URI</h3>

<p>spec Data_URI</p>

<p>with right <strong>type "text/javascript"</strong> there is no need to <strong>base64</strong> at all... ;) </p>

<p><strong>using plain text</strong> so you can use simple:</p>

<pre><code><script defer src="data:text/javascript,

//do something with b-lazy plugin, lightbox plugin and then with flexslider

lightbox.option({
  resizeDuration: 200,
  wrapAround: true
})

">
</code></pre>

<p>yes, it's little bit weird hack, but <code><script type="module"></code> are deferred by default, there is no other option to <strong>mix following in exact order</strong>:</p>

<ul>
<li>module external files - deferred <strong>by default</strong></li>
<li>module inline scripts - deferred <strong>by default</strong></li>
<li>external files - <strong>optionally</strong> deferred</li>
<li>inline scripts - only with this <strong>hack</strong> - as I know (without libraries/frameworks)</li>
</ul>
                                                                        <div class="appendcontent">
                                                        </div>
            </div>
            <div class="jieda-reply">
              <span class="jieda-zan button_agree" type="zan" data-id='528020'>
                <i class="iconfont icon-zan"></i>
                <em>0</em>
              </span>
                 <span type="reply" class="showpinglun" data-id="528020">
                <i class="iconfont icon-svgmoban53"></i>
               讨论(0)
              </span>
              
                                                   
              <div class="jieda-admin">
                                                            </div>
            </div>
                      <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_528020">
                    <div class="areabox clearfix">

<form class="layui-form" action="">
               
            <div class="layui-form-item">
    <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
    <div class="layui-input-block" style="margin-left:90px;">
         <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                        <input type='hidden' value='0' name='replyauthor' />
    </div>
    <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="528020">提交评论 </span></div>
  </div>
  
</form>
                    </div>
                    <hr>
                    <ul class="my-comments-list nav">
                        <li class="loading">
                        <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                         加载中...
                        </li>
                    </ul>
                </div>
          </li>
          	          <li data-id="111">
            <a name="item-1111111111"></a>
           
            <div class="detail-about detail-about-reply">
                              <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-124.html">
                <img src="https://www.e-learn.cn/qa/data/avatar/000/00/01/small_000000124.jpg" alt=" ">
              </a>
              <div class="fly-detail-user">
                <a href="https://www.e-learn.cn/qa/u-124.html" class="fly-link">
                  <cite>心在旅途 </cite>       
                </a>
              </div>
                            <div class="detail-hits">
                <span>2020-11-28 23:59</span>
              </div>
            </div>
            <div class="detail-body jieda-body photos">
                                                                       
<p>The scripts with the <code>defer</code> attribute load in the order they are specified, but <em>not before</em> the document itself has been loaded. As <code>defer</code> has no effect on <code>script</code> tags unless they also have the <code>src</code> attribute, the first script that gets executed is your inline script. So at that time jQuery is not loaded yet.</p>

<p>You can solve this in at least two ways:</p>

<ul>
<li><p>Put your inline script in a <code>.js</code> file and reference it with a <code>src</code> attribute (in addition to the <code>defer</code> attribute which you already had there), or</p></li>
<li><p>Let your inline script wait for the document and the deferred scripts to be loaded. The <code>DOMContentLoaded</code> event will fire when that has happened:</p>

<pre><code><script>
    window.addEventListener('DOMContentLoaded', function() {
        (function($) {
            //do something with b-lazy plugin, lightbox plugin and then with flexslider
        })(jQuery);
    });
</script>
</code></pre></li>
</ul>

<p>NB: Notice that in the latter case <code>$(document).ready(function()</code> is not included any more, as that would wait for the same event (<code>DOMContentLoaded</code>). You <em>could</em> still include it like you had in your original code, but then jQuery would just execute the callback <em>immediately</em>, which makes no practical difference.</p>
                                                                        <div class="appendcontent">
                                                        </div>
            </div>
            <div class="jieda-reply">
              <span class="jieda-zan button_agree" type="zan" data-id='528017'>
                <i class="iconfont icon-zan"></i>
                <em>0</em>
              </span>
                 <span type="reply" class="showpinglun" data-id="528017">
                <i class="iconfont icon-svgmoban53"></i>
               讨论(0)
              </span>
              
                                                   
              <div class="jieda-admin">
                                                            </div>
            </div>
                      <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_528017">
                    <div class="areabox clearfix">

<form class="layui-form" action="">
               
            <div class="layui-form-item">
    <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
    <div class="layui-input-block" style="margin-left:90px;">
         <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                        <input type='hidden' value='0' name='replyauthor' />
    </div>
    <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="528017">提交评论 </span></div>
  </div>
  
</form>
                    </div>
                    <hr>
                    <ul class="my-comments-list nav">
                        <li class="loading">
                        <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                         加载中...
                        </li>
                    </ul>
                </div>
          </li>
          	          
           <style>
   
.laypage-main a, .laypage-main span {
    display: inline-block;
}
        </style>                  </ul>
        
        <div class="layui-form layui-form-pane">
          <form id="huidaform"  name="answerForm"  method="post">
            
            <div class="layui-form-item layui-form-text">
              <a name="comment"></a>
              <div class="layui-input-block">
            
    
<script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.config.js"></script>
<script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.all.js"></script>
<script type="text/plain" id="editor"  name="content"  style="width:100%;height:200px;"></script>                                 
<script type="text/javascript">
                                 var isueditor=1;
            var editor = UE.getEditor('editor',{
                //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个
                toolbars:[['source','fullscreen',  '|', 'undo', 'redo', '|', 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|', 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'link', 'unlink', 'anchor', '|', 'simpleupload', 'insertimage', 'scrawl', 'insertvideo', 'attachment', 'map', 'insertcode', '|', 'horizontal', '|', 'preview', 'searchreplace', 'drafts']],
            
                initialContent:'',
                //关闭字数统计
                wordCount:false,
                zIndex:2,
                //关闭elementPath
                elementPathEnabled:false,
                //默认的编辑区域高度
                initialFrameHeight:250
                //更多其他参数,请参考ueditor.config.js中的配置项
                //更多其他参数,请参考ueditor.config.js中的配置项
            });
                        editor.ready(function() {
            	editor.setDisabled();
            	});
                            $("#editor").find("*").css("max-width","362px");
        </script>              </div>
            </div>
                          
    

        
         <div class="layui-form-item">
                <label for="L_vercode" class="layui-form-label">验证码</label>
                <div class="layui-input-inline">
                  <input type="text"  id="code" name="code"   value="" required lay-verify="required" placeholder="图片验证码" autocomplete="off" class="layui-input">
                </div>
                <div class="layui-form-mid">
                  <span style="color: #c00;"><img class="hand" src="https://www.e-learn.cn/qa/user/code.html" onclick="javascript:updatecode();" id="verifycode"><a class="changecode"  href="javascript:updatecode();"> 看不清?</a></span>
                </div>
              </div>
                                  <div class="layui-form-item">
                    <input type="hidden" value="133010" id="ans_qid" name="qid">
   <input type="hidden" id="tokenkey" name="tokenkey" value=''/>
                <input type="hidden" value="How to defer inline Javascript?" id="ans_title" name="title"> 
             
              <div class="layui-btn    layui-btn-disabled"  id="ajaxsubmitasnwer" >提交回复</div>
            </div>
          </form>
        </div>
      </div>
      <input type="hidden" value="133010" id="adopt_qid"	name="qid" /> 
      <input type="hidden" id="adopt_answer" value="0"	name="aid" />
    </div>
    <div class="layui-col-md4">
          
 <!-- 热门讨论问题 -->
     
 <dl class="fly-panel fly-list-one">
        <dt class="fly-panel-title">热议问题</dt>
            <!-- 本周热门讨论问题显示10条-->