<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://shazwazza.com/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Shazwazza</title>
    <link>https://shazwazza.com/</link>
    <description>My blog which is pretty much just all about coding</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <image>
      <url>/media/0libq25y/frog.png?rmode=max&amp;v=1da0e911f4e6890</url>
      <title>Shazwazza</title>
      <link>https://shazwazza.com/</link>
    </image>
    <item>
      <guid isPermaLink="false">1310</guid>
      <link>https://shazwazza.com/post/smidge-plus-nuglify-bundling-minification-and-source-maps/</link>
      <category>Web Development</category>
      <title>Smidge + Nuglify bundling, minification and source maps</title>
      <description>&lt;p&gt;Smidge &lt;strong&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/releases/tag/v2.0.0-rtm" target="_blank"&gt;2.0.0 RTM&lt;/a&gt;&lt;/strong&gt; is finally here!&lt;/p&gt;
&lt;p&gt;What is Smidge? Smidge is a lightweight &lt;u&gt;runtime &lt;/u&gt;bundling library (&lt;em&gt;CSS/JavaScript file minification, combination, compression&lt;/em&gt;) for ASP.NET Core -  &lt;a rel="noopener noreferrer" href="/post/smidge-20-alpha-is-out/" target="_blank"&gt;&lt;em&gt;Here’s some more background info on Smidge&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s plenty of great &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/milestone/5" target="_blank"&gt;new features in the version 2.0.0&lt;/a&gt; , but in this post I’ll just highlight a couple of fun ones….&lt;/p&gt;
&lt;h2&gt;Nuglify and source maps&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xoofx/NUglify" target="_blank"&gt;Nuglify&lt;/a&gt; if an ASP.NET Core port of the old &lt;a rel="noopener noreferrer" href="http://ajaxmin.codeplex.com/" target="_blank"&gt;AjaxMin&lt;/a&gt; library and this works very nicely with Smidge too. By default Smidge uses an updated version of &lt;a rel="noopener noreferrer" href="http://www.crockford.com/javascript/jsmin.html" target="_blank"&gt;JsMin&lt;/a&gt; that I maintain called &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/JsMinSharp" target="_blank"&gt;JsMinSharp&lt;/a&gt; for it’s JavaScript minification engine. JsMin works fairly well, it’s primary feature is that it’s &lt;em&gt;fast &lt;/em&gt;because it doesn’t come with any bells and whistles and doesn’t produce a &lt;a rel="noopener noreferrer" href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank"&gt;Syntax Tree&lt;/a&gt;. Nuglify on the other hand does produce a Syntax Tree which gives it loads of control over how the minification is done so that it can produce much smaller files, has the ability to rename/reduce parts of the JS and to produce &lt;a rel="noopener noreferrer" href="https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/" target="_blank"&gt;source maps&lt;/a&gt;. The downfall of all this control is that it becomes much slower but Smidge is smart enough to cache processed files on the server in a persistent state so it won’t re-process your files if it doesn’t need to.&lt;/p&gt;
&lt;p&gt;Here’s a quick benchmark of JsMin vs Nuglify to minify jQuery using the default options (and no source map). As you can see JsMin is substantially faster and is far better for memory but Nuglify can reduce the file size quite a lot more &lt;em&gt;(smaller Minified % is better)&lt;/em&gt;&lt;/p&gt;
&lt;table border="0" width="700" style="box-sizing: border-box; overflow: auto; margin-bottom: 16px; white-space: normal; word-spacing: 0px; margin-top: 0px; border-collapse: collapse; text-transform: none; border-spacing: 0px; orphans: 2; widows: 2; display: block; letter-spacing: normal; background-color: #ffffff; text-indent: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;"&gt;
&lt;thead&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #ffffff;"&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Method&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Median&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;StdDev&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Scaled&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Scaled-SD&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Minified %&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 0&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 1&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 2&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Bytes Allocated/Op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #ffffff;"&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;JsMin&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;10.2008 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.3102 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;1.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;51.75%&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;155,624.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #f8f8f8;"&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Nuglify&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;69.0778 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.0180 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;6.72&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.16&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;32.71%&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;53.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;22.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;15.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;4,837,313.07&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Source maps you say? JsMin isn’t all that smart so it can’t produce source maps (&lt;em&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/issues/57" target="_blank"&gt;yet&lt;/a&gt;&lt;/em&gt;) but Nuglify certainly can and by default the &lt;em&gt;Smidge.Nuglify&lt;/em&gt; package has this turned on by default. Here’s how you can get this working:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Follow the super easy Smidge &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge#quick-start" target="_blank"&gt;quick start installation guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the Smidge.Nuglify package
&lt;div&gt;
&lt;div class="nuget-badge"&gt;
&lt;p&gt;&lt;code&gt;PM&amp;gt; Install-Package Smidge.Nuglify&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Add Smidge Nuglify to your services: &lt;code&gt;services.AddSmidgeNuglify();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use Smidge Nuglify in your Configure method: &lt;code&gt;app.UseSmidgeNuglify();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace JsMin  with Nuglify for the default pipeline:
&lt;pre&gt;&lt;code class="language-csharp"&gt;services.Configure(opt =&amp;gt;
{
    opt.PipelineFactory.OnCreateDefault = (type, pipeline) =&amp;gt; pipeline.Replace(opt.PipelineFactory);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;That’s it! Nuglify is now the JS minifier for the default pipeline and will produce source maps. You can configure the Nuglify settings in the &lt;em&gt;AddSmidgeNuglify&lt;/em&gt; method.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now you can debug via the source maps in dev tools:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://shazwazza.com/media/articulate/windows-live-writer-smidge-nuglify_9f43-image_4.png"&gt;&lt;img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" src="https://shazwazza.com/media/articulate/windows-live-writer-smidge-nuglify_9f43-image_thumb_1.png" border="0" alt="image" title="image" width="600" height="350" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;File watching&lt;/h2&gt;
&lt;p&gt;Smidge can now watch your source files and if any changes are detected it can auto cache bust the bundle and flag for re-processing.&lt;/p&gt;
&lt;p&gt;Previous to version 2.0.0 if you were in release mode all of the bundling/minification would be active but you really just wanted to test this behavior but unfortunately it meant that if you updated a js/css file you would have to go bump the Smidge version in the config file to clear out the server side persistent cache. In 2.0.0, you can configure your bundle with different environment options for both Debug and Production. For example, perhaps in Debug mode you still want your bundles to be active so that the minification, combination, compression, etc… is still happening but you want to still actively edit files … you can easily do this! Here’s a nice fluent syntax to achieve this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;bundles.CreateJs("my-application", "~/js/site.js", "~/js/app")
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
        .ForDebug(builder =&amp;gt; builder
            .EnableCompositeProcessing()
            .EnableFileWatcher()
            .SetCacheBusterType())
        .Build()
    );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this example the “my-application” bundle will do the following when being rendered in debug:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Still process the files in the bundle and minify, combine, compress into a composite file&lt;/li&gt;
&lt;li&gt;Attach file watchers to all files in the bundle&lt;/li&gt;
&lt;li&gt;Change the cache buster for this bundle to only survive the lifespan of the current app domain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And what’s cool is that if you edit any of the source files in this bundle it will auto cache bust to a new value and re-process the bundle when it’s next requested.&lt;/p&gt;
&lt;h2&gt;Debug vs Production?&lt;/h2&gt;
&lt;p&gt;There’s a few ways that you could render assets in either debug or production mode but this is probably the easiest and uses ASP.NET Core’s environment tag helpers. Notice the debug attribute on the script/link tags and that the src/href attributes just include the bundle name … this is using Smidge’s tag helpers to define which bundle to render and if it’s in debug mode.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;environment names="Development"&amp;gt;
	&amp;lt;link rel="stylesheet" href="my-css" debug="true" /&amp;gt;
	&amp;lt;script src="my-js" debug="true"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/environment&amp;gt;

&amp;lt;environment names="Staging,Production"&amp;gt;
	&amp;lt;link rel="stylesheet" href="my-css" /&amp;gt;
	&amp;lt;script src="my-js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/environment&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Thanks!&lt;/h2&gt;
&lt;p&gt;Big thanks to &lt;a rel="noopener noreferrer" href="https://github.com/dazinator" target="_blank"&gt;@dazinator&lt;/a&gt; for all the help, recommendations, testing, feedback, etc… and for the rest of the community for filing bugs, questions, and comments. Much appreciated :)&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:27 Z</pubDate>
      <a10:updated>2023-03-23T15:08:27Z</a10:updated>
    </item>
  </channel>
</rss>