I am just getting started with Angular 2. It actually makes me think about the size of the page just for the Hello World.
Please look at the scripts which were actually needed and it already is 1.75 MB.
Offcourse with minification it would reduce 30-35% approximately.
Yet it would still be above 1 MB just for this junk Hello World type application. Adding bootstrap CSS / Jquery / Jquery UI at the minimal would take it even further plus add images depending upon the web application type.
Question is 1.75 MB of script without writing a single line of code pertaining to the application.
Is this the new web standard to make the page size on an average above 4-5 MB?
There are several strategies that will reduce the total size of your site.
Enable gzip compression for your assets. Most text files (like JS files) compress very well due to lots of strings that get repeated.
Use the minimised versions of libraries, as you identified.
Use CDN references to 3rd party libraries if possible. That way, the user may already have the file in their cache and don't need to refetch it. Some CDNs also support HTTP/2, meaning that more files can be requested in parallel.
Take advantage of the Ahead-Of-Time compilation (AOT, a.k.a. offline compilation) in Angular 2 RC 5, and swap to using the version of Angular 2 without the compiler. That saves about half of the size of the Angular 2 library file.
Use HTTP/2 yourself for your assets, and refer to each JS file individually, rather than bundling it. That way, if they haven't changed, the user won't need to download them again when they reload. And the first time, all the files can be fetched in parallel.
Use conditional comments or server side processing to remove the shims and other JS files that are only relevant to certain browsers like IE. That way, other browsers don't download those useless scripts.
Use something like Rollup or another tool that can do "tree shaking" to remove unused code.
There are probably other ways to save even more, but this is a good starting point.
Angular2 is going to get smaller in smaller now. See ngconf about this. Its mainly result of tree-shaking minification (loading only code, that really used).
Angular 2 seed project, wich in prod build loads with ~300kb is already available for use.
Related
I'm working on a web project that uses webgl content generated with unity. When trying to load the required js files the browser freezes for around 30 seconds. The main js file has 35MB size unzipped so this seems to be the cause.
I want to avoid this freeze if possible but I couldn't manage to do it using WebWorkers since the script needs access to UI. My other possible solution is to try to split the js file into smaller ones but I don't know how to do it. Do you have any suggestions?
If you add async to your script tag like this <script async src="app.min.js"></script> it will not block rendering anymore. Also caching the script in the browser or delivering it from a CDN can help reduce the download time.
35MB are, however, way too much for a website. Are you sure there isn't a lot of unused stuff like libraries in it?
We recently wrote an article with web performance best practices, with explanations to critical rendering path and other fronted concerns here
35 MB just for the JS file seems ridiculous. It could be that the entire build is probably of that size (textures, media, etc.). Have a look here on how to reduce the build size.
Though 35 MB is wayyyy to much for a JS file, you can start by following pointers:
Create utilities and reuse the code. This can be at any level. Be it generic component (HTML generating code) or validation logic, if it can be configured using arguments, make a function and use it.
If you have Hard-coded JSON in your js, move them to .josn files and load them only when they are required.
Split files based on sections in view. In SPAs, there are cases when a section is not visible. For such cases, don't load such files. Spread your code base from 1 file to 100s of file.
If you have a lot of event listeners, move them to different file. You can have section_event.js, section_data.json, section_utils.js and section_index.js. If there involves lot of data parsing, you can even have section_parser.js
Basic Idea is to split code into multiple files. Then, make code more reusable. You can even look into loading libraries to reduce your load.
Also, load a resource only when required. SPA have stages. Load concerned files when they are needed. Split download from 1 time to partial, on-demand approach. Also look into webpack or grunt or gulp to minify js.
I'm interested in using Cesium to build a 3D Earth with custom tiles, but as per the "get started" instructions here, it seems as though you have to download a massive 30mb directory and include the whole thing in your project to have it run correctly. Is this true? Can I not just include Cesium.js and get running like that? I don't need 80% of the UI elements they include anyways.
At the end of the "get started" tutorial, they seem to indicate that all you need to get running are these bits:
<script src="Cesium/Cesium.js"></script>
#import url(Cesium/Widgets/widgets.css);
<div id="cesiumContainer"></div>
var viewer = new Cesium.CesiumViewer('cesiumContainer');
But when I set these bits up, I get this error: "define is not defined" and "Cesium is not defined".
What is the lightest possible way to run Cesium?
That tutorial definitely needs an update and I'll make a note to clean it up. (For starters, there's a bug at the bottom of it, because Cesium.CesiumViewer should just be Cesium.Viewer.) That being said, here's the low-down on what's included in the zip and what you'll want/need for actual development.
Apps -> Sample applications.
Source -> AMD modules for module-based development (requirejs, browserify, etc..) also used by the sample applications.
Specs -> Unit tests.
ThirdParty -> Third party libraries required for the above.
Build/Apps -> Built and minified versions of the sampled applications.
Build/Documentation -> The reference documentation.
This leaves two directories, Build/Cesium and Build/CesiumUnminified, which I'll talk about in a minute.
But first, the technically correct answer to your question is to create the lightest possible Cesium-based application, use the AMD modules we provide. This means you only need to include the Source folder at development time, and then your build process will create the minified and concatenated version of your app for deployment. Using modules ensure you only include the Cesium features you are using. This is different than the "traditional" web development practice of including minified versions of all of your code and libraries in the correct order via script tags at the bottom of your page. Modules are gaining momentum on a daily basis and ES6 along with build systems like Babel are slowly taking over the web dev landscape. We use requirejs ourselves, but there are tons of options out there.
An example of an application built this way is the Cesium Viewer example in Build\Apps\CesiumViewer (source is in Apps\CesiumViewer). The entire built app (uncompressed) is 8.77 megs and exposes pretty much every Cesium feature and capability. 3.65 megs of that is the Natural Earth imagery that ships by default and other data files that the app only pulles down on demand if you use a feature that triggers it. The remaining JavaScript is greatly reduced in size by gzipping compression on the server end. To see this for yourself, run the latest Cesium Viewer link and open the network tab in your browser dev tools. The entire app only sucks down 2.2 megs (and that includes the initial imagery being loaded from Bing. The Cesium portion is only about 426kb. It might suck down a few extra kb if you start loading GeoJSON or KML files, but not much.
Since a module based approach requires additional set up and is still not that common in web development overall, we also supply the Build/Cesium and Build/CesiumUnminified folders. These included fully minified and concatenated versions of Cesium that suck all of the modules into a single file. However, you need more than just the Cesium.js file for deployment. Here's a break down of these folders:
Build/Assets -> The default imagery/assets that ship with Cesium (imagery/icons/stars/data for ICRF transformations). This data is pulled down as needed depending on how you configure your Cesium application. It's 3.65 megs, but chanes are your app will only ever touch a few kb of that (depending on the features you use). Rather than try and determine what to deploy to the server, I suggest deploying the entire directory (but as I said, the client may never retrieve most of it).
Build/Workers and Build/ThirdParty -> These contained the concatenated web workers used by Cesium. This includes code used by imagery/terrain, geometry tessellation, and zip file handling. It's pulled down on demand and even if you did something to require all of it, is still under a meg gzipped. These files can't be included in the primary Cesium.js because of the nature of WebWorkers (In our opinion this is a difficiency in the spec).
Build/Widgets -> contains the concatenated CSS, both in inidividual widget form and in a combined widgets.css file. I recommend just including widgets.css and be done with it (4kb gzipped); but if you are really concerned about size you can bring down individual css files. This folder also contains icons used by the various widgets. Once again, they are only retrieved from the server if needed.
As their names suggestions, Both Build/Cesium and Build/CesiumUnminified are pretty much the same thing. The main difference is that Build/Cesium has been minified and is much smaller. It is also faster because it has a lot of debug code removed in order to improve performance. Our official recommendation is to develop against CesiumUnminified and deploy using Cesium. This will make it easier to develop because you'll get better error handling and callstacks if there are problems in your code.
An example of an application built this way is the Hello World application link. There's actually not much size difference from the built Cesium Viewer app I linked above, but that's because they are essentially the same application built two different ways.
So this answer ended up being a lot longer than I wanted it to be, but Web Development is varied and Cesium tries to do its best to support all of its different approaches. Cesium itself is also incredibly ambitious so we've had to overcome a lot of hurdles that other projects never encounter. Is there room for improvement, absolutely, but we go out of our way to ensure that Cesium is as light as it can be while delivering the features that it has. I think in a 2.0 version we will probably take this even further and try and make things more modular.
I hope that answers your questions and concerns.
My question is two-fold would it be possible to load a whole directory of css or javascript? And would there be any advantage to doing so?
Example - For an ecommerce store you might have a bunch of additional css and javascript that is required for functionality/styling. Putting all the javascript files required in js/checkout directory and then importing the whole directory would seem to be more streamlined than calling each one individually.
Is it possible to do this?
Or is there some reason it would be a bad idea?
Rather than loading them individually, add a build step to your deployment so that you can minify all of the CSS and JavaScript into two files. Then serve those two files so that only send two things instead of potentially many many more.
Additionally, although creating a build system from scratch can be "fun", you may want to look into some of the build tools that already have a big following. I've used Dojo Toolkit before and it works well. You would get Asynchonous Module Definitions (AMD) from using it which could also reduce the number of requests you need to make. Another particular JS build system that I've heard mentioned quite often (although I haven't used it yet) is Grunt.
Note, there is a trade off choice. Using AMD can help you reduce the overall number of requests that you make to where you only load the scripts that you use. Compare this to downloading one gigantic JS file that holds all possible scripts.
One Mega Script
If you have 100 5kb script files, one mega minified script could (if there were no size gains from semicolons, name mangling, and linebreak removal) be 500kb. It would take one request to receive that script and let's pretend that a request takes 1kb on average. That means that, in total, the mega script would cost you 101kb.
AMD
Now consider the cost if you use AMD. Let's say on a particular page you only use 7 of those 5kb scripts and that the request still only takes 1kb. Let's also pretend that the overhead of the AMD library is 10kb. That page would cost 52kb ((7 * (1kb + 5kb)) + 10kb)
As you can see, using the AMD method rather than the build will cause for more requests, but give you a net gain in terms of cost. This ALSO doesn't account for caching things that have already been loaded before.
Also, if a user navigates your entire site, visiting every single page, causing every single script to be downloaded, then it will have cost you 610kb (100 * (5kb + 1kb)) + 10kb. However, if you go with the minified script, it would only cost you 501kb.
Oh, and don't think that AMD vs One Mega Script has an impact on minification. In both cases, minification is helpful in reducing request size.
In order to improve performance of our web pages, we are recommended to use CDNs to serve .js files on our web pages. That makes sense.
Also, we are recommended to bundle our .js files in order to reduce the number of requests which are being made to server on load.
So, we need to sit down and make decision between if we use CDN or bundle .js files.
What are the pros and cons? Which ones make more sense?
Why can't you bundle them and place them are the CDN? It should hardly be a decision of one or the other?
If you have to choose one or the other, it depends on how many .js files you are including. For a small number of files, I'd suggest that a CDN would be quicker, where-as for a greater number of files, a bundle of .js files would definitely be quicker. Where the switch-over would be, is something for you to experiment with.
My answer: both. Bundle them and place them on a CDN.
The downside of doing this? Depends. What does you build process look like? Can you easily automate the bundling and minification? Are you using Yahoo YUI or Google Closure or something else?
Also, if there is a lot of GUI dependent jQuery there might be some time consuming friction due to constantly changing elements/effects/css.
Testing is important too because due to possible minification quirks.
Bottom line: 5 javascript files safely bundled into 1 file === 4 fewer requests.
A page with just plain old Html and one external javascript reference === 2 requests to your server. However, a page with just plain old Html and one external javascript reference on a CDN === 1 request to your server.
Currently we are using the Google Closure tools. The Google Closure Inspector helps with the following:
Closure Compiler modifies your original JavaScript code and produces code that's smaller and more efficient than the original, but harder to read and debug. Closure Inspector helps by providing a source mapping feature, which identifies the line of original source code that corresponds to the compiled code.
As others have already stated, the answer is both if possible. Bundled (and minifying) gives a benefit to your users because it decreases the page weight. The CDN benefits your servers because you are offloading work. Generally speaking, you need not optimize either unless you have observed performance issues or you just have nothing better to do.
There's a few things you need to think about...
How much of the JS do you need to load early in the page load, and how much can you delay until later?
If you can delay loading JS (e.g. put it at the bottom of the page) or load it asynchronously as Google Analytics does, then you will minimise the amount of time downloading the JS spends blocking the UI thread.
After working out how the load of the JS can be split, I'd deal with the merge / minify of the various JS files - cutting down HTTP requests is key to improving performance.
Then look at moving to the CDN and ensure the CDN can serve the JS content compressed and allow you to set headers so it's "cached forever" (you'll need to version the files if you cache forever). A CDN helps reduce the latency but will also reduce size by being cookieless
Other thing you might want to consider is setting up a separate domain for static content, point it to your server(s) while you sort things out and then switch to a CDN if it looks worthwhile.
Andy
I have had some thoughts recently on how to handle shared javascript and css files across a web application.
In a current web application that I am working on, I got quite a large number of different javascripts and css files that are placed in an folder on the server. Some of the files are reused, while others are not.
In a production site, it's quite stupid to have a high number of HTTP requests and many kilobytes of unnecessary javascript and redundant css being loaded. The solution to that is of course to create one big bundled file per page that only contains the necessary information, which then is minimized and sent compressed (GZIP) to the client.
There's no worries to create a bundle of javascript files and minimize them manually if you were going to do it once, but since the app is continuously maintained and things do change and develop, it quite soon becomes a headache to do this manually while pushing out new updates that features changes to javascripts and/or css files to production.
What's a good approach to handle this? How do you handle this in your application?
I built a library, Combres, that does exactly that, i.e. minify, combine etc. It also automatically detects changes to both local and remote JS/CSS files and push the latest to the browser. It's free & open-source. Check this article out for an introduction to Combres.
I am dealing with the exact same issue on a site I am launching.
I recently found out about a project named SquishIt (see on GitHub). It is built for the Asp.net framework. If you aren't using asp.net, you can still learn about the principles behind what he's doing here.
SquishIt allows you to create named "bundles" of files and then to render those combined and minified file bundles throughout the site.
CSS files can be categorized and partitioned to logical parts (like common, print, vs.) and then you can use CSS's import feature to successfully load the CSS files. Reusing of these small files also makes it possible to use client side caching.
When it comes to Javascript, i think you can solve this problem at server side, multiple script files added to the page, you can also dynamically generate the script file server side but for client side caching to work, these parts should have different and static addresses.
I wrote an ASP.NET handler some time ago that combines, compresses/minifies, gzips, and caches the raw CSS and Javascript source code files on demand. To bring in three CSS files, for example, it would look like this in the markup...
<link rel="stylesheet" type="text/css"
href="/getcss.axd?files=main;theme2;contact" />
The getcss.axd handler reads in the query string and determines which files it needs to read in and minify (in this case, it would look for files called main.css, theme2.css, and contact.css). When it's done reading in the file and compressing it, it stores the big minified string in server-side cache (RAM) for a few hours. It always looks in cache first so that on subsequent requests it does not have to re-compress.
I love this solution because...
It reduces the number of requests as much as possible
No additional steps are required for deployment
It is very easy to maintain
Only down-side is that all the style/script code will eventually be stored within server memory. But RAM is so cheap nowadays that it is not as big of a deal as it used to be.
Also, one thing worth mentioning, make sure that the query string is not succeptible to any harmful path manipulation (only allow A-Z and 0-9).
What you are talking about is called minification.
There are many libraries and helpers for different platforms and languages to help with this. As you did not post what you are using, I can't really point you towards something more relevant to yourself.
Here is one project on google code - minify.
Here is an example of a .NET Http handler that does all of this on the fly.