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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@surf/forgepack

v0.1.0

Published

Webpack configuration factories for browser, SSR, and library builds — batteries included, no config file sprawl.

Downloads

27

Readme

forgepack

Webpack configuration factories for browser, SSR, and library builds.

Webpack configs sprawl. A real application ends up with several hundred lines of loader rules, plugin wiring, cache config, and mode branching — then the SSR build duplicates most of it with a handful of differences, and the shared component library duplicates it again. forgepack packages that whole surface as three functions you call with your project's paths.

// webpack.config.js
import { browserConfig } from '@surf/forgepack'

export default browserConfig({
  appDirectory: import.meta.dirname,
  appSrc: 'src',
  appBuild: 'build',
})

That returns a function webpack calls with its --env values, so webpack --env mode=production gets a production config and webpack serve --env mode=development gets a dev-server config, from the same file.

Install

npm install --save-dev @surf/forgepack

Requires Node 20+. The package is native ESM — it ships no build step and no CJS bundle. Use webpack.config.mjs, or set "type": "module" in your package.json.

What it builds

browserConfig(options) — client bundles

The full application build: babel/TypeScript via babel-loader (with a custom loader wrapper that lets webpack override preset-env targets), CSS/Sass with CSS Modules, PostCSS with preset-env + flexbugs-fixes + normalize, SVG via SVGR, asset inlining under a size threshold, web workers, HTML generation per page, a manifest, code splitting, filesystem caching, and Terser + css-minimizer for minification.

React Fast Refresh is wired automatically when the dev server has HMR enabled. Service worker precaching is available through workbox-webpack-plugin.

ssrConfig(options) — server bundles

target: 'node', dependencies externalized via webpack-node-externals (with CSS deliberately kept in the bundle, since Node cannot require a stylesheet), and the same style pipeline so server-rendered markup carries the right class names.

Unlike the other two, ssrConfig reads its mode from NODE_ENV at construction time rather than from webpack's --env.

libraryConfig(options) — distributable packages

Library output targets for publishing a package rather than an application.

Dev server

devServerConfig and friends under @surf/forgepack/utils cover HTTPS certificate resolution, host/port selection, the eval-source-map middleware, and a no-op service-worker middleware that stops a stale production service worker from hijacking local development.

Monorepo support

If your app lives in a yarn/npm workspace, forgepack finds the workspace root and works out which sibling packages your app actually depends on. Those packages' source directories are added to the babel-loader include paths and their node_modules to resolution, so you can consume workspace packages straight from source with no build step between them.

Opt in per-package via the workspaces block in your app's package.json:

{
  "workspaces": {
    "package-entry": "main:src",   // the package.json field pointing at source
    "development": true,           // use source in development builds
    "production": false            // use built output in production builds
  }
}

Outside a monorepo this degrades to a no-op — nothing to configure.

Requirements on your project

A few things forgepack expects rather than invents for you:

  • A browserslist config. The browser build compiles with target: 'browserslist', which webpack rejects outright if your project declares no browser targets. Add a browserslist key to package.json or a .browserslistrc.
  • NODE_ENV and ENV set. The configs wire webpack's EnvironmentPlugin without defaults, so a build with these unset fails loudly by design.
  • context defaults to process.cwd(). If you run webpack from somewhere other than your app root, pass context explicitly.

Provenance

forgepack is extracted from a private monorepo's internal webpack tooling. The extraction removed seven internal dependencies. For anyone auditing what is first-party here:

| Original internal dependency | Resolution | | --- | --- | | config | Real dependency on @cogs/config — signatures matched exactly, no shim needed | | casting | Vendored (src/vendor/casting.js) — resolveApp, getPublicUrlOrPath, formatWebpackMessages. The latter two originate in react-dev-utils (MIT) | | browserslist-config | Vendored (src/vendor/browserslist-utils.js), derived from @babel/helper-compilation-targets (MIT), plus a real browserslist dependency | | monorepo-utils | Vendored (src/vendor/workspace/) — only the workspace-discovery slice, with its locate-path dependency inlined | | basic-utils | Reimplemented (src/vendor/basic-utils.js) — two functions, existy and yn | | enums | Reimplemented (src/vendor/active-env.js) — the deployment-tier vocabulary, now read from ACTIVE_ENV | | node-pkg | Dropped. It existed only to proxy nested binaries around a private hoisting quirk. forgepack ships no bins; install webpack-cli directly |

An eighth dependency, the internal babel preset used to transpile node_modules, is reimplemented as src/presets/dependencies.js@babel/preset-env plus @babel/plugin-transform-runtime, which is what it always was underneath.

Nothing is stubbed. Every code path that shipped in the original ships here.

Deliberate changes

  • Native ESM, no build step. The original shipped dual CJS/ESM via a Babel build. forgepack publishes its source directly.
  • No bin entries. See node-pkg above.
  • Three bugs found and fixed during extraction, each covered by a test:
    • Builds crashed outside a git worktree (Docker, packed tarballs) because the version stamp shelled out to git rev-parse unguarded.
    • ssrConfig crashed on any non-monorepo project, passing a null workspace root into path.resolve.
    • Omitting the optional entries option crashed the browser and library factories, and the empty case emitted entry: [], which webpack rejects.

Development

npm install
npm run lint     # eslint
npm run build    # emit type declarations to types/
npm test         # vitest
npm run verify   # all three

The test suite validates every generated config against webpack's own options schema and compiles a real fixture bundle end to end.

License

MIT © Andrew Cates