I've been looking for a way to split my one page app's js file in more than one. Like this:
plugins.js
open.js
closed.js
admin.js
So, when the user loads the first page, plugins.js and open.js is loaded. The other are loaded only when in specific pages (like a closed section or an admin section, which is closed so I'd load it after the other ones). Today all my app users load the whole heavy and minified javascript file.
Am I able to do that using require.js? I couldn't find any reference to this kind of approach.
Thanks.
I've been looking for a way to split my one page app's js file in more than one. Like this:
plugins.js
open.js
closed.js
admin.js
So, when the user loads the first page, plugins.js and open.js is loaded. The other are loaded only when in specific pages (like a closed section or an admin section, which is closed so I'd load it after the other ones). Today all my app users load the whole heavy and minified javascript file.
Am I able to do that using require.js? I couldn't find any reference to this kind of approach.
Thanks.
Share Improve this question edited Oct 30, 2013 at 22:06 hexacyanide 91.9k31 gold badges166 silver badges162 bronze badges asked Oct 30, 2013 at 22:05 Eduardo MagaldiEduardo Magaldi 915 bronze badges 1- You can always include the files when you need them in the pages where you need them. – nietonfir Commented Oct 30, 2013 at 22:25
5 Answers
Reset to default 3Please take a look at require-lazy. It is functional, but documentation is a bit lacking for the time being, so the best thing to do is take a look at the examples.
In few words what it does is that it creates a layer on top of the optimizer (r.js) so as to sense application split points and generate the appropriate bundles. Application split points can be declared explicitly using the lazy!
AMD plugin:
define(["module1","lazy!module2"], function(m1,m2) {...});
In the case above, module2
is not loaded; an object with a get()
method is injected instead. module2
is loaded only when m2.get()
is called (it returns a promise). The build process will create 2 bundles for the case above: One that contains the main file and module1.js
and one that contains module2.js
.
I have also implemented a mechanism for "discovering" modules, see the module-discovery
example.
Related projects: require-lazy-grunt (soon to take off) and angular-require-lazy.
You might want to have a look at Grunt.js and bine it with its contrib-uglify
plugin. I've made a simple boilerplate package to help get me started on new projects, which include Grunt
and a simple contrib-uglify
implementation here.
You'll have to specify which files should be concatenated into which files, then you can load each file dynamically depending of where you are in your app.
You could also use Modernizr to do feature detection to/and/or assign corresponding classes to the html tag on your page and then use Yepnope to asynchronously load resources conditionally and serve only the files your users need - according to the features available or just based on classes you have defined, like contact-page
, for instance.
You can divide your JS code into several smaller files. Then in each page's <head>
section include only the relevant JS files.
<head>
...
<script type="text/javascript" src="plugins.js"></script>
<script type="text/javascript" src="open.js"></script>
</head>
If you really need to decide whether to load a script file dynamically, then RequireJS will do the job. It's well documented on their website how to use it. However, from what I understand, it would be an overkill in your case.
I remend using Webpack for this purpose instead of requireJS. Webpack was explicitly designed for the purpose of piling frontend code together - i.e. pulling dependencies in to generate a single js file from many modules - then splitting it into multiple files as per each page's needs. It's not a plete 180 degree change - you can leave a huge portion of your requireJS syntax in place, since it supports AMD modules out-of-the-box (along with UMD and CommonJS). The process of switching isn't too plicated.
It can also be used to watch your files, and automatically repile when one of them changes - so the proper split-up of your code is continuously maintained.
It also does a lot of really cool things above and beyond RequireJS, such as handle cross-dependencies between CSS and JS files, inject requested shims into all files, etc..
On a side note, I find Webpack especially powerful when integrated into a Gulp autopile workflow. You don't have to - I just found the bination worked particularly well.
Of course!
Optimizer configuration options of dir
and modules
is what your need.
You should write something like this, one optimizer configuration file fed and multiply minified javascript files out:
{
// dir is white your temp build files put
dir: 'build-temp-dir',
// one module for one minified javascript file
modules: [{
// module names are relative to baseUrl
name: 'mylib/module-entry1',
// include something else
include: ['mylib/module2']
},
// other one minified javascript file
{
name: 'mylib/module-entry2',
// if you don't want repetitive code put in the two out files
// just exclude it
exclude: ['mylib/module-entry1']
}]
}
Be sure to check the requirejs official multipage demo and module config option