DEV Community

Kevin Jump
Kevin Jump

Posted on

Smidge and Umbraco frontends

Previous versions of Umbraco came with the ClientDependencyFramework that let you bundle styles and scripts across your site. In fact the back office used it heavily to minimise all the Javascript.

In v9+ this has been replaced by Smidge - which does same job for the back office , but out of the box, it isn't quite configured to do the same from your front end (website) files.

You can add scripts or stylesheets to the site 'bundles' in your razor files:

for example you can add these to any of your razor templates:

SmidgeHelper.RequiresCss("~/css/site.css");
Enter fullscreen mode Exit fullscreen mode

or

SmidgeHelper.RequiresJs("~/scripts/payments.js");
Enter fullscreen mode Exit fullscreen mode

and then render them in the right place in your HTML with :

@await SmidgeHelper.CssHereAsync();
Enter fullscreen mode Exit fullscreen mode

and

@await SmidgeHelper.JsHereAsync();
Enter fullscreen mode Exit fullscreen mode

this works great but has a few problems :

  1. By default the script files are versioned with a version number that you have to change in the config file or your files will be cached by your site & browser

  2. You can't (with these native methods) add extra attributes to the tags (e.g <script src="file.js" async></script>)

Fortunately there are some work around for this:

1. Have generated files versioned with a timestamp in dev and appdomain (so after an app restart) on production

There are a few ways to make the css/js be better for developement a) you can set debug to true in the render tags:

@await SmidgeHelper.CssHereAsync(debug: true)
Enter fullscreen mode Exit fullscreen mode

b) you can change the configuration

now you can do this with a PostConfigure method that fires whenever the configuration changes :

builder.Services.PostConfigure<SmidgeOptions>(o =>
{
    o.DefaultBundleOptions.ProductionOptions
    .SetCacheBusterType(typeof(TimestampCacheBuster));
});
Enter fullscreen mode Exit fullscreen mode

or if you want to be a bit more fancy you can do this based on
the environment that is currently running via a configureOptions interface (where you can inject the Environment)

so in a composer you might have:

builder.Services.ConfigureOptions<SmidgeFrontEndSetup>();
Enter fullscreen mode Exit fullscreen mode

And then you have a IConfigureOptions<SmidgeOptions> interface
to set the value based on if you are running in development.

public class SmidgeFrontEndSetup : IConfigureOptions<SmidgeOptions>
{
    private readonly IWebHostEnvironment _webHostEnvironment;

    public SmidgeFrontEndSetup(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment = webHostEnvironment;
    }

    public void Configure(SmidgeOptions options)
    {
        if (_webHostEnvironment.EnvironmentName.Equals("Development", StringComparison.OrdinalIgnoreCase))
        {
            options.DefaultBundleOptions.ProductionOptions
                .SetCacheBusterType(typeof(TimestampCacheBuster));
        }
        else
        {
            options.DefaultBundleOptions.ProductionOptions
                .SetCacheBusterType(typeof(AppDomainLifetimeCacheBuster));
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Append extra attributes on script and style tags.

With ClientDependency in v8 you had the ability to append extra attributes to the script or link tags, when you rendered the bundle elements on your page. With the current release of smidge you can't do that with the default helper

but you can do it with a loop (and yes this could be made into a extension to help you. e.g.

replace :

@await SmidgeHelper.JsHereAsync()
Enter fullscreen mode Exit fullscreen mode

with:

@{
    var urls = await SmidgeHelper.GenerateJsUrlsAsync();
    foreach(var url in urls)
    {
        <script src="@url" async></script>
    }
}
Enter fullscreen mode Exit fullscreen mode

I think the next step is some of this could be bundled up into helper classes to make it easier, but I think it might be good for the default settings elements to go into the Umbraco.Core and the SmidgeHelper methods to go into Smidge then this could work for everyone 😄

Top comments (1)

Collapse
 
wvvirginiarochester profile image
WV-VirginiaRochester

Hi Kevin, thanks for this post. I'm upgrading a current Umbraco 8 site to Umbraco 9 and I'm trying to get Smidge working for the backend in the way we used ClientDependency to register our bespoke data editors in Umbraco. For example in the attached image, we registered our .js, .html and .cs files in a folder called 'Chores' in the DataEditor folder in App_Plugins in Umbraco8. Can we do something similar with Smidge for the backend in Umbraco9?
Image description