Splitting my Webpack bundle is causing JS issues - javascript

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.

Related

How to reduce unused JavaScript for next js application? [duplicate]

I have a project on Next.js framework and the problem is that First Load JS shared by all pages is rather heavy.
I want to know what possible aspects I can take into consideration to reduce it and also know if I'm doing something wrongly.
my next js version : ^10.0.3
information relating to pages while building :
I would suggest installing #next/bundle-analyzer to get a better idea of what dependencies you're importing and which ones are contributing to that file size. This can help in identifying any unused or unnecessary libraries that could potentially be removed.
You can also look into using code splitting to reduce the bundle for the initial load of the application. This can be achieve by lazy loading code using dynamic import() and/or next/dynamic.
Furthermore, Next.js also mentions in their documentation other tools you can use to understand how much a dependency can add to your bundle.
(...) you can use the following tools to understand what is included inside each JavaScript bundle:
Import Cost – Display the size of the imported package inside VSCode.
Package Phobia – Find the cost of adding a new dev dependency to your project.
Bundle Phobia - Analyze how much a dependency can increase bundle sizes.
Webpack Bundle Analyzer – Visualize size of webpack output files with an interactive, zoomable treemap.
bundlejs - An online tool to quickly bundle & minify your projects, while viewing the compressed gzip/brotli bundle size, all running locally on your browser.
— Next.js, Going to Production, Reducing JavaScript Size

Javascript bundling and module loading

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 :)

Excluding less-loader from webpack bundles

I'm using Webpack to compile my JavaScript bundles and am very happy with it. I'm also using it to compile my LESS files to CSS via the ExtractTextPlugin which is also working really well. I've started looking into the end size of the bundle and it's makeup and have found something I'd like to fix:
less-loader is taking up 9.9% of the bundle size. That seems a lot in and of itself, however what really strikes me is that I don't think I really need it in the bundle at all. I've already extracted the CSS as it's own file and don't do any require('./component.less') anywhere in my JavaScript modules.
Is there a way of asking webpack to exclude it that won't ruin the less -> css compilation?
With ExtractTextPlugin, your built style sources do not become a part of the resulting JS bundle. They'll rest in the output directory and unless you explicitly reference the files, they will not be included in the document.
I'm assuming the tool for analysis that you're using includes all outputs of the compilation as being part of "the bundle".
It seems an error in webpack-visualizer.
Open node_modules/less-loader -> index.js, take any string from it (I use loaderUtils.parseQuery) and search for it in your bundle.
I found nothing, so seems loader not included.

How to import/merge js files based on references

In my MVC 6 app, as a replacement for the older js/css bundling & minification-system, I want to produce 1 javascript file that I can reference in my HTML. This javascript file is page/action-specific so I can't just concat all .js files in a folder.
With CSS (using LESS) I already managed to do this by using #import, the created .css file will then be a combination of the original .less file plus all the imports merged into 1 file. Now I'm trying to do the same with my .js files.
In GULP I can easily minify each seperate file, and place them in the correct folders, but I don't know how to merge them with the right files. I dont want to create a gulp task for each file/js telling what to concat.
I thought about using TypeScript to reference other js files and then compiling them with GULP to one file but this seems a bit harder. I'm open to other frameworks that can manage this as well.
In typescript using ///reference or import module doesn't actually result in an import when compiling like it does with LESS.
So for example, consider the following js or typescript-structure
scripts/common/master.js (or .ts etc.)
scripts/maincontroller/index.js (uses master.js)
scripts/maincontroller/support.js (uses master.js)
desired result after compile/merge/concat with gulp:
wwwroot/js/common/master.js (unchanged because nothing referenced)
wwwroot/js/maincontroller/index.js (concat with master.js)
wwwroot/js/maincontroller/support.js (concat with master.js)
This is an interesting design. It actually means that I don't benefit as much from my browser caching, because I end up downloading master.js three times (but in three different files) - and that is just based on the three files in your example.
If you have a large number of files, keep everything as individual files and use a module loader, such as RequireJS. This way, master.js is cached after the first page and they only need to load index.js on the next page (and so on).
If you don't have a large number of files, bundle them into a single file and load it late in the page.
GO to solution explorer and right click on your project and click add references.
Then go and browse your references files. :)
sry for bad english!
Found a way to achieve this by using http://browserify.org/ with GULP. I can use 'require('master.js')' in my index.js and browserify will concat the 2 files together. Not the easiest task but it seems to work as desired.

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.

Categories