{"id":17472,"library":"sirv","title":"Sirv Static File Server Middleware","description":"Sirv is an optimized and lightweight middleware designed for serving static assets in Node.js applications, compatible with frameworks like Polka, Express, and native HTTP/S servers. The current stable version is 3.0.2. Its primary differentiator is a significant performance advantage over alternatives like `serve-static` because it pre-scans and caches file system information upfront (when not in 'dev' mode), avoiding costly per-request file system checks. This makes it very efficient for production deployments. Releases are active, with recent patches and a major version upgrade to v3.0.0 that introduced native ESM support and a higher Node.js baseline. It ships with TypeScript types, enhancing developer experience.","status":"active","version":"3.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/lukeed/sirv","tags":["javascript","typescript"],"install":[{"cmd":"npm install sirv","lang":"bash","label":"npm"},{"cmd":"yarn add sirv","lang":"bash","label":"yarn"},{"cmd":"pnpm add sirv","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Commonly used HTTP server framework in examples, highly performant.","package":"polka","optional":true},{"reason":"Used in quickstart example for GZIP compression, a common companion for static asset serving.","package":"compression","optional":true}],"imports":[{"note":"Since v3.0.0, sirv is primarily designed for ESM usage and requires Node.js 18+. While CJS might still work in some setups, native ESM import is the recommended and type-correct way. Using `require` with `type: module` in `package.json` will result in an error.","wrong":"const sirv = require('sirv');","symbol":"sirv","correct":"import sirv from 'sirv';"},{"note":"TypeScript type for SirvOptions, useful for explicit type annotations when configuring the middleware.","symbol":"SirvMiddlewareFunction","correct":"import type { SirvOptions } from 'sirv';"},{"note":"The default export is the `sirv` factory function itself, which returns the middleware. There are no other named exports typically used directly by consumers.","symbol":"sirv","correct":"import sirv from 'sirv';"}],"quickstart":{"code":"import polka from 'polka';\nimport sirv from 'sirv';\nimport compression from 'compression';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst publicDir = path.join(__dirname, 'public');\n\n// Create a dummy 'public' directory and an index.html file for demonstration\nimport { promises as fs } from 'node:fs';\nasync function setupPublicDir() {\n  await fs.mkdir(publicDir, { recursive: true });\n  await fs.writeFile(path.join(publicDir, 'index.html'), '<h1>Hello from Sirv!</h1><p>This is a static file.</p>');\n  await fs.writeFile(path.join(publicDir, 'styles.css'), 'body { font-family: sans-serif; background-color: #f0f0f0; }');\n}\n\n// Initialize sirv handler\nconst assets = sirv(publicDir, {\n  maxAge: 31536000, // 1 year\n  immutable: true,\n  gzip: true, // Look for precompiled .gz files\n  dotfiles: false, // Don't serve dotfiles\n  dev: process.env.NODE_ENV === 'development' // Enable dev mode for caching control\n});\n\nconst PORT = process.env.PORT ?? 3000;\n\nawait setupPublicDir();\n\npolka()\n  .use(compression()) // Apply compression before sirv\n  .use(assets) // Serve static assets\n  .use('/api', (req, res) => {\n    res.setHeader('Content-Type', 'application/json');\n    res.end(JSON.stringify({ message: 'This is an API endpoint', timestamp: Date.now() }));\n  })\n  .listen(PORT, (err) => {\n    if (err) throw err;\n    console.log(`> Ready on http://localhost:${PORT}!`);\n    console.log(`> Serving static files from ${publicDir}`);\n  });","lang":"typescript","description":"This quickstart demonstrates how to set up `sirv` with `polka` and `compression` to serve static files from a 'public' directory. It highlights ESM usage, configuration options like `maxAge` and `dev` mode, and shows how to integrate it alongside other middleware. It dynamically creates a 'public' directory and files for immediate execution."},"warnings":[{"fix":"Upgrade Node.js to version 18 or higher (e.g., using nvm) or pin sirv to a 2.x version in your `package.json` (e.g., `\"sirv\": \"^2.0.0\"`).","message":"Sirv v3.0.0 and later require Node.js version 18 or higher. Projects running on older Node.js versions must either upgrade Node.js or remain on sirv v2.x.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Migrate your imports to use ESM syntax: `import sirv from 'sirv';`. Ensure your project is configured for ESM, typically by setting `\"type\": \"module\"` in `package.json` or using `.mjs` file extensions.","message":"Sirv v3.0.0 introduced native ESM support via an `exports` map, which changes how the package is imported. Direct `require()` statements in ESM contexts or projects with `\"type\": \"module\"` in `package.json` may break, resulting in `ERR_REQUIRE_ESM`.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure `opts.dev` is set to `false` or omitted (default is `false`) for production builds. A common pattern is `dev: process.env.NODE_ENV === 'development'`.","message":"Using `opts.dev: true` enables 'dev' mode, which disables file caching and performs file system checks on every request. This is highly inefficient and should *never* be used in production environments, as it will severely degrade performance.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always provide an absolute path for `dir`, e.g., using `path.resolve(__dirname, 'public')` or `path.join(path.dirname(fileURLToPath(import.meta.url)), 'public')` for ESM.","message":"The `dir` option in `sirv(dir, opts)` expects a directory path. While it resolves relative paths based on `process.cwd()`, relying on `process.cwd()` can be brittle in complex deployment scenarios. Incorrect paths can lead to assets not being found.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your file structure does not have top-level files named identically to your static asset directory (e.g., if `dir` is 'public', do not have a file named 'public' in the root serving directory).","message":"Sirv v3.0.2 includes a patch to prevent serving top-level files that unexpectedly share a name with the configured static directory. If you previously relied on such a pattern for some edge cases, this behavior will now be prevented.","severity":"gotcha","affected_versions":">=3.0.2"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change `const sirv = require('sirv');` to `import sirv from 'sirv';` and ensure your project uses ES Modules correctly.","cause":"Attempting to `require('sirv')` in a Node.js environment configured for ES Modules (`\"type\": \"module\"` in `package.json`) after upgrading to sirv v3+.","error":"ERR_REQUIRE_ESM: require() of ES Module ... sirv/index.mjs not supported."},{"fix":"Verify the `dir` path is absolute and correct. Check if `opts.dotfiles` is `true` for dotfiles, and `opts.extensions` includes the necessary fallback extensions (e.g., `['html']` for `/foo` to find `/foo.html`). Also, ensure file permissions allow Node.js to read the files.","cause":"The `dir` option provided to `sirv()` is incorrect, or the requested file does not exist within that directory, or `opts.dotfiles` and `opts.extensions` are not configured to match the asset.","error":"GET /path/to/asset 404 Not Found"},{"fix":"Change the `PORT` variable in your quickstart code to an unused port (e.g., 8080, 5000) or ensure the conflicting process is stopped. You can also use a tool like `lsof -i :<PORT>` on Unix-like systems to identify the process.","cause":"Another process is already listening on the port that your `polka` (or other HTTP server) instance is trying to bind to.","error":"Error: Port 3000 is already in use"}],"ecosystem":"npm","meta_description":null}