Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.


The Trouble with DNN JavaScript / CSS Minification (aka Client Dependency / Resource Management)

(Opinion) For years now 2sxc has promoted the merits of the DNN Client-Dependency-Management, and tried to use it wherever possible + recommended it in blogs. In reality, it hurt us badly. Bogdan from DNNSharp showed me a better way - so 2sxc now officially stops doing this, and recommend that you evaluate if this is important for you too.

    What is the Client Dependency Management?

    Basically it's a system in DNN which should be told what CSS / JS files the page will use, and then delivers them all in one single request. Combined, minified and zipped, from the server to the browser. It also takes care of the sequence of loading things, to ensure that the order of items works - so that jQuery is loaded before your stuff, etc. This should improve performance and reliability. So basically it does a few core things

    1. Ensure that each script is only included once (if multiple components need a script, it will only be added once)
    2. Attempt to order the scripts correctly (so that jQuery comes before your script)
    3. Attach all files into one file
    4. Do some minification / zipping
    5. Cache this combination of files

      Bundles with MANUAL Re-Build

      In the implementation, DNN will create a list of JS files used in a specific combination, bundle them in one file which is zipped and stored somewhere. This zip is then always re-used for future requests. This ZIP is never updated, unless a site-admin performs a manual step to invalidate all previous bundles - like this:

        What's wrong with it?

        There are quite a few issues with the CDM / CRM, some of them conceptual, some of them in implementation. For example, the script-ordering result is a bit random. The conceptual issues I will skip, because what hurts us as module developers is the implementation. Here's a common story:

        It starts with someone using our module and reporting a bug. The bug can be anything - like

        1. It can on the server or the client, doesn't matter
        2. The problem can be on all pages, or just on some pages - this varies from installation to installation
        3. The exception can occur in JS (because the JS was expected a different setup on the server) or it can be on the server (because the JS called something on the server, expecting a different API)
        4. Very often: the user recently updated to a newer version (but might not be aware of it)

          Browser JS not in Sync with Server

          It almost always turns out to be that the JS  in the browser is not in Sync with the installed system. This causes small differences in APIs which are called or parameters which are passed around.  So the user will update to version 08.03.05 and will experience an issue. He will assume that 08.03.05 has a bug, and never realize that this version actually works, but that his browser is still running the JS of 08.02.03.

          We will always waste our users time and ours to try to figure it out. The solution is usually to get the user to manually invalidate his previous bundles. This is terrible! Upgrading should be simple and just work - but it isn't.

          This is BTW by far not the only really bad issue, and there are ways to work around each of them. But at the end of the day we end up spending a lot of time working around features which should have helped, but actually don't.

            Should we just fix the DNN Client Resource Management?

            Edit: I just heard that it is fixed in DNN 8.0.1 :)
            Yes we should - but it wouldn't help anybody developing modules. If (a) the community fixes it (and yes, someone should) and (b) the fix actually addresses all the right problems and (c) it actually makes it into DNN without too many people voicing alternate ideas, then it might probably end up in a distribution of DNN within 3-6 months, and after some fixes from real-life projects, really, really work one release later (in about 1 year from now).  

            So if we do fix it in DNN, you can expect a working solution in a real distribution in about 1 year, meaning the customers would use it in published projects in about 1-2 years (yes, this is true!), and all previous versions 7+ would never, ever benefit from the change. So if you want a solution to work for real customers, than you can't wait for a fix.

              The Savior: ASP.net Page.ClientScript

              Since I was so focused on solving things the DNN way, I completely missed the fact that ASP.net also has a solution. Bogdan from DNN-Sharp showed it to me, and said their support-frequency dropped by more than 50% after this change. It doesn't do as much as the DNN solution (yea!) but reliably. Actually all it does is prevent multiple files from being added. This is very, very important, because loading a JS twice can have serious side-effects like double execution and timing issues. 

              Here's some code as 2sxc does it from now on (you see that it also appends the version number, which will also ensure that the browser will load a new version after an upgrade):

              Registering a Script using ASP.net

                public static void RegisterJs(Page page, string version, string path)
                {
                    var url = string.Format("{0}{1}v={2}", path, path.IndexOf('?') > 0 ? '&' : '?', version);
                    page.ClientScript.RegisterClientScriptInclude(typeof(Page), path, url);
                }

                  What's Missing in Page.ClientScript

                  Some things are missing in this, so bear with me while I tell you what is left to do:

                  1. Ensure the script is only included 1x - check!
                  2. Order the scripts correctly: nope, won't happen. So you should never use this for global, dnn-shared scripts like jQuery, best leave those to DNN to handle them. But it's perfect for everything that comes from you.
                  3. Merging into one file: nope, but that's a good thing. Use Gulp/Grunt instead, it's much, much better.
                  4. Minification: nope, but that's a good thing. Use Gulp/Grunt instead, it's much, much better.
                  5. Zipping: nope, but again a good thing. Use the IIS functionality instead, it's (imho) better.
                  6. Caching: not necessary; the browser can cache JS very, very well - and the server doesn't need an additonal cache

                  What about CSS?

                  Sorry, not supported. You are either stuck with the DNN-Mechanism, with multiple-includes or with some self-handcrafted solution. BUT you should still use Gulp/Grunt to better control the minification, again delivering a much better solution.

                  Rounding it Up

                  For us, this change took care of many, many support issues - and probably took care of many more issues that were never reported, but left users frustrated. Maybe it fits your solution as well, maybe not. And if you have better solutions, or something I was not aware of which would be way better - then share it - would love to hear from you.

                  Love from Switzerland,
                  Daniel


                  Daniel Mettler grew up in the jungles of Indonesia and is founder and CEO of 2sic internet solutions in Switzerland and Liechtenstein, an 20-head web specialist with over 800 DNN projects since 1999. He is also chief architect of 2sxc (see forge), an open source module for creating attractive content and DNN Apps.



                  Read more posts by Daniel Mettler

                  Comments

                  Brian Dukes
                  DNN 8.0.1 fixes the issue of resources not updating after module upgrades (see DNN-8048, pull request at https://github.com/dnnsoftware/Dnn.Platform/pull/1315), so it's certainly an issue to be aware of, but not broken forever.
                  Brian Dukes Wednesday, April 13, 2016 10:58 AM (link)
                  Daniel Mettler
                  @Brian - that is awesome news :)
                  Daniel Mettler Wednesday, April 13, 2016 11:39 AM (link)

                  Comment Form

                  Only registered users may post comments.

                  NewsArchives


                  Aderson Oliveira (22)
                  Alec Whittington (11)
                  Alessandra Daniels (3)
                  Alex Shirley (10)
                  Andrew Hoefling (3)
                  Andrew Nurse (30)
                  Andy Tryba (1)
                  Anthony Glenwright (5)
                  Antonio Chagoury (28)
                  Ash Prasad (37)
                  Ben Schmidt (1)
                  Benjamin Hermann (25)
                  Benoit Sarton (9)
                  Beth Firebaugh (12)
                  Bill Walker (36)
                  Bob Kruger (5)
                  Bogdan Litescu (1)
                  Brian Dukes (2)
                  Brice Snow (1)
                  Bruce Chapman (20)
                  Bryan Andrews (1)
                  cathal connolly (55)
                  Charles Nurse (163)
                  Chris Hammond (213)
                  Chris Paterra (55)
                  Clint Patterson (108)
                  Cuong Dang (21)
                  Daniel Bartholomew (2)
                  Daniel Mettler (181)
                  Daniel Valadas (48)
                  Dave Buckner (2)
                  David Poindexter (12)
                  David Rodriguez (3)
                  Dennis Shiao (1)
                  Doug Howell (11)
                  Erik van Ballegoij (30)
                  Ernst Peter Tamminga (80)
                  Francisco Perez Andres (17)
                  Geoff Barlow (12)
                  George Alatrash (12)
                  Gifford Watkins (3)
                  Gilles Le Pigocher (3)
                  Ian Robinson (7)
                  Israel Martinez (17)
                  Jan Blomquist (2)
                  Jan Jonas (3)
                  Jaspreet Bhatia (1)
                  Jenni Merrifield (6)
                  Joe Brinkman (274)
                  John Mitchell (1)
                  Jon Henning (14)
                  Jonathan Sheely (4)
                  Jordan Coopersmith (1)
                  Joseph Craig (2)
                  Kan Ma (1)
                  Keivan Beigi (3)
                  Kelly Ford (4)
                  Ken Grierson (10)
                  Kevin Schreiner (6)
                  Leigh Pointer (31)
                  Lorraine Young (60)
                  Malik Khan (1)
                  Matt Rutledge (2)
                  Matthias Schlomann (16)
                  Mauricio Márquez (5)
                  Michael Doxsey (7)
                  Michael Tobisch (3)
                  Michael Washington (202)
                  Miguel Gatmaytan (3)
                  Mike Horton (19)
                  Mitchel Sellers (40)
                  Nathan Rover (3)
                  Navin V Nagiah (14)
                  Néstor Sánchez (31)
                  Nik Kalyani (14)
                  Oliver Hine (1)
                  Patricio F. Salinas (1)
                  Patrick Ryan (1)
                  Peter Donker (54)
                  Philip Beadle (135)
                  Philipp Becker (4)
                  Richard Dumas (22)
                  Robert J Collins (5)
                  Roger Selwyn (8)
                  Ruben Lopez (1)
                  Ryan Martinez (1)
                  Sacha Trauwaen (1)
                  Salar Golestanian (4)
                  Sanjay Mehrotra (9)
                  Scott McCulloch (1)
                  Scott Schlesier (11)
                  Scott Wilkinson (3)
                  Scott Willhite (97)
                  Sebastian Leupold (80)
                  Shaun Walker (237)
                  Shawn Mehaffie (17)
                  Stefan Cullmann (12)
                  Stefan Kamphuis (12)
                  Steve Fabian (31)
                  Steven Fisher (1)
                  Tony Henrich (3)
                  Torsten Weggen (3)
                  Tycho de Waard (4)
                  Vicenç Masanas (27)
                  Vincent Nguyen (3)
                  Vitaly Kozadayev (6)
                  Will Morgenweck (40)
                  Will Strohl (180)
                  William Severance (5)
                  What is Liquid Content?
                  Find Out
                  What is Liquid Content?
                  Find Out
                  What is Liquid Content?
                  Find Out