grunt-amd-compile
v1.0.0
Published
Compile and optimize AMD modules from a files tree to a bundle.
Downloads
3
Maintainers
Readme
grunt-amd-compile
Compile and optimize AMD modules files into bundles.
Installation
npm i grunt-amd-compile --save-dev
AMD optimization
First what is optimizing AMD module ?
This is a not optimized module :
define(['require', 'exports'], function (require, exports)
{
// ...
});
The same module but optimized :
define('my/module/path/is/here/OptimizedModule', ['require', 'exports'], function (require, exports)
{
// ...
});
An optimized module have its path as a first argument of its define statement. Without this path, RequireJS can't know what is the virtual path of this module. Others modules can require this one from its path, like so :
define('my/module/path/is/here/OtherOne', ['require', 'exports', './OptimizedModule'], function (require, exports, OptimizedModule)
{
// Here we can use OptimizedModule which is in the same folder
});
Dependency paths are relative to each others, but RequireJS implementation takes care of this.
Optimizing, bundling and code-splitting
First, take a look at this AMD files tree as example :
- amd/
- common/
- components/
- CommonComponent.js
define(['require', 'exports', 'react', 'react-dom'], function (require, exports, React, ReactDOM) { // Module code of a component using React and ReactDOM });
- CommonComponent.js
- components/
- firstApp/
- components/
- FirstAppComponent.js
define(['require', 'exports', 'react', 'react-dom', '../../common/components/CommonComponent'], function (require, exports, CommonComponent) { // Module code of a component using React, ReactDOM and another AMD module : CommonComponent });
- FirstAppComponent.js
- Main.js
define(['require', 'exports', 'react', 'react-dom', './components/FirstAppComponent'], function (require, exports, FirstAppComponent) { // Module code of a component using React, ReactDOM and another AMD module : FirstAppComponent });
- components/
- secondApp/
- Main.js
define(['require', 'exports', 'react', 'react-dom', '../common/components/CommonComponent', './OtherModule'], function (require, exports, CommonComponent, OtherModule) { // Module code of a component using React, ReactDOM and another AMD module : FirstAppComponent });
- OtherModule.js
define(['require', 'exports'], function (require, exports, CommonComponent, OtherModule) { // Module code });
- Main.js
- common/
Note : This kind of file tree is easily generated with Typescript and is used seamlessly in solid-js framework.
We can see 2 things from this tree :
- Modules are not optimized.
- Modules files paths are representing the module paths.
We can optimize every modules easily and concat them into a big bundle with this grunt task... But that's not all !
Apps :
Some modules are using other modules but in other "apps". Apps here are these folder :
common/
firstApp/
secondApp/
Each apps can be bundled into one file :
common/**/*.js
->www/js/common.js
firstApp/**/*.js
->www/js/first-app.js
secondApp/**/*.js
->www/js/second-app.js
App to bundle is important to get because this is an powerful feature : Code-Splitting.
Each app have resources and dependencies. One app = one js file This is handy to optimize our application by loading bundled files for only the code we need.
Example :
- Page
a.html
can loadcommon.js
andfirst-app.js
because it does not usesecondApp
modules. - Page
b.html
can loadcommon.js
andsecond-app.js
because it does not usefirstApp
modules.
Static libs
grunt-amd-compile can also concat static libraries.
This is useful to bundle huge JS files, like react or jquery together, but without the AMD optimization.
Concatenation is faster and libraries like react / jquery / gsap / pixi, etc, works well as global module.
amdLite has an option to map global modules to dependencies.
So when a module requires ['react', 'react-dom', 'gsap'], it will in fact returns window.React
, window.ReactDOM
and window.GreenSockGlobals
See amdLite config file to see how it works.
Uglify
The option addUglifyTargets: true
adds every amdCompile
target to the uglify config node.
Usage
See this configuration file example.
In the browser
Now you have clean and optimized bundles containing your AMD modules, you need a library to define and require these modules from their virtual path.
The original RequireJS script is pretty big, can do a lot of stuff, and is complex to configure.
So I made a little RequireJS implementation for the browser, named amdLite. The configuration is easy, take a look !
Also, all of this is used transparently with solid-js framework. If you want something ready to use, give it a try :)
Links
- Read this really good article about modular JS : https://addyosmani.com/writing-modular-js/
- Solid JS framework is a Typescript framework using AmdLite
- RequireJS optimization : http://requirejs.org/docs/optimization.html