0

I'm working on a large backbone single page application where we've all the JS files specified in order just before </body> tag. Then, for production, using grunt-usemin we concatenate and make single minified app.min.js file for production. Also all the templates are converted to JS using grunt-contrib-handlebars and concatenated into the same app.min.js file.

As the code is growing, size of app.min.js file has gone up to 1.25MB and still this application has long way to go. There are many major sections yet to be developed.

At the same time, I don't want to load 5 or more JS files and same number of templates when user visits to each screen. Rather, I wanted to have modules and load single module file and user can browse through whole of the module without loading any other JS file.

Also I want those module files to be minified and optimized and revved (for cache busting) for production

I was looking through require.js and it's optimizer. I've just started implementing one of our next module using require.js and when I came to building for deployment, it seems that r.js optimizer creates single output file which brings me back to square.

Is it not possible to do what I'm looking for using require.js, or am I missing something? Or is there any better solution of my problem than require.js?

NOTE: Though there is a benefit of using loader even though single big file is loaded at once, I don't want to load whole code when I just need one module of code.

Community
  • 1
  • 1
IsmailS
  • 10,797
  • 21
  • 82
  • 134

1 Answers1

1

you can build into multiple files. inside requirejs:compile:options: do the below

modules: [

                    {
                        name: '../build1',
                        include: [
                            // 3rd party libs
                            'backbone',  //the reference to these files are present in paths: property                            
                            'underscore'
                        ]
                    },
                    //build 2
                    {
                       name: '../build2',
                        include: ['build2ReqFile1','build2ReqFile2'],
                        // Excludes all nested dependencies and built dependencies from "common"
                        exclude: ['../build1','build2UnReqFile1']
                    },
                   //build 3
                    {
                       name: '../build3',
                        include: ['build3ReqFile1','build3ReqFile2'],
                        // Excludes all nested dependencies and built dependencies from "common"
                        exclude: ['../build1','../build2','build3UnReqFile1']
                    },
                ]


Updating with explanation yep this is for single page application.
Few things to understand here - whenever you define i.e. define('app/test',['app/load1','app/load2'],function(load1Ref, load2Ref){}), new script tag is added to dom and a data-xyz = name of module i.e. <script data-xyz = 'app/test' src = '' type='text/javascript'> is added. I dont remember what the name of xyz is.
The returned value of the define is stored in the context data-xyz. So when ever you do require(['app/test']) it returns the value present in data-xyz of app/test script.
Now when you build, all the require and defines that are referenced are built into one single .js. SO by doing the above you can have multiple builds where in you mention which of the defines each of these individual builds should include or exclude.
So these builds are nothing all the javascript files minified and compiled into one/multiple files. Depending on which files you require you need to include these built files.
If you require 'build2ReqFile1','build2ReqFile2' then you can just include build2.js in your code, if you want backbone and underscore along with 'build2ReqFile1','build2ReqFile2' then you need to include build2.js and build1.js

Is it clear?

wallop
  • 2,510
  • 1
  • 22
  • 39
  • if this should go in gruntfile.js, I guess would then need to refer `build1`, `build2` in my define in js code which I won't find in development time but will work in production. Or am I misunderstanding? – IsmailS Aug 20 '14 at 13:59
  • Also note that I have only single page in my application. – IsmailS Aug 20 '14 at 14:50
  • yes you need to refer to the build1 and build2 which will be available in your production but not in development. – wallop Aug 20 '14 at 15:17
  • Its better to have a common name to the entry js file that your html refers to so that you dont need to explicitly make any changes to the production files after build!!! Or You could design in such a way that in production the files referred are different than from development!!! – wallop Aug 20 '14 at 15:26
  • Then it will give 404 in development and it isn't workable solution I guess. – IsmailS Aug 20 '14 at 15:27
  • its a challenge but its not impossible. I seem to have done it, i cant remember the exact steps i did. However you could use the url which points to app/production/entry.html for production nd app/development/entry.html for development while trying to load specific modules – wallop Aug 20 '14 at 15:28
  • `Its better to have a common name to the entry js` That can be workable. Though, I was reading https://github.com/jrburke/r.js/blob/master/build/example.build.js#L363 and as I understand (might be wrongly) optimizer doesn't overwrite files. – IsmailS Aug 20 '14 at 15:29
  • nope optimizer doesnt overwrite, like i said it minifies and builds all the related files into one – wallop Aug 20 '14 at 15:31
  • anytime. as long as its useful : ) – wallop Aug 20 '14 at 15:37