I use require.js (AMD) and optimize it into one final javascript file (main.js)
My main.js is half a megabyte, and it will continue to increase.
The problem is: when the client loads my backbone app, they must first download the entire half megabyte file before they can browse the site. (the router is included inside the file)
Oftentimes this can take 3 seconds before the initial load.
What can I do?
Split your code up into the following categories and use separate requirejs modules for each.
Core code required to get the initial app displayed
Most of your modules that are heavily used through your app can go here
Secondary code that is OK to arrive in a subsequent request via AMD
things like animation helpers, stuff that only appears on click, etc
Any modules that are only needed in the corners of your app
specialty error handlers
edge case logic
paths most users don't take through your app (like a refund module in a e-commerce app)
That way with a single, hopefully reasonably sized request, your app is up and running. A second request takes another second or so to get you 98% loaded, and the last 2% trickles in on-demand if a given user needs it.
Requirejs has facilities for doing this via the config file. It just takes some forethought and testing to find the right places to draw the dividing lines for your specific application.
General tips: consider fewer large third party dependencies. Consider a separate bundle for administrators if you have different user roles.
Related
I have a requirement to develop multiple Angular 2 applications independently by various teams. Each team will have independent releases scheduled. Towards the end, all these applications will need to be injected into one main application at runtime. They will need to work as a Single Page Application.
We tried Lazy loading modules of Angular 2. One of the roadblocks we see is that we cannot compile the main application using web pack without having the lazy load modules in the project solution.
Here is the structure of my present solution:
Image1
This is how I defined the routes
image2
We have defined two routes that lazy loads two modules(LazyModule and MoreLazyModule). This solution works fine.
When we remove those modules from the solution try to build it using web pack, the compiler throws an error.
Is there any way we can decouple the modules to develop them as independent projects and inject those modules in production?
Lazy Loading is the solution for your problem (at least as far as I know).
If I understand correctly, what you are trying to build is an app which has an external container (app.module and app.component) which need to orchestrate several other independent apps. The whole thing needs to behave as a Single Page Application.
If this is the case, then what I suggest you to do is the following:
have a team (or an individual responsible for all the code of the
Container app (app.module, app.component, any other common code you
may want to share among the various apps) - the Container app
references all the subApps (and gets updates as soon as a new subApp
is added)
have different teams responsible for the different subApps - these
teams work on the code of their competence, submit to the code
repository when ready, but use the entire project (i.e. also the
subApps of the other teams) any time they build
I do not see any issue in organizing the work like this, as soon as every team checks in the code to the central code repository only when all tests have passed (and the tests cover the application functionalities thoroughly). The coordination effort required to the team responsible for the Container app is really minimal.
I have an Angular website, I used that for my website panel, there are some different roles in the panel, some admin roles and some different kind of users and I could handle that and limit different users and route/views by their roles.
What is the problem? I bundled all of my needed *.js files to one file named bundle.js and it is working well, but the problem is the file is heavy and it is hard to debug the program just by one file! bundle.js is more than 2 mb and I really need to change it.
For example, I have a role which used d3 which is a heavy size library and just in one route. So, Why should I add that to bundle.js when just some kind of users may need it.
Questions:
Is there any way, I can have the single page application but still each view/route include its own external javaScripts?
Is bundling files harmful? Is there any real project that bundled all files in one js file?
This question is realy broad as it highly depends on how you implemented your roles and how you organized your code.
For the problem of loading lazily your modules depending on the user and his role, you could take a look at the ocLazyLoad library that looks like doing this job (loading modules lazily).
You could also make several bundles for your app (one for each role) an use a server-side script to load the needed one.
Is bundling harmful ?
As you stated bundling can be a problem, if you have many kind of different users, or if you don't know where the user will go after the first page (an app with hundreds of screen, for example).
However you should always bundle because it is more network friendly to load a single big file than hundreds of small ones.
The fact is you have to bundle wisely and make one bundle for each page or group of pages, or user role, etc. Everything depends on how the app works...
So depending on your needs you should make several bundles, whatever happen, let's say a common-one where you store your common functions, modules, routing etc. and others depending on the role or the page you want to display.
I have an application that have more than 7 tabs at home page and each tab is very comprehensive in itself with nested tabs/windows.
I am using EXTJS 4.2 MVC architecture. My question is what approach should I use to load all views/controllers/stores. This does not include proxy calls to web servers as those are only user request based.
First Approach: Load all files on application first load by including all controllers in app.js file and those controllers will load all tab specific files. I do have one person resource who is working with ExtJs for long time and suggested that it is OK to load all at once. EXTJS build process will combine all these files in one single file and it will be like ext.js file that is very big in itself and takes very less time to load.
Second approach: Only load tab views/controllers when user select that tab. That will require invoking controllers dynamically.
As I am new to ExtJS and have lazy loading mentality. Not sure how it fits in EXTJS world. Please advice me based on your experiences.
As long as you concatenate and minify your files into a single bundle your resource loading time should be reasonable. If you also include a version number at the end of your resource loading url you will get the benefit of browser caching and refresh on demand when you want to update the bundle. You just rev the version and the browse will reload your bundle from the server the next time.
Processing 7 controllers and setting up listeners is an overhead but I doubt you will see a major performance improvement here. Do be mindful of multiple round trips to the server to fetch resources and data. This is where you will see negative impact.
Question 1:
Why do I need to asynchrously load my JavaScript files in a web page? I can see the rationale for it on the server side, but if I know all the files I need to load in the client, why shouldn't I concatenate all my source files into 1 file and load that on page load? Is the first initial page load so important that future operations may be slowed down due to latency in retrieving every JS file?
Question 2:
Assuming the answer to question 1 is that I need to load JS files separately:
AMD loads each JS file asynchrously, CommonJS loads synchronously. CJS is required for server-side loading (that's how Node.js works, if I'm not mistaken). AMD seems to be a better fit for the client. Thus, the only reason to use CJS in the client is to share code with the server.
Is there a way to make AMD and CJS play nicely, so that client JS files can be loaded asynchronously but still have CJS syntax?
(What exactly does require.js do? I cannot for the life of me read between the lines on their website.)
You do not "need" to load javascript files asynchronously or via some custom loader. Here are some reasons when asynchronous loading or custom loading might provide a benefit:
When the javascript file is not normally needed and you might want to load it upon demand rather than all the time
When the javascript file is not needed for initial page display and you want to maximize the speed of first display for your page
When you want to control the timing of exactly when the javascript file is loaded
When you are deciding, based upon some condition, whether to load the javascript file or not (for example, if loading from a CDN failed, you might load from a backup location)
When you want script loading to proceed in parallel with other things rather than serialized one after another
If you don't need any of these benefits or some other benefit provided by programmatic loading, then you can just use the normal <script> tags and let them load synchronously.
Part of the issue with just concatenating the file isn't the time spent downloading, it's the time spent compiling on every page.
If you've got a 20,000 line file, and you only need 600 of those lines to get everything up and running (assuming that everything is written to be modular and asynchronous, using any pattern at all for managing the resources), then you're going to save yourself what might be half a second or more, if you serve the core program and extend as-needed (or on a delayed timer, serving large chunks of functionality which are closely related to one another).
The overall time spent downloading is higher.
The overall number of HTTP connections used is higher.
But the time required to make the page visible to the user is lower.
The time required to add base-functionality to the page is lower.
Then extra functionality can be streamed in, either after the load and initialization, or just-in-time, as-requested by the user, and in both cases, as long as the code you've streamed in is focused on doing that one thing, and isn't calling for a half-dozen other dependencies, the time between the request and the addition of the functionality is going to be minimal.
RequireJS uses a promise system, basically.
It allows you to declare dependencies up front, and hand in the code (as a callback) to be implemented, after all of its dependencies are handled.
If those dependencies have any dependencies, then they won't be initialized until their dependencies are loaded.
If you just want it loaded and order isn't important, then you don't need to give it dependencies.
The overall moral is, if you've got a system where all of your files are small, the overall weight of JS on the page is very small, you only needed a few hundred lines to do everything you wanted on the page... ...plus, you know where all of your dependencies are, you have a system on the server to make sure they're in the right order, et cetera (plus you've got great documentation, or you're the only one who touches this code, and you live inside of it, day to day)...
...then there's nothing at all wrong with doing what you're doing.
You might not see any difference at all, if the compile time is outweighed by the number of HTTP requests you make.
But for overall applications which are tens (or hundreds) of thousands of lines long, where only a fraction of that functionality is needed on any one page, there can be big savings in terms of perceived time between when the page loads, and when the app is "ready" for basic interaction by the user.
If you want to load your entire javascript source for every page, sure, compile it into one file. If you load different code based on what actions the user takes, or based on what page has been loaded, use AMD loaded modules. The other alternative would be to list a bunch of script tags, which of course would only be loaded one at a time and could take a while.
AMD is not a specific library, it is actually a standard for loading javascript modules that most of the loaders you mentioned use. This means they all use similar syntax for defining and loading modules. They are considering making AMD part of the ECMA script spec. The usefulness of it is that you can also define dependencies, so if your code requires jQuery to run, you can list this as a dependency, and it will be loaded into your modules namespace.
define( [ 'jquery' ], function ( $ ) {
// use jquery in here without clouding up the global namespace
return {}; // return your module for use in a different module or whatever
};
In this example, the code in the defined module will not be run until the jquery module has been downloaded. It will then inject the jquery module directly into your newly defined module as an argument $.
You can now keep your code neatly organized into files which contain modules. None of your modules will cloud up the global namespace. All of your dependencies will be sure to have been loaded before your module runs (no loading race condition bugs for dependent pieces of code).
Another advantage is you can set up your loader to use different paths for the same module, so you can define the path for the jquery module to be 'https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js' in one spot in your code even though it may be used in almost every module. Now when I need to update my jquery version to 1.8.3, I can simply change the path in one spot in my code, and it will use this path for every module that uses jquery as a dependency. This can also be useful for easy switching when testing when you are using module stubs, or debug versions of certain modules.
Now this is not necessarily needed for tiny projects. The bigger your project gets however, the more sense this type of loading starts to make.
I'm pretty new to Sencha Touch and am trying to make a simple application that has a login form and makes calls and fetch results into lists.
My question is, how should I create the structure of the application? Should it all be inside one .html file? or should I different pages for each list and the login page? If so, how can I change views from one page to another and get transition effects?
There is actually a generator which you can use to generate the canonical app structure. From the Sencha download, go to the jsbuilder directory, then run a command similar to this:
./sencha.sh generate app MyApp path/to/myapp
Also, this slide set demonstrates the structure, though you may have to dig for more of the philosophy for why things are where:
http://www.sencha.com/conference/sessions/session.php?sid=322
And here's the example app talked about in the discussion:
http://cl.ly/1d1S282O1Y2c3N1v1j1i
It's fine to use a single HTML file to get things started, but in the long run it's worth making the application structure consistent with 'best practices' so that others can look at, and understand, your code subsequently.
Sencha Touch generators (coming in v1.1) place the launch logic in a file called app.js and then have files for each model, view and controller (in respective directories).
While you may not be building a fully fledged MVC application from the start, you should probably still use these conventions. Take a look at the Twitter and Kiva apps in the SDK (and at http://dev.sencha.com/deploy/touch/examples/ ) foor good examples.
The index.html file can link to each file individually, but of course for production, you are also advised to look at the JSBuilder tool to package and minify them all so that the device can fetch them in one single HTTP request.
I would break it up by major function (i.e. purpose). For mobile apps, you want to avoid having unnecessary postbacks / loading multiple pages and views if you can help it.
If your mobile app has one purpose, I would keep it on one html page and only break up the JavaScript files as you need to keep it organized.
If it has two purposes (e.g. 1-to ENTER a bunch of information, and 2-to display reports on your data), then I would break it up into two html files.
For example, if you have a mobile app that takes you through a series of wizard steps to perform data entry (i.e. single purpose), I would house that whole wizard inside of an Ext.Panel (on a single page), and swap out each content Ext.Panel "step" of the wizard as the user progresses through the wizard.
Start with the simplest thing and refactor later. I've just done an app in Sencha Touch and it gets quite bewildering looking at the example files. I found the easiest way to learn was to create a single html file and as soon as something became unwieldy or obviously needed a refactor I started creating subsequent files.