Module definition to work with node.js, require.js

2019-07-29 14:01发布

问题:

I am working on a javascript module/library that should work in 3 environments:

  1. in node.js
  2. in requirejs
  3. when simply included using tags into the webpage. In this case the whole module should be hooked up under window.myModule

Do you have any suggestions as to how to write the structure of the library so that it works in all these environments?

EDIT: basically I mean some sort of wrapper code around the library so that I can call the file form any of those three methods and I'm fine...

回答1:

This requirement and its solution is known as Universal Module Definition (UMD). It is currently a draft proposal. Background and current status is described in Addy Osmani - Writing Modular JavaScript With AMD, CommonJS & ES Harmony article. Look for "UMD" link pointing to various templates you can use.

Quite many other templates can be found on the web - UMD is the search keyword.

(did not find the final link myself yet :)



回答2:

We're working on the same thing, I think.

And we have some success. We have library (we call it 'slib'), compiled to AMD js files. It does not depend on npm modules or browser, so it can be called from node and from browser.

1) To call it from node, we use requirejs:

file require.conf.js

module.exports = function(nodeRequire){
    global.requirejs = require('requirejs');

    requirejs.config({
        baseUrl: __dirname+"/../web/slib/",
        paths: {
            slib: "."

        },
        nodeRequire: nodeRequire
    });
}

In any other serverside (nodejs) file we add this line at the beginning

require("./require.conf")(require);

then we call slib's code by:

var Computation = requirejs("slib/Computation");

2) To call slib from browser, we just use requirejs. It handles everything fine.

3) We do not need to call slib from < script > directly. For production, we use r.js to make a bundle js file with most of dependencies and use it on the page with one < script >. And this script downloads all other deps, if they are not included, using standard requirejs and it does not need requirejs (as far as I remember), it just works alone. This is very flexible for large projects: use requirejs while development, use r.js to bundle core files in production to speed up page load, use whole bundle if you need only one < script > without any other requests. r.js bundles all dependencies correctly, including old js libraries, which were commonly loading using only < script > and accessible by window.myOldLibrary using shim param on config.

It seems you can use browserfy to make some npm modules accessible from slib's code, but we did not tried yet. Also, using requirejs on node's side, I think, can be simpler (why we need second 'requirejs' function together with node's one?) We just have not investigated it well, but this works.

In any slib module you can write

if (window)
    window.module1 = this // or whatever

and it will be exported as old js lib upon load