I'm trying to solve a perceived problem with JavaScript and its use on our site(s). I don't think I'm the only one who perceives this problem. I'm not sure how to describe it in a title (or a search term, so, although I've done a bit of searching for information about this), so I thought I'd talk about it with the knowledgeable folks here.

Firstly, we're not a "JavaScript" site. Our Pages are loaded from the server and generated by PHP; they are not large one-page-apps.

However, like all of us, we need functionality within the browser, and the ability to run widgets provided by people like Google, FaceBook, etc. We all know that we can't ignore JavaScript.

My problem revolves around making sure the small amount of available manhours in our IT department can keep up with JS development on our site(s) without breaking currently implemented JS; as things continue and we continually add JS code to pages, my nervousness about this grows; there are so many things in the global scope. So many dependencies on scripts from other locations. So many unknowns in the end-user's browser.

I hatched a plan to create a global object that would envelop a large number of these various methods and properties, pulling in dependencies, etc...

And the real value to us: One_File_To_Rule_Them_All.js which is well-organized, well-known to staff, studied, documented, etc.

A bit of work has ensued to create this; I'm preparing to test it on our site.

But we have chicken-and-egg problems. So many dependencies on jQuery ... how can it be wrapped? Ditto the google object, Scriptaculous (legacy code) and so on.

The problem really seems to be that there are, as we all know, things that expect to be placed in the document <head> and things that are better left until later, specifically until the DOM is loaded.

We had hoped to simply include "ourfile.js" in the HEAD of every page on the site and remove all other script tags except calls to our objects methods:

<head><title>My Nice Site</title>
<script src = "/js/onefile.js"></script>
<script>
OneFile.GoogleAnalytics();
</script>
</head>
<body>
<div id = "google_translate_element">
<script>
OneFile.GoogleTranslateAddElement();
OneFile.GoogleTranslateElementInit();
</script>
</div>
</body>
</html>

But we're having the chicken/egg issues I've mentioned, and I'm now not sure this was even a good idea.

I hope you at least understand what I'm trying to do. Has anyone tried this sort of thing? Is it Not_A_Problem(tm), or just something you've not bothered to worry about? Is it something you've solved?

And, if so, how did you solve it?

Thanks in advance for what I'm quite sure will be an enlightening discussion! Have a great day.

    Could this be a use case for migrating to something like TypeScript, which presumably(?) through its enhanced class/object paradigm could help control scope and dependencies?

      Could the job of managing dependencies be brought under PHP's control in some way? Some kind of configuration database where you say "I want to use FooJS and BarJS on this page" and it comes back with a list of JS file inclusions and snippets to be inserted in the head and at the bottom.

        I use requirejs to manage dependencies and couldn't be happier. It adds a little boilerplate to every file, but makes it really easy get all the right files in place. Additionally, it makes it really easy to create uglified/minified files for serving in production.

          Weedpacket;11053205 wrote:

          Could the job of managing dependencies be brought under PHP's control in some way? Some kind of configuration database where you say "I want to use FooJS and BarJS on this page" and it comes back with a list of JS file inclusions and snippets to be inserted in the head and at the bottom.

          That's a good and worthy idea. I have to admit being a little tied up in wanting to improve my JS foo and not really considering this line of inquiry (which was actually known to me as it was a feature of the software that I have mostly replaced at this point).

          The one issue that I foresee with this idea is that I was also trying to make "one_file_to_rule_them_all.js" for helping simplify page rendering and load times. That might still be addressable with this paradigm ... I'll have to cogitate on that a bit.

          Derokorian;11053207 wrote:

          I use requirejs to manage dependencies and couldn't be happier. It adds a little boilerplate to every file, but makes it really easy get all the right files in place. Additionally, it makes it really easy to create uglified/minified files for serving in production.

          Hmm, that looks like a similar idea to what I was trying to do. Might I ask, how much boilerplate, and does it need to be changed/updated much over time?

          Also, I might need to expound further on the problems I'm encountering. It's not so much about getting the code injected into the HTML output. It's about the JS actually working (perhaps too well?). The big issue right now is that I have a wrapper around jQuery. I call it, and then I create some other functions that use it. Apparently it's too fast; the functions can't use jQuery to initialize themselves. However, after the page is loaded, jQuery seems to be available. It's a little frustrating.

            dalecosp;11053213 wrote:

            Hmm, that looks like a similar idea to what I was trying to do. Might I ask, how much boilerplate, and does it need to be changed/updated much over time?

            Also, I might need to expound further on the problems I'm encountering. It's not so much about getting the code injected into the HTML output. It's about the JS actually working (perhaps too well?). The big issue right now is that I have a wrapper around jQuery. I call it, and then I create some other functions that use it. Apparently it's too fast; the functions can't use jQuery to initialize themselves. However, after the page is loaded, jQuery seems to be available. It's a little frustrating.

            Not much boilerplate, or none at all depending on the file (dependencies for third party files generally go in the configuration shim). I've never had to update the dependencies of a file after getting it working, so I would say it doesn't change much if at all over time. Requirejs also makes sure things are loaded in the correct order. For example, you would say that your function file(s) depends on your jQuery wrapper file, and requirejs won't even make the request for the functions until after the jQuery finishes.

            This is a valid example from my site:

            define([
                'app',
                'filters',
                'toasts',
                'blog/model'
            ], function (app) {
               // bunch of angular code here
            });

            Basically this is saying, for this file to work properly, I must have my app loaded, as well as filters, toasts and the model for the blog module.

            Its also super simple to minify to a single file for production with requirejs:

            r.js -o public/scripts/build.js out=public/scripts/main-build.js

            You can also define dependencies for third party scripts in the config file, like so:

            require.config({
                baseUrl: '/scripts',
                paths: {
                    'angularjs': 'lib/angular-1.4.2.min',
                    'jquery': 'lib/jquery-1.11.1.min',
                    'bootstrap': 'lib/bootstrap-3.3.4.min',
                    'modernizr': 'lib/modernizr-2.6.2-respond-1.1.0.min',
                    'ui-router': 'lib/angular-ui-router-0.2.13.min'
                },
                shim: {
                    'angularjs': {
                        exports: 'angular',
                        deps: [
                            'jquery',
                            'bootstrap'
                        ]
                    },
                    'bootstrap': {
                        deps: [
                            'jquery',
                            'modernizr'
                        ]
                    },
                    'ui-router': {
                        deps: [
                            'angularjs'
                        ]
                    }
                }
            });

            So basically what's going on here is, baseUrl is where my scripts are located relative to the site's root. Paths, give me friendlier names for files (jquery, instead of typing lib/jquery-1.11.1.min every where I depend on jquery) and allows for easy version updates (only one file to change the version in the file name). Finally the shim section, this is where third-party scripts are listed for their dependencies on other scripts (third-party or otherwise), for example, we can see that angular needs jquery and bootstrap.

              5 days later

              So, is this what you used for your Personal Home Page at De--------.com? I probably need to go that route if so....

                dalecosp;11053283 wrote:

                So, is this what you used for your Personal Home Page at De--------.com? I probably need to go that route if so....

                Yes, it is. All those examples are from my personal site (otherwise I wouldn't be allowed to post them publicly). But its also what I used at my last job (where I really learned to utilize requirejs well), and we had (when I left) over 3500 js files, which is far more than the couple dozen my site has 😛

                  I use PHP to serve the relevant files but I've always felt it's cludgey.. and I see every other site seeming to throw everything at the wall in one go.
                  Of course I have lots of PHP variables that need to be made available to the JS.
                  At least we all know not to put too much dependence on JS, unlike say Magento who were found to be only validating a key email with JS.

                  There has to be a better controlled way it's true..

                    cretaceous;11053341 wrote:

                    I use PHP to serve the relevant files but I've always felt it's cludgey.. and I see every other site seeming to throw everything at the wall in one go.
                    Of course I have lots of PHP variables that need to be made available to the JS.
                    At least we all know not to put too much dependence on JS, unlike say Magento who were found to be only validating a key email with JS.

                    There has to be a better controlled way it's true..

                    Yeah, that's why I use require, and I also favor SPAs or small modular SPAs. So I tend to think of it as: I have a front end application written in javascript that needs to interact with my hosted application, I'll make a bunch of API calls to the other application - using the same API mechanism available publicly. ConverselyI have a server side application written in X (usually PHP) that need to accept input from an API, filter and validate it properly - and return a useful and standardized response for easy consumption by users (applications). I tend to consider them two entirely separate applications, and write them as such. This way, just as I can switch out models to interact with a different database in PHP, I can switch out models to interact with a different API in the front end.

                      10 months later

                      Well, I'm kind of sorry to have let this drop for the better part of a year. I'm still struggling with $WhatToDoAboutThis.

                      Several of you mention (esp. looking at you, Derokorian), a fairly large number of JS files in an app. What impact does this have on server performance, and page performance in the browser? We've been putting one-year "Expires" headers on images, CSS, and JS for quite some time to help the site run faster due to the resources being saved in browser caches. When I update a CSS or JS file, we stick a dated query string on it to cause end-user caches to update.

                      That's why I thought of "One JS File to rule them all" ... that ... and namespacing. I mean, pretty obvious there are going to be other scripts (advertisements, 3rd-party trackers like Google Analytics, Alexa, Hubspot, etc.). So I was going to create One Big JS File for us and put everything in a MYSITE object:

                      MYSITE = {};
                      
                      MYSITE.blah = function() {
                         return 1 + foo;
                      }
                      ....
                      //a gazillion more functions

                      What's industry Best Practice, or "standard practice" where you are right now?

                        I still use RequireJS to manage all my dependencies. The top of every file, points to each direct dependency. RequireJS looks at these and loads the files in the correct order. Then for production, we use r.js to turn it into a single file, and we name that file as a standard name with an md5(file_contents) attached to the end. (like main-79054025255fb1a26e4bc422aef54eb4.js) the md5 part is for clearing cache as you mentioned. This is also very performant because you just load ONE file from the server, a single request. You can even put it on a CDN instead of coming straight from your primary web servers.

                          Derokorian;11058565 wrote:

                          I still use RequireJS to manage all my dependencies. The top of every file, points to each direct dependency. RequireJS looks at these and loads the files in the correct order. Then for production, we use r.js to turn it into a single file, and we name that file as a standard name with an md5(file_contents) attached to the end. (like main-79054025255fb1a26e4bc422aef54eb4.js) the md5 part is for clearing cache as you mentioned. This is also very performant because you just load ONE file from the server, a single request. You can even put it on a CDN instead of coming straight from your primary web servers.

                          Thanks ... so, "r.js" is your shorthand for require.js, yes? I assume it perhaps handles minification too? And does it "turn it into a single file" by default, or easily configurable option? How do you use it in the sandbox(es)? Similar fashion except for the "single file"?

                            And, to not burden you further, I'm answering most of my questions by RTFM (although it seems really short, heheh)....

                              dalecosp;11058573 wrote:

                              Thanks ... so, "r.js" is your shorthand for require.js, yes? I assume it perhaps handles minification too? And does it "turn it into a single file" by default, or easily configurable option? How do you use it in the sandbox(es)? Similar fashion except for the "single file"?

                              In my template, I have 3 files included, require.min.js, config.js (application specific configuration) and main.js (this exists to bootstrap my Angular application, and may not always be needed). When I build for production, I replace these 3 tages with a single tag for the built file. That's it.

                              So in stage / sandbox / whatever you wanna call it, you get all the files pulled individually. If you watch the network tab on dev tools you can see tons of files flying in. Then I run the command from my post above from 01-20-2016 to create a single file, and a sed command to replace the script tags. Again, this is a scripted process, I'm not actually running any commands besides "cli build -e production -b master".

                              r.js is the node package for requirejs that gives command line tools.

                                Write a Reply...