npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cjs-loader

v0.1.0

Published

Transitively includes commonJS modules for use on the web

Downloads

8,804

Readme

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.

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+.

Usage

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>

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 we wrap.

Implementation

  1. Stub out module.exports, require() etc.
  2. Load the target module as an ES6 module^1
  • If a further dependency is unavailable in require(), throw a known exception^2
  • Catch in a global handler, and load the dependency via step 2
  • Retry running the target module when done

^1 more or less

^2 require() is synchronous, so we can't block to load more code

Specific Hacks

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

Notes

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

TODOs

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