esm-middleware
Serve ES modules from your node_modules
folder.
Overview
esm-middleware
is an Express middleware that aims to make it easy to deliver ES modules from the node_modules
directory to the web browser, using the ECMAScript 2015 import declaration syntax, which is currently available in all major browsers.
Installation
yarn add esm-middleware
Basic usage
On the server side, just create an Express
app and attach the esm-middleware
:
server/server.js
const express = ;const esm = ;const http = ;const path = ; const app = ; // The esm middleware should be attached to the Express app before// the static built-in middleware.app; // Make the node_modules directory public.app; // Also, expose the directory where our client side code lives.app; app; const server = http; server;
Let's now assume we wanted to use Lodash in our client side code, we first need to install it within our static node_modules
folder:
npm install lodash
Then, in our client side code, we would just import Lodash as:
client/app.js
; // Use Lodash methods here...
Public API
esm-middleware
exports a factory function which takes a single options object argument:
{ |
Type | Default value | Description |
---|---|---|---|
cache |
Boolean |
true |
if true , modules are cached. |
nodeModulesRoot |
String |
path.resolve("node_modules") |
it is an absolute path to the folder containing npm packages. |
} |
Furthermore, the middleware implements a tiny web API which controls whether a certain module should be skipped from processing.
Just add a nomodule=true
query string argument to the declaration source, e.g.:
;
How it works
Behind the scenes, esm-middleware
uses a tiny Babel transform that rewrites ES import/export declaration sources so that they resolve to paths that are locally available to the web server and publicly accessible by the web browser.
Processed modules are parsed and transformed once. Subsequent requests are fullfilled by sending a cached version of each module.
Caching can be disabled by initializing the middleware with the { cache: false }
option.
Known limitations
CommonJS support
At the moment, commonjs
modules are also supported but only the default export is made available to consumers (e.g. the value assigned to module.exports
, similar to how --experimental-modules
works in Node).
If a commonjs module has multiple named exports, you'll have to access them as properties of the default export, e.g.:
; // Same as invoking module.exports.bar() on the server side.myModule;
In version 1.1.0
, basic support for UMD CommonJS named exports was added.
So, if the requested module is packaged as a UMD
module, it will be possible to do:
// let's pretend this is the file an hypothetical module named// "umd-module" package json main's field points to!{}{ebar='foo'} // in your source code, you can request "bar" by writing:;console; // you can still use the default export though, it will always// be made available for backward compatibility;console;
<script>
tags
Any module loaded through a <script>
tag, should be requested by specifing an extension for which the mime
module returns a MIME type
of application/javascript
, e.g.
...// `app` is an Express application instance.app
If the extension is omitted, the middleware will not be able to process the module.
Extension can be omitted for modules requested through import
or export
declarations indeed.
Node core modules
Node code modules are not supported at the moment, so doing something like:
;
won't just work.