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
Related
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.
This relates to an AngularJS application, originally built using yo angular-fullstack with JS scripting (not ts). Functionally fine, but hitting performance UX issues.
My production deployment is to AWS ElasticBeanstalk nano instances, which probably isn't helping but I get the impression from reading up that my {app|polyfill|vendor}bundles are too big.
Homework done - biblio and webpack.config.plugins at end.
Even with all of the above plus 'lessons learned' from wiser souls than me (see biblio) included in my project, I'm still seeing 'big' warnings from webpack and large, whole-package bundles in the webpack-bundle-analyzer output:
polyfills.66cd88606235a4586eb1.js.gz 25.8 kB [emitted]
app.66cd88606235a4586eb1.js.gz 48.8 kB [emitted]
vendor.66cd88606235a4586eb1.js.gz 319 kB [emitted] [big]
../client/index.html 4.77 kB [emitted]
I don't think my app is that complicated. 10-ish components on 4 views, one chart (angular-chart.js).
Here are my questions:
various modules appear to be bundled whole (e.g. angular 1.23MB, lodash 528KB, ...) For example, I've changed all of my own imports to specific lodash functions/modules, but the overall lodash library is still being bundled. Does that mean that one of my dependencies (or one nested further down is pulling it in, or am I missing something?
I think I can change my import module from 'angular'; statements to something more specific like import ... from '#angluar/core'; but all the documentation seems to imply that I'd have to upgrade the whole app to Angular5 to do that - am I missing something? (Said another way, I can't find beginner-friendly documentation on angular2 '#angular/core'.)
the angular-cli seems to be for new ng inited projects, so I think it's production shrinking and tree-shaking features aren't available to me unless I upgrade/restructure my project - is that correct?
are the bundles that webpack injects into index.html the gzipped ones? Not sure when/how they get used (if at all).
I'm configuring and invoking webpack from gulp - are all of the plugins I'm using (see list above) equivalent to the -p CLI option? ...or do I need to do more?
Help! What else do I need to look at or do to reduce bundle size? Do I have to go delving in node_modules/** to find out what is sucking in whole packages? What am I missing?
TIA
Biblio
Angular2 CLI huge vendor bundle: how to improve size for prod? - from which I learned about not importing whole modules when I only need a bit of it (spin-off question above)
How to use babel loader on node_modules in webpack for ES6+? - from which I learned about setting up a raft of webpack plugins to reduce, organise and compress my bundles (spin-off question above)
https://hackernoon.com/optimising-your-application-bundle-size-with-webpack-e85b00bab579 - from which I got confirmation from Google that my app is slow because the bundles are big and some more webpack config hints
https://hackernoon.com/reduce-webpack-bundle-size-for-production-880bb6b2c72f - followed all the steps, but it didn't seem to make any different to my bundle sizes
https://github.com/mgechev/angular-performance-checklist#introduction - picked as much as I could out of this without going to the 'upgrade to 5' areas.
webpack
My webpack config for production build currently includes:
config.devtool='source-map'
DefinePlugin (NODE_ENV=production)
NoEmitOnErrorsPlugin
UglifyJsPlugin with everything turned up to 11
OccurrenceOrderPlugin
AggressiveMergingPlugin
CommonsChunkPlugin
ModuleConcatenationPlugin
HashedModuleIdsPlugin
OK, so did a raft more delving and think I'm onto some fruitful tools and techniques now. In summary...
On #1 I went back to a clean, unmodified yo angular-fullstack and it turns out that my bundles weren't much different in size to the ones which came out of the box. So, I don't think that expending loads of effort trying to unpick where I've created bundle size is going to be too fruitful.
On #2 and #6, I think the answer is technically yes, I could delve into each node_module dependency and 'fix' it from depending on whole bundles, but that seems counter-intuitive for how better coders than I have written those modules in the first place. So, I'm not progressing that.
On #3, yes I was blurring AngularJSand Angular(5). I want to stay with AngularJS for now so no further action here.
On #4, no. Manually changing the webpacked index.html to use the gzip bundles results in fast download, but the app doesn't work. Using zipped resources is a web server config thing. Amended my nginx config to serve gzipped js instead - that's just going through deployment as I write.
On #5, I think so, yes.
On #6, I found Madge, which helps visualize dependency graphs. Pointing this at my client entry point (client/app/app.js in my case) and including node_modules (see CLI options) suggests:
I need to look at structuring my single module into a series of modules so each can be loaded seperately
I need to look at lazy loading of modules which are not required for the home page (example)[https://toddmotto.com/lazy-loading-angular-code-splitting-webpack]
Further tuning needs to come from optimizing functional design of the home page so it is light on both number http requests and size of responses. Nothing earth-shatteringly insightful there, it just hadn't shown up on local dev environment so I hadn't thought about it until now.
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 :)
I need your help with website project I'm working on. My project consits of 7 html documents, 3 stylesheets, 8 .js (including jquery.min.js and some jquery plugins) and some pictures. I want to bundle and minify it as much as it is possible (it would be good to get only 1 css and 1 js file or maybe 1 js, which contains styles inside).
For clarity - now, when I have all dependencies in html - everything is working properly. But I'm not sure how to set all module.exports and requires. Could you tell me how to do it step-by-step in a proper way?
Many thanks in advance.
PS. I write in ES5, so I don't use Babel.
You can do the following to make your codebase a bit more tidy.
Manually group the content of your relevant js files into one and export it as a nodejs module by using module.exports = module_name on the top of your merged js script (Repeat as needed for any jscripts in your project).
Then include the exported module in your main node file and include its main functionality using var modulesfile = require(./module_name); Please note directory paths while importing your js modules.
You can also run a minifier like minifyjs to make your js files size even smaller if they need to be called multiple times from a url. Nodejs installation and usage for minifyjs can be found here.
You can also call other css from within existing ones by using the
#import url("./css/filename.css"); Just verify proper css directory paths first.
In case you also want to use browserify for node there is a full guide in the npm website.
Another good and simple solution is to move all of your codebase in a visual studio web project. From there you can do pretty much what you want, organize your scripts and css files (/Scripts and /Content directories) in bundled configuration files etc.
NOTE: All your code has to be migrated to an asp .NET project to use this approach (as per Microsoft doc) properly.
I have a production application whose folder structure is much like you would expect:
/project
/css
/js
/php
/fonts
/images
/index.php
I have recently begun learning to use react.js and I would like to start developing new features using react while leaving all existing functionality as is and I understand that react.js can certainly be used this way.
What isn't entirely clear, is how to structure the files in my non node.js project and access them.
For example, I tried searching for this and found this article which proposes the following structure
and states:
Here index.jsx works as the entry point of the application. It uses ReactDOM.render to render App and gets the party started. App in turn does something interesting with Note. If I wanted yet another component, you would simply add it below /components.
Presumably this is a node.js project where index.jsx can call something like require('components/App.jsx');, but how do I achieve the same in my non node.js project.
Consider if I set the following folder structure:
/project
/css
/js
/php
/fonts
/images
/react
/components
/App.jsx
/Note.jsx
/scripts
/featureFoo.jsx
/index.php
Given the above, I'd like to have index.php load react/scripts/featureFoo.jsx which would somehow include/use react/components/App.jsx and react/components/Note.jsx
I figure I could have script tags in index.php to load all of the components then featureFoo.jsx but I feel like there is a more react way to do this.
So
How can I structure/access the react components of my non node.js application?
Im tagging node.js as I feel those users may well bring insight regarding this possibly from having to deal with multiple projects/aproaches.
In order to import/require other modules in a non-node.js (i.e. browser-based) JS application, you'll need to use a bundler such as webpack or browserify.
They work by starting at your "entry" file (index.jsx in your case) and recursively following all of your imports/requires. Then it smartly bundles everything up into a single "output" file, which includes everything your application uses, that you can link in your HTML.
You can also use more complex configurations with multiple entry and output files, or even dynamic loading of "chunks" at certain points in your application. But the above is the most basic use case, and works well for most simpler projects.
These bundlers have some other cool features as well. For instance, with webpack (with additional plugins and loaders) you can:
Write ES6/ES7 JavaScript that gets compiled (via babel) into cross-browser compatible ES5
minify/uglify your output JS
import/require non-js files such as CSS, images, and webfonts, and choose how to process these imports (e.g. pre/post-process your CSS, or optimize your images)
Extract all imported CSS into a single .css file
Use webpack-dev-server (or webpack-dev-middleware) to take advantage of hot module replacement, which makes developing JS apps easier by letting you see your changes take effect instantly in the browser without having to refresh or lose your app's state.
And a lot more. The world of bundlers is a pretty big ecosystem with a lot to learn, but it's totally worth getting into.
A good place to get started is the excellent Survive JS series of tutorials.
However, if you're still learning React, then diving into webpack and the entire ecosystem of JavaScript tooling can be overwhelming. It will probably be easier and a more efficient use of your time to keep things simple at first, and then only get into bundlers etc. after you get comfortable with React.