ES Module Serve

0.3.1 · active · verified Wed Apr 22

esmoduleserve is a lightweight, shim HTTP development server designed for serving ES modules directly in the browser without requiring a bundling step. Currently at version 0.3.1, it focuses on providing a direct ES module development experience by rewriting import specifiers on-the-fly to precise, resolved paths. It implements a Node-like module resolution algorithm, prioritizing `"module"` or `"jsnext"` fields in `package.json` over `"main"`. This differentiates it from more comprehensive dev servers (e.g., Vite, Webpack dev server) that typically integrate bundling, transpilation, and hot module reloading, by offering a simpler, unbundled approach for native ES module workflows. Its release cadence is likely infrequent, as it serves a specific, focused niche for rapid development and testing of native ES modules.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `esmoduleserve` as HTTP middleware into a basic Node.js server. It sets up a server that serves static files from a 'demo' directory and uses `ModuleServer` to rewrite and serve ES modules from the same directory under the `/_m/` path. This setup is ideal for local development and testing of native ES modules in the browser without a separate bundling step.

const http = require('http');
const { ModuleServer } = require('esmoduleserve/moduleserver');
const path = require('path');
const fs = require('fs');

// Create a 'demo' directory and place an 'index.html' and 'my-module.js' inside for testing.
// Example index.html: <script type="module" src="/_m/my-module.js"></script>
// Example my-module.js: export const message = 'Hello from ES module!'; console.log(message);
const rootDir = path.join(__dirname, 'demo'); 

const moduleServer = new ModuleServer({
  root: rootDir,
  maxDepth: 2, // Allow access to modules one parent directory deep (e.g., for monorepos)
  prefix: '_m' // The URL prefix for rewritten module scripts
});

const server = http.createServer((req, res) => {
  console.log(`Request: ${req.method} ${req.url}`);

  // First, try to handle the request as a module through esmoduleserve
  if (moduleServer.handleRequest(req, res)) {
    return; // Request was handled
  }

  // If not a module request, serve static files (e.g., index.html)
  const requestedPath = req.url === '/' ? '/index.html' : req.url;
  const filePath = path.join(rootDir, requestedPath);

  fs.readFile(filePath, (err, data) => {
    if (err) {
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('Not Found: ' + requestedPath);
      console.error(`File not found: ${filePath}`);
      return;
    }

    let contentType = 'text/plain';
    if (filePath.endsWith('.html')) contentType = 'text/html';
    else if (filePath.endsWith('.js')) contentType = 'application/javascript';
    else if (filePath.endsWith('.css')) contentType = 'text/css';

    res.writeHead(200, { 'Content-Type': contentType });
    res.end(data);
  });
});

const port = process.env.PORT ?? 8080;
const host = process.env.HOST ?? 'localhost';

server.listen(port, host, () => {
  console.log(`esmoduleserve server running at http://${host}:${port}/`);
  console.log(`Serving static files from: ${rootDir}`);
  console.log(`Module scripts are available under the /_m/ prefix (e.g., http://${host}:${port}/_m/my-module.js)`);
});

view raw JSON →