Search code examples
javascriptnode.jsrequirejsamdr.js

Grouping shared dependencies of different AMD dependency trees with r.js


I have an AMD project, which basically has the following structure :

samples/sample1/main
________________
* sharedpackage1/subfolder1/module1
* sharedpackage1/subfolder2/module1
* ./localmodule1
* ./localmodule2
* ./subfolder1/localmodule1



samples/sample2/main
________________
* sharedpackage1/subfolder2/module2
* sharedpackage2/subfolder1/subfolder1/module1
* ./localmodule1
* ./localmodule2
* ./localmodule3
* ./subfolder1/localmodule1
* ./subfolder1/localmodule2
* ./subfolder2/localmodule1



samples/sample3/main
________________
* sharedpackage2/subfolder2/subfolder1/module1
* sharedpackage2/subfolder3/module1
* ./localmodule1
* ./localmodule2
* ./localmodule3
* ./localmodule4
* ./localmodule5

...

I would like to use r.js to pack my project and end up with...

  • a single shared.js file for all samples that contains all modules in sharedpackage1 and sharedpackage2 - and their dependencies - that are used in at least one of the samples
  • one main.js file per sample that contains all the modules that are specific to that sample (the "local" modules)

Note that...

  • sharedpackage1 and sharedpackage2 are libraries that could contain hundreds of different interdependent modules
  • neither sharedpackage1 nor sharedpackage2 has a "root" (or "main") module that has all other modules within the package as dependencies
  • modules in sharedpackage1 can have modules from sharedpackage2 as dependencies
  • modules in sharedpackage2 only has other modules in sharedpackage2 as dependencies
  • modules from sharedpackage1 or sharedpackage2 that are not used in any of the samples should not be included in shared.js
  • the sample-specific configuration should be as minimal and as generic as possible, so it can easily be generated at build-time with a Node script

Now, as long as every new sample has a main.js file as "root" module, it shouldn't be too hard to have every new sample automatically picked up by my build script without any additional configuration. So I'll manage with that.

What I can't seem to figure out from any of the documentation I've found, is how to create a single shared.js file that contains only those modules from sharedpackage1 and sharedpackage2 that are used in the samples without defining a shared module where I manually list all the individual dependencies for each main.js of each sample (which is ill-suited for my use case).

Is it possible to do this with r.js? If yes, how can I achieve this?


Solution

  • I received the following answer from jrburke on Github :

    example-multipage project sounds closest to what you describe. However, it may not be as smart as you are wanting. The "common" layer still needs the build config to list some top level modules to include. It can trace the modules by those top level modules in the include array, so it does not need to be an exhaustive graph listing.

    It also sounds like you may want bundles config, if you don't want to do the two-staged loading that example-multipage does. But bundles config can be very wordy.

    If you want really fine grained tracing and grouping, amodro-trace will just trace the modules, and you can use your own build scripts to combine the traced modules into the bundles you want. It still may take some effort to turn turn those built files into a runtime requirejs config that can be used to efficiently load the bundles though.

    There are no solid easy answers for complex bisecting of module graphs and separating the bundles. r.js is not very smart as far as not doing any fancy source modifications to, for example, introduce intermediate require([]) calls to load bundles.