2015-09-16 4 views
1

Я ищу, чтобы оптимизировать способ загрузки больших файлов javascript в моем MVC-проекте. Я уже использую связывание и минимизацию, но мне бы хотелось загрузить только несколько из них ПОСЛЕ загрузки HTML и CSS. Я смотрел на такого рода подход:Откладывание загрузки javascript в asp.net MVC

https://varvy.com/pagespeed/defer-loading-javascript.html

В этом подходе теги сценария впрыскивают в использовании JavaScript в случае загрузки/OnLoad после загрузки тела. Моя проблема заключается в том, что я хотел бы использовать наряду с набором и минимизацией, предлагаемыми каркасом, и я не нашел хорошего способа сделать это.

Я просто задаюсь вопросом, успешно ли кто-либо использовал этот подход с проектами MVC, и, возможно, уже может быть библиотека (на Nuget или иначе), чтобы облегчить это.

EDITED: Вот мое текущее решение, но я не уверен, что мне это нравится.

Поскольку структура Bundling может возвращать один тег сценария или список из них в зависимости от того, выполняется ли вы отлаживать или нет, нам нужно извлечь исходные значения для этих тегов. Для этого я создал статический помощник.

public static string ExtactFromScriptBundle(string aBundle) 
    { 
     List<string> returnValue = new List<string>(); 

     var jQueryString = Scripts.Render(aBundle).ToHtmlString(); 

     var reg = new Regex("\".*?\""); 

     var matches = reg.Matches(jQueryString); 
     foreach (var match in matches) 
     { 
      returnValue.Add(match.ToString().Replace("\"", "")); 
     } 

     return Json.Encode(returnValue); 
    } 

чем от _layout.cshtml вы cound вставить блок, как следующий прямо перед тегом:

<script> 
    function downloadJSAtOnload() { 
    createScripElementsFromArray(@Html.Raw(ScriptHelper.ExtactFromScriptBundle("~/bundles/jquery"))); 
createScripElementsFromArray(@Html.Raw(ScriptHelper.ExtactFromScriptBundle("~/bundles/bootstrap"))); 
    } 

    function createScripElementsFromArray(fileNameList) { 
     var arrayLength = fileNameList.length; 
     for (var i = 0; i < arrayLength; i++) { 
      createScripElement(fileNameList[i]); 
     } 
    } 

    function createScripElement(fileName) { 
     var element = document.createElement("script"); 
     element.src = fileName; 
     document.body.appendChild(element); 
     console.log(fileName + " was loaded"); 
    } 

    if (window.addEventListener) 
     window.addEventListener("load", downloadJSAtOnload, false); 
    else if (window.attachEvent) 
     window.attachEvent("onload", downloadJSAtOnload); 
    else window.onload = downloadJSAtOnload; 
</script> 

Это немного хак на мой взгляд, так как я рендеринга пучки просто разобрать выход, но я думаю, что я мог бы также кэшировать эти выходные данные для дальнейшей оптимизации рендеринга страницы.

ответ

0

Один из вариантов - использовать jquery для загрузки внешних скриптов. У вас будет начальная зависимость от самого jquery, но jquery - очень легкий.

Вы бы затем:

$(document).ready(function(){ 

    //At this point, the HTML/CSS has already been loaded and rendered. 

    //load external scripts 
    $.getScript("ajax/test.js", function(data, textStatus, jqxhr) { 
     console.log(data); // Data returned 
     console.log(textStatus); // Success 
     console.log(jqxhr.status); // 200 
     console.log("Load was performed."); 
    }); 

}); 

Jquery документ: https://api.jquery.com/jquery.getscript/

+0

Проблема с этим подходом заключается в том, что он не использует структуру связывания/минимизации для сжатия test.js. – daoom

2

По Occam's Razor, лучшим решением является использование Defer атрибут ...

<script src='myJavaScriptFile.js' defer></script> 

Это есть well supported.

Если вы хотите использовать его в ASP.NET MVC, то вы будете делать это:

Создать новую команду Razor так:

public static class Scripts 
{ 
    public static IHtmlString RenderDeferred(params string[] paths) 
    { 
     return Scripts.RenderFormat(@"<script src='{0}' defer></script>", paths); 
    } 
} 

И затем использовать его как это:

@Scripts.RenderDeferred("~/myBundle/myJavaScriptBundle") 
+0

Предполагая, что я загружаю каждый файл сам, но также хочу использовать инфраструктуру связывания и минимизации для оптимизации файлов. – daoom

+0

Хорошо, @daoom, как насчет сейчас? См. Мой обновленный ответ. – Rap

+0

Моя проблема в том, что, хотя решение кажется элегантным, реализация ключевого слова defer варьируется от браузера к браузеру, а порядок, в котором сценарии будут загружены и выполнены, не является полностью детерминированным.Использование defer, если скрипт B зависит от сценария A, и оба загружаются с отсрочкой, даже если вы размещаете один перед другим, вы не можете гарантировать, что они будут всегда загружаться и выполняться по порядку. – daoom

Смежные вопросы