Fetching latest headlinesโ€ฆ
Building Pure Frontend Formatter Tools: Why Node.js Libraries Fail in the Browser
NORTH AMERICA
๐Ÿ‡บ๐Ÿ‡ธ United Statesโ€ขJune 29, 2026

Building Pure Frontend Formatter Tools: Why Node.js Libraries Fail in the Browser

0 views0 likes0 comments
Originally published byDev.to

Building a pure-frontend online formatter tool site seems straightforward: import a formatting library โ†’ call it in the browser.
In practice, three commonly-used libraries all failed in the browser.

The Problem List

During development, three popular libraries all broke in the browser:

Library Purpose Browser Behavior
terser JS minification โŒ fs is not defined
html-minifier-terser HTML minification โŒ fs is not defined
xml-formatter v3.7.0 XML formatting โš ๏ธ ESM/CJS interop issues

terser: The fs Module Problem

Reproduction

import { minify } from 'terser'

// Called in a browser component
const result = await minify(code, { compress: true, mangle: true })

Build succeeds. Runtime error:

Uncaught ReferenceError: fs is not defined
    at Object.readSourceMap (terser/dist/bundle.min.js:1:xxxxx)

Root Cause

terser internally calls fs.readFileSync to read source map files. Fine in Node.js โ€” fs doesn't exist in browsers.

Even though terser's package.json declares a browser field for conditional exports, some internal modules still reference fs, and webpack/SWC tree-shaking doesn't fully eliminate them.

Solution: Lightweight Regex Minifier

function minifyJs(code) {
  return code
    // Remove single-line comments
    .replace(/\/\/.*$/gm, '')
    // Remove multi-line comments
    .replace(/\/\*[\s\S]*?\*\//g, '')
    // Collapse whitespace
    .replace(/\s+/g, ' ')
    .trim()
    // Remove spaces around punctuation
    .replace(/\s*([,;{}()\[\]])\s*/g, '$1')
    // Remove blank lines
    .replace(/\n\s*\n/g, '\n')
}

Advantages:

  • Zero dependencies, pure JS
  • Works in both browser and Node.js
  • Tiny codebase (20 lines)
  • More than sufficient for a tool site's JS minification

Disadvantages:

  • Lower compression ratio than Terser
  • No AST-level optimizations (variable mangling, dead code elimination)

But for "user pastes code in browser to see minified output," regex is more than enough.

html-minifier-terser: Same fs Problem

Problem

Same root cause as terser. html-minifier-terser calls fs internally to read local files for <script src="..."> etc.

Solution

function minifyHtml(html) {
  return html
    .replace(/<!--[\s\S]*?-->/g, '')   // Remove HTML comments
    .replace(/>\s+</g, '><')            // Collapse whitespace between tags
    .replace(/\s*=\s*/g, '=')           // Tighten attribute values
    .replace(/ {2,}/g, ' ')             // Collapse multiple spaces
    .trim()
}

xml-formatter: ESM/CJS Interop Issues

Problem

This library actually supports the browser. But v3.7.0's export structure is messy:

// xml-formatter v3.7.0 actual exports
export default function formatXml(...) { ... }  // default export
export function minify(xml) { ... }             // named export

After SWC compilation (CJS wrapper), the default export becomes exports.default. Direct import formatXml from 'xml-formatter' sometimes returns a non-function object.

Debugging

// โŒ formatXml is undefined at runtime
import formatXml from 'xml-formatter'
import { minify } from 'xml-formatter'  // โœ… This works

// โœ… Correct approach
import _formatXml from 'xml-formatter'
const formatXml = _formatXml.default || _formatXml

Final Solution

// Format with xml-formatter (interop handled)
import _formatXml from 'xml-formatter'
const formatXml = _formatXml.default || _formatXml

// Minify with custom function (xml-formatter's minify is inconsistent across versions)
function minifyXml(xml) {
  return xml
    .replace(/<!--[\s\S]*?-->/g, '')
    .replace(/\s+/g, ' ')
    .replace(/>\s+</g, '><')
    .trim()
}

Library Selection Checklist

Before choosing a library, run through this:

  1. Does package.json have a browser field? โ€” Yes โ†’ browser-adapted
  2. Does the dependency tree include fs, path, net? โ€” Yes โ†’ can't use in browser
  3. Does the npm page mention "Browser Support"?
  4. Search GitHub Issues for "browser", "client-side" โ€” Any similar reports?
  5. Test locally with a simple HTML + <script type="module">

Recommended Libraries for Pure Frontend Tools

Function Library Why
JS/HTML/XML formatting js-beautify Explicit browser build support
CSS minification csso Pure JS, no Node.js deps
JSON formatting JSON.stringify/parse Native API
SQL formatting sql-formatter Browser-compatible
YAML formatting js-yaml Browser-compatible

Core Lesson

Don't judge a library by its name. Judge it by its runtime dependencies.
"js" in the name doesn't mean it runs in browsers. "node" in the name doesn't mean it can't.

Project

utlkit.com โ€” All formatter tools run purely in the browser. The solutions above are running stably in production.

Comments (0)

Sign in to join the discussion

Be the first to comment!