Javascript bundling and module loading - javascript

I've recently been thrown in to clean up a project which has like 45-50 individual .js javascript files. I wonder what the best approach would be to decrease the loading size of them all. Just concatenate all files into one with npm or gulp? Install some module loader? webpack?

If you're already concatenating, minifying, and uglifying and you don't want all the files to be loaded on all the pages due to a monolithic bundle, you might be looking for something like Webpack's Commons Chunk Plugin.
This plugin walks down the tree of dependencies for each endpoint defined in your Webpack.config file and determines which modules are required across all pages. It then breaks the code into two bundles, a "common" bundle containing the modules that every page requires, which you must load with a script tag on each page:
<script src="commons.js" charset="utf-8"></script>
And an endpoint bundle for each individual page that you reference normally in a script tag placed after the commons script tag:
<script src="specificpage.bundle.js" charset="utf-8"></script>
The result is that an individual page will not have to load modules that will only ever be used on other pages.
Again, this is a Webpack plugin. I don't know if this functionality is available as a Gulp plugin, because it must have knowledge of all endpoints in order to determine which dependencies are common to them all.

I redirect you to the very good https://github.com/thedaviddias/Front-End-Checklist
In particular the following advises:
JavaScript Inline: High You don't have any JavaScript code inline
(mixed with your HTML code).
Concatenation: High JavaScript files
are concatenated.
Minification: High JavaScript files are minified (you can add the .min suffix).
You can accomplish this with a package manager such as gulp, grunt or webpack (for the most famous ones). You just need to choose what you prefer to use.
If you consider webpack, You can start with my very simple (but understanding) starter: https://github.com/dfa1234/snippets-starter

There's no much thing that you can do, basically is:
Concatenation - https://www.npmjs.com/package/gulp-concat
Minification - https://www.npmjs.com/package/gulp-minify
Instead of creating all those scripts, you can get something to re-use on yeoman, f.e. the Fountain, so it will reduce a lot of time just typing procedural code for doing the concatenation/minification.
Also if you can use some lazy load (like RequireJS or some frameworks have support to lazy load the module, like Angular) that will improve the performance of your aplication
EDIT:
If you want even more performance, you can install some compression tool in your server, for example this one for NodeJS https://www.npmjs.com/package/compression

I'm my personal opinion, if you have time, the best approach would be to read and understand the purpose of the project. Then plan a proper refactor. You are not fixing anything with concatenating, this is just a deployment step.
You should analyze which technologies are being used and if you want to maintain this code, in the long run, make a proper refactor into a much more modern stack, maybe you can take a seed project with ES6, webpack, Babel... and create a proper repository well maintained with proper modularity and dependencies resolution.
Once you have that, decreasing the load its just about adding proper tools in build time (babel, webpack, etc).
You would like to add some unit tests and continue working properly :)

Related

Splitting my Webpack bundle is causing JS issues

I'm using Webpack in a fairly simple, straightforward way that bundles together a few JS and TS files into one bundle, and it works well on my site.
However, I want to split the current bundle into smaller bundles, as I get both a warning when I build the bundle due to it's size, and I get warnings running Lighthouse audits in browser that I should reduce the file size of my bundle.js file.
The simplest solution in my mind is to split my current bundle into 4 parts, i.e. bundle1.min.js, bundle2.min.js, etc... Then I just serve the bundles consecutively.
The problem is splitting and serving my bundle this way is breaking other JS on my page. For example a function defined in bundle1 and called in a different JS file no longer works, unless I remove all the other bundle.js files. It seems that only the most recently loaded bundle file works.
Is there a better approach to get smaller bundles, and make sure that all bundles work correctly?
Route-based code splitting is quite popular because each page/route usually has a small subset of components on it.
The guide can be found here (for React)
A little embarrassed, looks like this was just a scoping issue with a dependency in one bundle breaking code in another by being absent. Reorganizing my bundles so dependencies are present where needed. Ai ya.

How to integrate Webpack in a multi-page PHP application

I'm working on an old Codeigniter website where the Javascript codebase is messy and poorly structured and I would like to use Webback to manage the scripts. My goal would be start using it to bundle the code I have the way it is, and gradually refactoring it to make use of modules and imports.
At the moment I'm using Gulp on development (but mostly to minify the files) and Carabiner (a Codeigniter library) to insert the scripts in the views.
The scripts, which are all written as IIFEs are not bundled, so in every controller function I have an array of the scripts needed in that page. For example:
public function homepage()
{
$this->carabiner->js([
['libraryThatIOnlyNeedHere.min.js'],
['myscript1.js'],
['myscript2.js'],
['myscript3.js'],
]);
I would like to use Webpack to create a series of bundles so that I end up loading maximum two files on every page: one for the libraries and one for my scripts.
All the practical examples I've seen with Webpack, though, are for Single Page Applications where it's quite easy to bundle everything together.
What would be the best approach in my case? Considering that the code is still not ready to properly use modules and imports, shall I create many entry points in the Webpack configuration file, possibly one for every page and list every script needed in that page?
Main idea behind webpack is to build modules graph from provided sources and then to combine it into bundles. If your code doesn't have explicit dependencies - it may be good idea to start with creating a module from every file using any of available approaches (AMD, CommonJS, etc). You will need to create module identifiers and define dependencies for every module. It may be worth to read this article for example.
As intermediate step you may want to use some loader like Require.JS to load your modularized code.
Until this step will be done - there is not much use of Webpack.

why use module loading in the backend?

I have been trying to find an answer why webpack cares about module loading on the backend. Is there a reason why this may be needed?
Does JSPM do backend module loading as well?
Assuming your first question is along the lines of "Why pre-bundle JavaScript code for the client?"
There are many reasons for module bundling. A few:
Simple file aggregation: Bundling related code makes many tasks easier / more intuitive. Instead of deploying a large directory tree of files after bundling those files may instead be a single bundle file.
Loading Performance: Individually loading dependencies that are in separate files on the client side has historically been very slow. Each file must be parsed and evaluated separately and depending on the module system used may incur considerable delay while waiting for dependencies to be discovered and loaded.
Media type abstraction: Bundlers typically allow methods for bundling non-JavaScript content. Including assets like images and stylesheets is convenient and encourages explicit/clear dependency by parts of your application that use them.
Tree shaking: By analyzing dependency among modules and code it's often possible to selectively include what is needed by the application and reduce the size of your overall code base. This isn't inherently a characteristic of bundling, but is commonly done because there is some notion of a build step.
Regarding your second question:
JSPM does offer this functionality. This is can be done on the command line with the jspm bundle command.
The simplest reason is for performance. Opening a file and closing a file is a slower processes than the time it takes to send the file (stream) so the fewer open and close file operations the faster the server can send the files requested. So by reducing the number of files that make up a javascript/web project the faster the browser will finish getting the files and start processing them for the end user.
The things that a good build process can do for you web project can go beyond simply adding all your Js files together as tools such as JSPM can also bring css and html files together into one bundle.js file further adding to your end-user experience.

How to get r.js optimizer to combine all modules in a project into one file?

From experimenting with the r.js optimizer, it seems that there is no way for your final index.html file to just reference a single script and never make any async calls to other scripts during the lifetime of a user's session (unless they reload the page of course). From my experience, it looks like it creates a bunch of combined groups of optimized files which can be referenced when needed? This seems counterintuitive to most combine scripts where you end up with just one combined/optimized js file that is in the correct order. Can anyone help explain my issue?
Yeah, that's how r.js works, it optimize your dependencies into one or multiple file (you'd use include option to get all your file togheter).
Although, this build will keep require.js script file out of the build. But, after the build, you can combine require.js (or minimal AMD implementation like almond.js) at the top of your builded file and it will all work mostly fine (some problem may occur depending on how you bootstrap your app, but most of the time those issues are pretty easy to resolve).
To combine the files easily, you can use tools like grunt.js (I really recommend it to you as it can do much more and is really a must have in frontend developpement workflow). If you work with backbone app, you can checkout (Backbone Boilerplate)[https://github.com/tbranyen/backbone-boilerplate] and their grunt implementation.

Javascript compiler / dependency manager?

I have many JS files. Some of them depend on each other. Many of them depend on jQuery.
I need tool that can accept one file as parameter, fetch all its dependencies transitively and compile them into one file in proper order (based on dependencies)
Dependency information not always available inside files itself, so it would be nice to have it somewhere outside (xml file? folder structure?)
I've heard about Yahoo JS compiler, closure and so on, but I am not sure they do what I need.
Look: I have module "CustomerPage". It sould include "validation.js" and "gui.js". Both require jquery.js. And "gui.js" also requires "myFunctions.js".
I want some ant task or some script that would generate "CustomerPage.js" as result of all that files.
Tool should check dependency order, prevent double including and so on.
My project could have around 500 js files, how could I live with out of this tool?
People says "use GWT", but I need plain JS.
You might want to look at one of the AMD-style module loaders, such as RequireJS. Some of these can do what you want for precompiling, and can run in a development mode which makes it easier to debug by including all the files directly.

Categories