A Connect-style and Karma middleware for resolving ES-module imports and exports to node_modules

Usage no npm install needed!

<script type="module">
  import adobeEsModulesMiddleware from 'https://cdn.skypack.dev/@adobe/es-modules-middleware';



This middleware provides a connect-style middleware and a Karma middleware factory for resolving ES-module import and export statements on the fly.

Browsers do not currently support 'bare module specifiers' such as import * from 'chai'. The browser does not know how to resolve 'chai' since its not an absolute URI or a relative URI. So results in this error message:

Uncaught TypeError: Failed to resolve module specifier "chai". Relative references must start with either "/", "./", or "../".

There are several proposals to fix this, one such proposal is import-maps (repo). The workaround to this would involve using relative references for imports, this is fine when you're not using any node_module based dependencies, but when you want to import some external lib you end up having to bundle your modules to resolve these dependencies or import through complete relative paths to your node_modules folder.

This middleware provides an alternative to that by rewriting the import and export statements served on the fly to resolve the paths to a node_module folder. This implementation is based heavily on the es-module-devserver middleware by myfreeweb with some small tweaks to make it compatible with Karma.

In general you would NOT use this middleware in any production service, where it is expected that you would use bundling to resolve these issues. This middleware is intended for development purposes so the complications of a bundled development environment can be avoided and ES-modules can be used natively. Polymers CLI tools also implement this behavior, for additional context see this documentation.


There is a complete working example projection in the examples folder which implements a web component using the LitElement library as a dependency.


  • NodeJS >= 8.10.0


npm install --save-dev @adobe/es-modules-middleware


The module can be included and used as a connect middleware by providing it with a map of url base path to file system path from which to serve files. Any files served through the middleware will be processed to resolve import/export paths properly.

const esModuleMiddleware = require('@adobe/es-modules-middleware');
const express = require('express');

const app = express();
const port = 3000;

const rootPath = path.resolve(__dirname);

        paths: {
            '/node_modules': path.join(rootPath, 'node_modules'),

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

It can also be used in Karma to aid in testing es-modules in the browser. Here's an example of using this middleware in combination with the karma-web-components framework to test web components using HTML test pages:

const path = require('path');

module.exports = function(config) {
        basePath: '.',
        plugins: ['karma-*', require('@adobe/es-modules-middleware')],
        frameworks: ['mocha', 'chai', 'sinon', 'web-components'],
        middleware: ['es-modules'],
        esModulesMiddleware: {
            // NOTE: add any paths which you wish to be processed and served by the middleware
            paths: {
                '/': __dirname,
                '/node_modules': path.join(__dirname, 'node_modules'),
        files: [
                pattern: '**/*.test.html',
                watched: false,
                included: false,
                served: true,
                pattern: '**/test/*.js',
                watched: true,
                included: false,
                served: false,
        // NOTE: proxy node_modules paths to base so they get picked up by the middleware
        proxies: {
            '/node_modules/': '/base/node_modules/',
        reporters: ['mocha'],


We'd be very grateful if you contributed to the project! Check out our contribution guidelines for more information.