Inlining Js and Css files in ASP.Net MVC View

As part of testing the performance of some views I’ve been working on recently I kept seeing the following warning in the Chrome Dev tools:

"[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.",

When creating new views I’d created my “Components” in as 3 separate files: Component.cshtml, Component.js, Component.css. These were then being included with either link or script tags in the .cshtml file for the partial view. This is something I have become used to when working with Angular so it feels wrong to throw everything in one file.

All my $.ajax requests in the .js files were async (as they are by default so it had to be the import.

As Chrome was correctly identifying, including the files in this way wasn’t optimal, but what was the alternative?

Inlining

Now this approach might still not be ideal, but I didn’t want to add any additional steps to the existing build process or include any extra dependencies and make it simple for other developers to use in their own code, so the first step was to get the scripts content into the .cshtml.

A simple solution was to use the answer from this SO question.

First create a extension method which reads the text from the path provided, and then return it as a HtmlString so it is included on the page.

/Helpers/HtmlHelperExtensions.cs

public static class HtmlHelperExtensions
{
    public static MvcHtmlString InlineScriptBlock<TModel>(this HtmlHelper<TModel> htmlHelper, string path)
    {
        var builder = new TagBuilder("script");
        builder.Attributes.Add("type", "text/javascript");

        var physicalPath = htmlHelper.ViewContext.RequestContext.HttpContext.Server.MapPath(path);
        if (File.Exists(physicalPath))
        {
            builder.InnerHtml = File.ReadAllText(physicalPath);
        }

        return MvcHtmlString.Create(builder.ToString());
    }
}

This can then be used in a view file in place of the script import:

/Views/MyView/MyView.cshtml

@Html.InlineScriptBlock("~/Views/MyView/MyView.js")

<p>This view doesn't do much yet!</p>

Applying these changes to my code caused the error to go away, but it still felt like it needed improving, as no modifications were being made to the included javascript, it still contained unnecessary whitespace and could be made smaller. This will be covered in the next post about bundling.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s