-
Notifications
You must be signed in to change notification settings - Fork 143
Loading Modules
Modules are a way of breaking up your code into logical pieces to maintain a separation of concerns.
On a practical level, JavaScript modules are files that resolve to a single object. Modules need to be accessible by your code, which means they need to be loaded in memory one way or another; and they need to set or return a reference to themselves.
Let's take as an example Hypergrid plug-ins, which are modules. Let's load a hypothetical plug-in named event-logger
.
The plug-in can be built into your app and loaded with it, or can be loaded separately by the client:
-
CommonJS modules are "bundles" together at build time into a single file which is loaded at run time with a single
<script>
tag. -
Client modules are individual files that are loaded at run time, each with its own
<script>
tag.
At build time, Browserify or webpack converts a base file, typically /index.js
, and any other files it "requires" (and anything they in turn "require", etc.) into a single build file.
This file can then be loaded by the client with a single <script>
tag:
<script src='my-build.js'></script>
If not using Browserify or webpack, the client loads each "required" module separately:
index.html
:
<script src='https://fin-hypergrid.github.io/core/2.0.2/build/fin-hypergrid.min.js'></script>
<script src='https://fin-hypergrid.github.io/event-logger/1.0.0/build/event-logger.min.js'></script>
<script src='main.js'></script>
In the above:
- Hypergrid loads itself synchronously into the
fin.Hypergrid
global. - Other files must then be loaded (synchronously or asynchronously) into members of the
fin.Hypergrid.modules
namespace.
The file main.js
is a "wrapped" version of index.js
:
window.onload = (function(require){
/* index.js contents goes here */
}).bind(null, fin.Hypergrid.require);
A gulp or grunt watch task can be set up to do the wrapping.
Alternatively, you can avoid wrapping by using Hypergrid.require()
instead of require()
. The advantage of wrapping is that index.js remains a CommonJS module, which is nice if your intention to to eventually migrate to bundling the code into a single file with Browserify or webpack.
While the above guidelines are sufficient, a Hypergrid Client Module has a wrapper that does both of the following:
- Inserts the module into
Hypergrid.modules
- Supports
module
,moudle.exports
,exports
, andrequire
within the module
Therefore, a Hypergrid Client Module is available to other such modules via require
as well as being able to use require
itself to load other such modules. If modules are dependent on one another in this way, they must be loaded synchronously. Forward and circular references are not supported.
The following utilities help wrap up modules as Hypergrid Client Modules:
-
fin-hypergrid-client-module-wrapper
defines a succinct little wrapper that in addition to makingrequire()
available (similar to the simple wrapper shown above), also makesmodule
,module.exports
, andexports
available and also transparently assignsfin.Hypergrid.modules[modulename] = module.exports
for you. -
fin-hypergrid-client-module-maker
defines a standard gulp task for wrapping your code. It also defines standardlint
andtest
tasks.
See also the Client Modules wiki that describes the concept in more depth.