Skip to content

Instantly share code, notes, and snippets.

Last active Aug 29, 2015
What would you like to do?
How to share modules across RequireJS, CommonJS web apps?

Earlier today I tweeted:

I want to use node modules in my existing requirejs browser app. What’s the right path?

This was really understating the problem I'm trying to solve. I need a way to share modules across various JS (browser) applications. Some of these applications are RequireJS apps, and changing them away from that is probably not on the table. Others are newer applications where we have a choice when it comes to the build system -- common choices of late seem to be browserify and webpack.

I want to be able to maintain a set of modules separate from these projects that can be used by these projects. The requirements, then, are:

  • Modules must be usable by a CommonJS-based module/build system, such as Browserify or Webpack.
  • Modules must be usable by an AMD-based module/build system, such as RequireJS.
  • Modules must be installable, update-able, and version-able; that is, the modules should be not need to be modified in any way by the host application.
  • Modules must be able to share dependences; that is, if two modules require the same version of lodash, then an application that requires them should not end up with two lodashes in its build.
  • We can make modifications to the RequireJS apps short of completely changing the module/build system.
  • Modules should work just fine for Node apps, too, where appropriate.

This comment has been minimized.

Copy link

@jrburke jrburke commented Feb 19, 2015

Assuming you control the authoring of these shared modules, use a UMD wrapping in the module source to allow cross use between CJS and AMD.

The next piece is choosing a package manager. For your last point, that likely means publishing to npm. If choosing npm to consume the modules in the front end app, then be wary of nested dependencies, which could lead to your "duplicate code" issue. Hope that npm dedupe does something for you. Your mileage may vary.

When using npm, then the main issue, if the modules are in UMD wrappers in source form, is configuring the requirejs loader to know how to resolve the IDs.

  • notobo might be an option, particularly if you end up with nested node_modules config. Relatively new tool though. It will scan through the files, find nested node_modules and set up map config for the requirejs config.
  • If you can keep the dependencies flat, all under the top level node_modules, then I prefer using adapt-main-pkg as a post npm install task to write out the main module adapter files in node_modules. It does not actually touch the files in the node_modules package directories, just creates adapters at the top, inside the node_modules root directory. So the packages can be upgraded as desired. The README for the project outlines a project setup that avoids lots of config: basically configure baseUrl to the node_modules directory, configure one paths config for your app's file location, then keep all your app modules under the app/ directory.

The requirejs loader's nodeIdCompat option might also be useful, but I would encourage just not referencing dependencies by using ".js" in the file names, it muddies the difference between module IDs and paths. The nodeIdCompat can help though if you do not control some of the dependency strings in the modules you are consuming.


This comment has been minimized.

Copy link

@thomaswilburn thomaswilburn commented Feb 19, 2015

Shouldn't UMD work? If you build your modules with browserify --standalone, it should generate a UMD-compatible module, which could then be loaded with either AMD or another module system.

EDIT: Or, you know, what jrburke said. Nice comment!


This comment has been minimized.

Copy link
Owner Author

@rmurphey rmurphey commented Feb 19, 2015

@thomaswilburn that doesn't solve for the fourth point, as far as I can tell?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment