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

koa-node-resolve

v1.0.0-pre.9

Published

Koa middleware that transforms Node package specifiers to relative paths

Downloads

24,364

Readme

koa-node-resolve

Middleware for Koa servers that resolves Node package specifiers in standard JS modules to relative paths for use on the web.

The following import uses a bare module specifier, which won't currently load natively in browsers (until import maps are available):

import { foo } from "stuff";

koa-node-resolve solves this problem by resolving stuff using the same rules as Node require(), and transforming the import specifier to a path that can be loaded natively by any browser that supports standard JS modules:

import { foo } from "./node_modules/stuff/index.js";

Because this is middleware, you can use it in a simple static file server as well as a proxy server sitting in front of a test server such as the one karma starts up. (See karma testing setup below.)

Note: HTML and JavaScript are parsed on every request for those content-types, it is intended for use in development context to facilitate build-free testing/iteration as opposed to in a high volume production web server.

Installation

$ npm install --save koa-node-resolve

Usage

Create your own mini-development server in file ./dev-server.js. This one depends on koa and koa-static, so you'll need to npm install --save-dev koa koa-static for your project to use it.

const Koa = require('koa');
const staticFiles = require('koa-static');
const { nodeResolve } = require('koa-node-resolve');

const server = new Koa()
  .use(nodeResolve())
  .use(staticFiles('.'))
  .listen(3000);
$ node dev-server.js

Now you can serve up your web assets and Node package specifiers will be transformed on request.

Configuration

nodeResolve(options={})

Options

  • root the on-disk directory that maps to the served root URL, used to resolve module specifiers on the filesystem. In most cases this should match the root directory configured in your downstream static file server middleware.

  • logger an alternative logger to use (console is the default). The logger will receive error() to record exceptions during parsing/transforming of JavaScript modules, warn() when a specifier is unresolvable, info() to report URLs with transformed content, debug() to report all Node module specifier resolutions. All log messages are prefixed with [koa-node-resolve]. To disable all logging, provide false.

  • logLevel (defaults to warn) sets the minimum level of severity for an event to be logged. Options in order of severity: debug, info, warn, error.

  • htmlParser function to convert HTML source to a Parse5.DefaultTreeNode. The default implementation is equivalent to:

    const { parse } = require('parse5');
    
    nodeResolve({ htmlParser: parse);
  • htmlSerializer function to generate string from AST of Parse5.DefaultTreeNode. The default implementation is equivalent to:

    const { serialize } = require('parse5');
    import { removeFakeRootElements } = 'koa-node-resolve/lib/support/parse5-utils';
    
    nodeResolve({ htmlSerializer: (ast) => {
      // Don't emit parse5's hallucenated <html>, <head> and <body> tags.
      removeFakeRootElements(ast);
      return serialize(ast); 
    });

    Maybe you don't want to remove the generated <html>, <head> and <body> tags-- you can provide an htmlSerializer function that doesn't do that then.

  • jsParser function to convert JavaScript module source to a Babel.Node. The default implementation is equivalent to:

    const { parse } = require('@babel/parse');
    
    nodeResolve({
      jsParser: (source) => parse(source, {
        sourceType: 'unambiguous'
      })
    });

    The most common reason to provide your own JavaScript parser function is to enable the middleware to process content which has syntax requiring babel syntax plugins that your project is making use of, such as decorators, dynamic imports or import meta etc.

  • jsSerializer function to generate output string from AST of Babel.Node. The default implementation is equivalent to:

    const serialize = require('@babel/generator');
    
    nodeResolve({ jsSerializer: (ast) => serialize(ast).code })

    The @babel/generator documentation shows many options available for tweaking output. Maybe you want to generate source maps and embed them in the response; you could do that here.

Karma Testing Setup

In a karma setup, your karma.conf.js file could create the Koa server before exporting the config. The Koa server uses the koa-proxy package (therefore npm install --save-dev koa-proxy) in between the browser and the Karma server, transforming all the Node package specifiers encountered in documents located under the base/ URL namespace, which is a special Karma behavior for partitioning the package resources under test from Karma support resources.

const Koa = require('koa');
const mount = require('koa-mount');
const proxy = require('koa-proxy');
const { nodeResolve } = require('koa-node-resolve');

const server = new Koa()
  .use(mount('/base', nodeResolve()))
  .use(proxy({ host: 'http://127.0.0.1:9876' }))
  .listen(9877);

module.exports = config => {
  config.set({
    upstreamProxy: {
      hostname: '127.0.0.1',
      port: 9877,
    },
    files: [
      { pattern: 'test/**/*.js', type: 'module' },
      { pattern: '**/*.js', included: false },
      { pattern: 'node_modules/**/*', included: false },
    ],
  });
};

In this setup, the Koa proxy server that runs the Node resolution middleware will be on port 9877 and the Karma server will be on port 9876, so be sure to open up http://127.0.0.1:9877 in your browser rather than http://127.0.0.1:9876. The upstreamProxy configuration block tells Karma, when it launches browsers, to points them to the Koa app instead of directly to the Karma server.

Note also that in this configuration its important to tell Karma that the test files are modules and to serve those up, but to list the other files, like the ones in node_modules as available but not "included" (i.e. Karma can serve them by request, but shouldn't add inline dependencies on them when generating its "context" HTML).