🔥👨💻🔥 This is a successful but terrible idea and should not be used by anyone.
APACHE-2.0 License
cjs-loader transitively includes commonJS modules for use on the web, and is useful for developers wanting to migrate to ES6 modules who still have legacy dependencies. Go here for a demo (needs a browser with native modules support—Safari 10.1+, or Chrome 61+).
We do this using just your browser, without a compile step, by implementing require()
and other methods just while loading the module code.
For users of cjs-loader, we provide load(moduleName)
that returns a Promise
of the exports.
🔥👨💻🔥 This is an interesting, successful but terrible idea and should not be used by anyone. It reqiures support for ES6 Modules 🛠️ and has only really been tested on Chrome 61+.
First, install any public modules you want to use with NPM or Yarn. Then, use the loader:
<script type="module">
import {load, setup} from './path/to/cjs-loader.js';
setup('./path/to/cjs-loader.js');
load('npm-package-name').then((out) => {
// do whatever as if you require()'d the package
});
</script>
(This assumes npm-package-name
is in the path ./node_modules/npm-package-name
. You can also require()
a relative path.)
For example, to use Handlebars (as per the demo):
load('handlebars').then((handlebars) => {
const Handlebars = handlebars.create();
const source = '<p>Hello {{name}}, you have {{name.length}} letters</p>';
const template = Handlebars.compile(source);
console.info(template({name: 'Sam'}));
});
Handlebars internally fetches about ~35 modules (via require()
), which all get wrapped.
module.exports
, require()
etc.require()
, throw a known exception^2^1 more or less
^2 require()
is synchronous, so we can't block to load more code
We abuse the fact that Chrome reruns but does not need to reload script files with the same path, but a different hash. This allows for "efficient" retries. e.g.:
import * as foo1 from './foo.js#1';
import * as foo2 from './foo.js#2';
foo1 !== foo2 // not the same, but only caused one network request
TODO: document more hacks
Things that we can't fix:
Don't use this in production. It's horrible.
Modules can't really determine their path, so if one of your dependenies is from a 302 etc, all bets are off
Runtime require()
(i.e., not run on initial import) calls will fail if the code isn't available
Things that we can fix:
Built-in Node packages don't work (fs
, path
etc)
We should coalesce multiple failures to require()
(just return null
until an actual error occurs) and request further code in parallel
This code is forked from cjs-faker, and still supports AMD, but calling an unplanned require()
from within define()
doesn't work yet