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

webrun

v4.0.0

Published

A custom module loader and global shim for Node to make it compatible with the browser.

Downloads

12

Readme

WebRun

A custom module loader and global shim for Node to make it compatible with the browser.

The goal is to make code that works in browsers first, but can also run anywhere that Node runs.

**NOTE: The module has migrated from @rangermauve/webrun to just webrun

Usage:

# Install the CLI
npm install -g webrun

# Run it without installing globally
npx webrun "https://rangermauve.hashbase.io/example.js"

# Load a module from the web and log to the console
webrun "https://rangermauve.hashbase.io/example.js"

# Run a local file
webrun ./example.js

Then in your JS:

// Load code from an HTTPS server
import example from "https://rangermauve.hashbase.io/esm.js";

// Load from the dat network
// Requires the `webrun-plugin-dat` module to be installed
import datExample from "dat://rangermauve.hashbase.io/esm.js";

// Load from the IPFS network. Might not always be online.
// Requires the `webrun-plugin-ipfs` module to be installed
import ipfsExample from "ipfs://QmTWdgJtp3fXaszsomragX8dPXsqWe5c8uQETy6NkFJ7xA";

example();
datExample();
ipfsExample();

You can opt-into dat and IPFS support by installing the webrun-plugin-dat or webrun-plugin-ipfs modules.

You can start a REPL using:

webrun

Then you can load modules using the new dynamic import syntax.

This will return a promise that contains all the exported properties.

If you want to load the default export you can use something like the following:

let {default: example} = await import("https://rangermauve.hashbase.io/esm.js")

example()

You can enable the require global by adding the --allow-require flag. This is disabled by default to encourage use of import and to limit what scripts can do. This behaves differently from the usual require in that it's a global and always requires relative to the current working directory. Instead of adding allow-require, though, you should use webrunify to build your CommonJS dependencies into a single ESM-compatible bundle.

STDIO

You can opt-into input from STDIN and output to STDOUT using self.onmessage and self.postMessage.

These are the same APIs that exist for iframes and WebWorkers which means that your worker code can potentially run in webrun and vice-versa.

// Get text from STDIN, uppercase it, send it to STDOUT
self.onmessage = (text) => self.postMessage((text+"").toUpperCase())

CLI arguments

We want to be as close to the web as possible, so instead of adding a non-standard global for CLI arguments, we pass them in as query string params.

You can access the URL of the current module using the new import.meta.url syntax.

For example, given the file example.js:

console.log(`My URL is: ${import.meta.url}`)

Running this:

webrun example.js --foo bar --fizz buzz

Will result in

My URL is file://whatever/the/path/us/example.js?foo=bar&fizz=buzz

You can access these arguemnts using the following

const url = new URL(import.meta.url)

const foo = url.searchParams.get('foo')
const fizz = url.searchParams.get('fizz')

Web API support

Here's a list of the APIs that are supported, or are going to be supported eventually. Feel free to open an issue if you have ideas about other APIs that can be added.

API

Plugins

Help it's not working!

  • Delete the .webrun folder in the current directory. This will clear the cache
  • If that doesn't work, raise an issue.

How it works:

The new experimental-modules feature in Node.js is great, but it currently only works with file: URLs.

This means that modules made for the web are totally incompatible with Node. As a result, there's now four environments to code against: The legacy web with script tags, the web with ESM, Legacy CommonJS modules, and ESM in Node.js.

Luckily, node's vm builtin module now has support for custom ESM loaders. This means that we can now create a context that's separated from Node's globals and use anything we want for loading the contents of modules.

That's exactly how this works. It intercepts calls to https:// imports, downloads the content to the ./.webrun/web-cache folder, and loads it with the VM module.

Some browser APIs have been added to the global scope so hopefully a lot of modules made for browsers should work here, too. Feel free to open an issue to add your favorite missing browser API.

In addition to loading content from https:// URLs, this loader also supports dat:// URLs. This way you can download code right from the peer to peer web!

You can still load Node modules by using require, but this should only be done for APIs that you absolutely can't get on the web because otherwise your code won't be portable to the web.

PRs for additional protocols are welcome! All you need is an async function that takes a URL, and returns the file content string.

Roadmap:

  • [x] Able to load from the filesystem
  • [x] Able to load HTTPS URLs
  • [x] Able to load Dat URLs
  • [x] Able to load using reqire (behind a flag)
  • [ ] Browser APIs
  • [x] Dat protocol support
    • [x] Load from Dat URLs
    • [x] DatArchive global
    • [ ] Experimental Beaker APIs (does it make sense?)
  • [x] IPFS
    • [x] Load from IPFS URLs
    • [x] Load from IPNS URLs
    • [x] ipfs global
  • [x] CLI arguments: Add them to searchParams for the URL being loaded