{"id":17830,"library":"netjet","title":"Netjet Express Preload Middleware","description":"Netjet is an Express.js middleware designed to automatically inject `<link rel=\"preload\">` headers into HTML responses. These headers enable web browsers to perform early resource fetching, which can significantly improve page load performance by fetching critical assets like scripts, styles, and images before the browser's main parsing engine discovers them. The package is currently at version 1.4.0 and appears to be in an active maintenance state, with recent updates focusing on bug fixes and additional preload attributes. It differentiates itself by offering automatic, configurable scanning of HTML responses for subresources to preload, and leverages an `lru-cache` for efficient caching of resource analysis. Its primary use case is optimizing web application delivery for HTTP/2 and modern browsers.","status":"active","version":"1.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/cloudflare/netjet","tags":["javascript","express","middleware","link","preload"],"install":[{"cmd":"npm install netjet","lang":"bash","label":"npm"},{"cmd":"yarn add netjet","lang":"bash","label":"yarn"},{"cmd":"pnpm add netjet","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency as Netjet functions as an Express.js middleware.","package":"express","optional":false},{"reason":"Used internally for caching resource analysis; configurable via Netjet's options.","package":"lru-cache","optional":false}],"imports":[{"note":"Netjet is primarily a CommonJS module. Attempting a direct ESM import (e.g., in a `type: module` project) will likely result in a `TypeError: require is not a function` or similar unless transpiled or configured for interoperability.","wrong":"import netjet from 'netjet';","symbol":"netjet","correct":"const netjet = require('netjet');"},{"note":"While Netjet does not explicitly ship TypeScript types in its `package.json`, this JSDoc pattern provides type hinting for the options object in JavaScript projects. If a `@types/netjet` package were available, `import type { NetjetOptions } from 'netjet'` would be the TypeScript equivalent.","symbol":"NetjetOptions","correct":"/** @typedef {import('netjet').NetjetOptions} NetjetOptions */"},{"note":"The `netjet` function must be called (e.g., `netjet()`) to return the actual Express middleware. Passing `netjet` directly without invoking it will lead to an error or unexpected behavior as `app.use` expects a function returning the middleware.","wrong":"app.use(netjet);","symbol":"netjet() middleware","correct":"app.use(netjet({ directives: ['nopush'] }));"}],"quickstart":{"code":"const express = require('express');\nconst netjet = require('netjet');\nconst path = require('path');\nconst fs = require('fs');\nconst app = express();\nconst port = 1337;\nconst root = path.join(__dirname, 'public'); // Assuming a 'public' folder\n\n// Create a 'public' directory and dummy files if they don't exist\nif (!fs.existsSync(root)) {\n  fs.mkdirSync(root);\n}\nfs.writeFileSync(path.join(root, 'style.css'), 'body { color: blue; }');\nfs.writeFileSync(path.join(root, 'image.png'), '/* dummy image content */');\nfs.writeFileSync(path.join(root, 'script.js'), 'console.log(\"Script loaded!\");');\n\napp\n  .use(netjet({\n    // Enable parsing for images, scripts, styles (often true by default, but explicit for clarity)\n    images: true,\n    scripts: true,\n    styles: true,\n    // Example option from v1.3.0 notes to add custom attributes\n    directives: ['nopush'],\n    // Recommended: configure an LRU cache to prevent unbounded memory usage\n    cache: { max: 500 }\n  }))\n  .use(express.static(root)) // Serve static files after Netjet has a chance to process responses\n  .get('/', (req, res) => {\n    res.send(`\n      <!DOCTYPE html>\n      <html>\n      <head>\n        <title>Netjet Demo</title>\n        <link rel=\"stylesheet\" href=\"/style.css\">\n      </head>\n      <body>\n        <h1>Hello from Netjet!</h1>\n        <img src=\"/image.png\" alt=\"demo image\">\n        <script src=\"/script.js\"></script>\n      </body>\n      </html>\n    `);\n  })\n  .listen(port, () => {\n    console.log(`Netjet demo app listening on http://localhost:${port}`);\n    console.log(`Open http://localhost:${port} in your browser and inspect network/headers for preload links.`);\n  });\n","lang":"javascript","description":"Demonstrates how to integrate Netjet middleware into an Express.js application to automatically generate `Link` preload headers for static assets like CSS, images, and JavaScript files, including custom attributes and cache configuration."},"warnings":[{"fix":"Regularly review release notes for updates and thoroughly test against new versions before deploying to production. Consider pinning to specific patch versions (`~1.x.x`) to mitigate unexpected changes.","message":"The package is marked as 'stability-experimental' in its README badge. While actively maintained, this suggests the API might evolve, and future versions could introduce breaking changes or significant behavioral shifts without strict adherence to semantic versioning for major increments.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Upgrade to `netjet@1.1.3` or higher to ensure proper URL encoding in `Link` headers.","message":"Prior to version 1.1.3, URLs included in generated `Link` preload headers were not consistently or correctly encoded. This could lead to malformed headers, HTTP/2 push failures, or browsers failing to fetch preloaded resources, especially for URLs containing special characters.","severity":"breaking","affected_versions":"<1.1.3"},{"fix":"Ensure `app.use(netjet(options))` is invoked early in your Express middleware chain, preceding any middleware responsible for serving the HTML content it needs to analyze.","message":"Netjet relies on intercepting and modifying the HTML response to inject preload headers. It must be placed *before* any middleware that serves the HTML content (e.g., `express.static`, templating engines, or routes sending HTML). If placed after, it will not be able to process the response and add headers.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always configure a `cache.max` option with an appropriate integer value (e.g., `netjet({ cache: { max: 500 } })`) to prevent unbounded cache growth and potential out-of-memory errors in long-running applications.","message":"The `cache` option, which uses `lru-cache` internally, can lead to uncontrolled memory growth if `cache.max` is not configured. Without a maximum number of items, the cache will continuously store resource analysis results, potentially consuming excessive memory over time.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"You must invoke `netjet()` to obtain the middleware function, even if you don't pass any options. Correct usage is `app.use(netjet())` or `app.use(netjet({ /* options */ }))`.","cause":"The `netjet` package exports a function that *returns* the middleware, not the middleware function directly.","error":"TypeError: app.use() requires middleware functions but got a [object Undefined]"},{"fix":"Verify that `netjet` is placed *before* your static file server (`express.static`) and other HTML-serving routes. Also, check the `netjet` options; ensure that `images: true`, `scripts: true`, and `styles: true` are explicitly set if you want those resources to be preloaded.","cause":"This typically occurs if the `netjet` middleware is positioned incorrectly in the Express middleware chain (after content has been served) or if the asset-specific options (`images`, `scripts`, `styles`) are disabled.","error":"No preload headers are generated, despite serving HTML with assets."},{"fix":"Ensure `netjet` is placed early in the middleware chain, specifically before any middleware or route handlers that might explicitly call `res.send()`, `res.end()`, or `res.setHeaders()` in a way that bypasses Netjet's interception mechanism.","cause":"While Netjet uses response hijacking to mitigate this, incorrect placement or interaction with other middleware that eagerly sends headers can still cause this error if Netjet attempts to modify headers after the response stream has begun.","error":"ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}