{"id":17454,"library":"next-compose-middleware","title":"Next Compose Middleware","description":"next-compose-middleware is a library designed to simplify the creation of complex and declarative middleware for Next.js applications, particularly leveraging Next.js's Edge Runtime middleware. It enables developers to construct highly readable and maintainable middleware logic by composing multiple functions. The current stable version is 2.0.4, indicating active development with incremental releases. Key differentiators include its path-based middleware execution, allowing for \"Nested Middleware\" behavior, and the ability to compose functions with early exit mechanisms (`breakAll`, `breakOnce`) for fine-grained control over execution flow. This approach helps in organizing middleware into logical, reusable units, enhancing maintainability for applications with intricate authorization, authentication, or request transformation requirements in a single `middleware.ts` file.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/kj455/next-compose-middleware","tags":["javascript","next.js","middleware","edge","typescript"],"install":[{"cmd":"npm install next-compose-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add next-compose-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add next-compose-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for Next.js middleware functionality, specifically v12.2.0+ for stable middleware support.","package":"next","optional":false}],"imports":[{"note":"The library is primarily used in Next.js middleware files, which are typically ESM. Avoid CommonJS `require()` syntax.","wrong":"const composeMiddleware = require('next-compose-middleware');","symbol":"composeMiddleware","correct":"import { composeMiddleware } from 'next-compose-middleware';"},{"note":"This type is used for type-checking custom middleware functions. It should be imported as a type, not a runtime value.","symbol":"ComposableMiddleware","correct":"import type { ComposableMiddleware } from 'next-compose-middleware';"}],"quickstart":{"code":"import { NextRequest, NextResponse } from 'next/server';\nimport { composeMiddleware, ComposableMiddleware } from 'next-compose-middleware';\n\n// Example middleware functions\nconst root1: ComposableMiddleware = async (req, res) => {\n  console.log('Executing root1 for path:', req.nextUrl.pathname);\n  // Example: Modify response headers or cookies\n  res.headers.set('X-Root-Middleware-1', 'processed');\n  return res;\n};\n\nconst root2: ComposableMiddleware = async (req, res) => {\n  console.log('Executing root2 for path:', req.nextUrl.pathname);\n  return res;\n};\n\nconst foo: ComposableMiddleware = async (req, res) => {\n  console.log('Executing foo for path:', req.nextUrl.pathname);\n  return res;\n};\n\nconst fooBar: ComposableMiddleware = async (req, res) => {\n  console.log('Executing fooBar for path:', req.nextUrl.pathname);\n  // Early exit example: if a condition is met, stop further middleware\n  if (req.nextUrl.searchParams.has('exit')) {\n    console.log('Early exiting from fooBar!');\n    return res; // Returning res without breakAll/breakOnce continues chain, but no further changes here.\n  }\n  return res;\n};\n\nconst fooId: ComposableMiddleware = async (req, res) => {\n  const id = req.nextUrl.pathname.split('/')[2];\n  console.log('Executing fooId for path:', req.nextUrl.pathname, 'ID:', id);\n  return res;\n};\n\nconst fooIdBaz: ComposableMiddleware = async (req, res) => {\n  console.log('Executing fooIdBaz for path:', req.nextUrl.pathname);\n  return res;\n};\n\nconst fooQux: ComposableMiddleware = async (req, res) => {\n  console.log('Executing fooQux for path:', req.nextUrl.pathname);\n  return res;\n};\n\nexport default async function middleware(req: NextRequest) {\n  console.log(`\\n--- Incoming Request for ${req.nextUrl.pathname} ---`);\n  \n  // Compose middleware based on paths\n  return composeMiddleware(req, NextResponse.next(), {\n    scripts: [root1, root2], // Applied to all matching paths\n    '/foo': {\n      scripts: [foo], // Applied to /foo and its children\n      '/bar': {\n        scripts: [fooBar], // Applied to /foo/bar and its children\n      },\n      '/[id]': { // Dynamic segment\n        scripts: [fooId], // Applied to /foo/:id and its children\n        '/baz': [fooIdBaz] // Applied to /foo/:id/baz\n      },\n      '/qux': [fooQux] // Applied to /foo/qux\n    }\n  });\n}","lang":"typescript","description":"Demonstrates how to set up `next-compose-middleware` with path-based execution for different routes and compose multiple middleware functions, including an example of conditional logic for early exit."},"warnings":[{"fix":"Upgrade your Next.js project to version 12.2.0 or newer to ensure compatibility and access to stable middleware features.","message":"This library requires Next.js v12.2.0 or higher for stable middleware support. Older versions of Next.js do not fully support the middleware API that this library leverages, especially regarding nested middleware, which was deprecated in favor of a single root middleware file.","severity":"gotcha","affected_versions":"<12.2.0 of next"},{"fix":"Carefully choose between `breakAll(res)` to completely halt middleware execution or `breakOnce(res)` to only skip siblings in the current path segment, based on your desired control flow.","message":"Misunderstanding 'breakAll' vs 'breakOnce' in early exit scenarios can lead to unexpected middleware execution flow. 'breakAll' completely halts all subsequent middleware in the entire composition, while 'breakOnce' only stops subsequent middleware at the current nesting level, allowing parent or sibling middleware branches to continue.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Avoid Node.js-specific APIs within your middleware. For dynamic environment variables or complex logic, consider using API routes or native Web APIs like `fetch`. Ensure environment variables are configured correctly for the Edge runtime.","message":"Next.js Middleware functions (and thus ComposableMiddleware) run in the Edge Runtime, which has limitations compared to Node.js environments. This means certain Node.js APIs and global objects are unavailable, and environment variables are often resolved at build time, not runtime.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure you are using ESM `import { composeMiddleware } from 'next-compose-middleware';` syntax, especially in Next.js middleware files which are typically ESM. Verify the symbol name is correct and not a default export.","cause":"Attempting to import `composeMiddleware` using CommonJS `require()` syntax in an ESM context, or an incorrect named import.","error":"TypeError: next_compose_middleware_1.composeMiddleware is not a function"},{"fix":"Always ensure your `ComposableMiddleware` functions, especially those implementing early exit logic, explicitly return a `NextResponse` instance (e.g., `return res;`, `return breakAll(res);`, or `return breakOnce(res);`).","cause":"A middleware function is not returning a valid `NextResponse` object, causing subsequent middleware to receive an undefined or invalid response object.","error":"TypeError: Cannot read properties of undefined (reading 'cookies') or 'headers' is undefined"}],"ecosystem":"npm","meta_description":null}