Remove Render-Blocking JavaScripts

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
8 years ago
Here is my solution. not passing the google's Eliminate render-blocking JavaScript but you can optimize the first bite time, content download time.

Step1) Script on _Root.Head ( before </body> )
<script type="text/javascript">

    function downloadJSAtOnload() {
        (function (scripts) {
            var i = 0,
                l = scripts.length;
            for (; i < l; ++i) {
                var element = document.createElement("script");
                element.src = scripts[i];
                document.body.appendChild(element);
            }
        })(['http://www.xxxxxx.com/Themes/NopShop/Scripts/example1.js', 'http://www.xxxxxx.com/Themes/NopShop/Content/example2.js']);
    }

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

    </script>

Step2) put your .js file source instead of http://www.xxxxxx.com/Themes/NopShop/Scripts/example1.js and example2.js. you can add as many as you want.

Step3) Remove Html.AppendScriptParts and Html.AddScriptParts calls for the scripts you used in step2.

If you test your website on http://www.webpagetest.org/ you will see that your scripts are loading after content download.

ps: make sure you are not defering the scripts need to be loaded before main content, means do not try to over optimize :))
8 years ago
Hi guys,

Do you have something new to share?

I didnt get too much time to work on this since my last post.

Thanks!
8 years ago
I am making changes for 3.60 I didn't have time either. but I really don't worry abt it bc it only changes 1 or 2 points on google speed. Not a big deal.
8 years ago
dianoche wrote:
but I really don't worry abt it bc it only changes 1 or 2 points on google speed. Not a big deal.


You should. From Abril 21st, Google started to check website's mobile version, so, on mobile, the blocking scripts down score almost 30 points, what results a pretty bad total.

We must fix it ASAP.

Ivan.
8 years ago
ivanslater wrote:
but I really don't worry abt it bc it only changes 1 or 2 points on google speed. Not a big deal.

You should. From Abril 21st, Google started to check website's mobile version, so, on mobile, the blocking scripts down score almost 30 points, what results a pretty bad total.

We must fix it ASAP.

Ivan.


I agree but my mobile speed is 68 now. Passing mobile friendly test. I agree that would be nice to be able to pass that google rule. We are working on gift registry now. That is our priority right now. I think a.m. can give us some ideas about how we can implement remove rendering java script. I saw a work item for inline java scripts. After that it would be easier to find a way.
8 years ago
Ivan,
Have you ever tried this approach?
8 years ago
anyone have tried this ? http://www.techumber.com/2014/05/simple-non-blocking-javascript-mulitple-scripts.html
8 years ago
Yes, this is a good approach..

The big problem still is remove all inline scripts and put them into JS file, so they can be deferred..

The main focus is the WEB project because we can use ADMIN area as it is, without deferring scripts.

I didnt have too much time these days, but it is on our focus.

I let you know!

Ivan.
8 years ago
Eu consegui 100% no PagesPeed, mas antes fiz as seguintes inclusões e alterações:

1) Em LayoutExtensions.cs adicionei as linhas:

        public static void AddFootCustomParts(this HtmlHelper html, string part)
        {
            var pageFootBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
            pageFootBuilder.AddFootCustomParts(part);
        }

        public static void AppendFootCustomParts(this HtmlHelper html, string part)
        {
            var pageFootBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
            pageFootBuilder.AppendFootCustomParts(part);
        }

        public static MvcHtmlString NopFootCustom(this HtmlHelper html)
        {
            var pageFootBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
            return MvcHtmlString.Create(pageFootBuilder.GenerateFootCustom());
        }

------------------------------------------------------

2) Em IPageHeadBuilder.cs adicionei as linhas:

        void AddFootCustomParts(string part);
        void AppendFootCustomParts(string part);
        string GenerateFootCustom();

------------------------------------------------------

3) Para todos as páginas *.cshtml que contém scripts fiz o seguinte:

Abaixo um exemplo da página: customer\info.cshtml

@using System.Text;    

var sb = new StringBuilder();
    sb.AppendLine("<script>");
    sb.AppendLine("$(function () {");
    sb.AppendLine("$(\"#" + Html.FieldIdFor(model => model.CountryId) + "\").change(function () {");
    sb.AppendLine("var selectedItem = $(this).val();");
    sb.AppendLine("var ddlStates = $(\"#StateProvinceId\");");
    sb.AppendLine("var statesProgress = $(\"#states-loading-progress\");");
    sb.AppendLine("statesProgress.show();");
    sb.AppendLine("$.ajax({");
    sb.AppendLine("cache: false,");
    sb.AppendLine("type: \"GET\",");
    sb.AppendLine("url: \"" + Url.RouteUrl("GetStatesByCountryId") + "\",");
    sb.AppendLine("data: { \"countryId\": selectedItem, \"addSelectStateItem\": \"true\" },");
    sb.AppendLine("success: function (data) {");
    sb.AppendLine("ddlStates.html('');");
    sb.AppendLine("$.each(data, function (id, option) {");
    sb.AppendLine("ddlStates.append($('<option></option>').val(option.id).html(option.name));");
    sb.AppendLine("});");
    sb.AppendLine("statesProgress.hide();");
    sb.AppendLine("},");
    sb.AppendLine("error: function (xhr, ajaxOptions, thrownError) {");
    sb.AppendLine("alert('Failed to retrieve states.');");
    sb.AppendLine("statesProgress.hide();");
    sb.AppendLine("}");
    sb.AppendLine("});");
    sb.AppendLine("});");
    sb.AppendLine("});");
    sb.AppendLine("</script>");
    Html.AddFootCustomParts(sb.ToString());

------------------------------------------------------

4) Em _Root.Heard.cshml antes do término do body fiz o seguinte:

  @Html.NopScripts(this.Url, ResourceLocation.Head)
  @Html.NopScripts(this.Url, ResourceLocation.Foot)
  @Html.NopFootCustom()
</body>


------------------------------------------------------

5) Para o bloqueio CSS.

1- Antes rodei o site e copie todo conteúdo css que foi gerado pelo bundles css para um arquivo chamado master.css que adicionei na pasta principal do site.

2- Em CommonController.cs fiz o seguinte:

        //master.css CssHeader
        [ChildActionOnly]
        public ActionResult CssHeader()
        {
            string result = System.IO.File.ReadAllText(Server.MapPath("~/master.css"));
            string htmlInput = string.Format("<style type=\"text/css\">{0}</style>", result);
            return Content(htmlInput);
        }

2- Em <head>
   <title>@Html.NopTitle(true)</title>
   @Html.Action("CssHeader", "Common")

Todo conteúdo css agora é renderizado logo apos o título da página conforme o próprio código fonte da página de testes do Page Speed do Google.


------------------------------------------------------

6) Para minificar e reduzir espaços de todo código html das paginas, adicionei no projeto:

  WebMarkupMin.Core
  WebMarkupMin.Mvc
  WebMarkupMin.Web
  WebMarkupMin.WebForms

Nos controladores adicionei:

using WebMarkupMin.Mvc.ActionFilters;

Em quase todas as public ActionResult, acima dicionei:

[MinifyHtml]

Deu certo :)

http://www.simpatiaspopulares.com/images/pagesSpeed.jpg
8 years ago
ricardo wrote:


3) Para todos as páginas *.cshtml que contém scripts fiz o seguinte:

Abaixo um exemplo da página: customer\info.cshtml

@using System.Text;    

var sb = new StringBuilder();
    sb.AppendLine("<script>");
    sb.AppendLine("$(function () {");
    sb.AppendLine("$(\"#" + Html.FieldIdFor(model => model.CountryId) + "\").change(function () {");
    sb.AppendLine("var selectedItem = $(this).val();");
    sb.AppendLine("var ddlStates = $(\"#StateProvinceId\");");
    sb.AppendLine("var statesProgress = $(\"#states-loading-progress\");");
    sb.AppendLine("statesProgress.show();");
    sb.AppendLine("$.ajax({");
    sb.AppendLine("cache: false,");
    sb.AppendLine("type: \"GET\",");
    sb.AppendLine("url: \"" + Url.RouteUrl("GetStatesByCountryId") + "\",");
    sb.AppendLine("data: { \"countryId\": selectedItem, \"addSelectStateItem\": \"true\" },");
    sb.AppendLine("success: function (data) {");
    sb.AppendLine("ddlStates.html('');");
    sb.AppendLine("$.each(data, function (id, option) {");
    sb.AppendLine("ddlStates.append($('<option></option>').val(option.id).html(option.name));");
    sb.AppendLine("});");
    sb.AppendLine("statesProgress.hide();");
    sb.AppendLine("},");
    sb.AppendLine("error: function (xhr, ajaxOptions, thrownError) {");
    sb.AppendLine("alert('Failed to retrieve states.');");
    sb.AppendLine("statesProgress.hide();");
    sb.AppendLine("}");
    sb.AppendLine("});");
    sb.AppendLine("});");
    sb.AppendLine("});");
    sb.AppendLine("</script>");
    Html.AddFootCustomParts(sb.ToString());



As we said, the big trouble is remove all script from cshtml files. We should test what solution has less impact on response time, once will be a lot of .CS code in .CSHTML files to be processed, than using esxternal .js files.

Another problem on your solution is remove the bundle css file and make it fixed.

But, good job!
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.