{"id":14976520,"url":"https://github.com/lukeed/webpack-route-manifest","last_synced_at":"2025-06-20T14:10:43.331Z","repository":{"id":49516021,"uuid":"202962990","full_name":"lukeed/webpack-route-manifest","owner":"lukeed","description":"Generate an asset manifest file, keyed by route patterns!","archived":false,"fork":false,"pushed_at":"2021-06-16T02:32:11.000Z","size":21,"stargazers_count":129,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-04T17:10:30.896Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukeed.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-18T05:18:51.000Z","updated_at":"2025-05-17T10:23:03.000Z","dependencies_parsed_at":"2022-09-12T19:43:26.534Z","dependency_job_id":null,"html_url":"https://github.com/lukeed/webpack-route-manifest","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/lukeed/webpack-route-manifest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fwebpack-route-manifest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fwebpack-route-manifest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fwebpack-route-manifest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fwebpack-route-manifest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukeed","download_url":"https://codeload.github.com/lukeed/webpack-route-manifest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fwebpack-route-manifest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260959044,"owners_count":23088816,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T13:54:01.112Z","updated_at":"2025-06-20T14:10:38.315Z","avatar_url":"https://github.com/lukeed.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# webpack-route-manifest\n\n\u003e Generate an asset manifest file, keyed by route patterns!\n\n***The Context***\n\nModern applications (should!) take advantage of route-based code splitting. This enables an application to be compartmentalized into smaller, highly relevant \"chunks\" for a particular section or feature of that application. By default, this means that your application is only giving its client(s) the code it needs for that page.\n\n***The Problem***\n\nWhile amazing, this isn't (yet) a perfect solution. The client wants to navigate to other pages!\n\nIn a default, code-splitting configuration, when the client goes to a new page (eg; `/blog`), the blog page's assets only start downloading **after** the click has been made. What this means is that our super speedy and state of the art application is at the mercy of the client's network connection.\n\nOur client is staring at a loading screen/spinner \u0026mdash; or worse, a split-second flash of the loader \u0026mdash; until the blog's code has loaded.\n\n***The Solution***\n\nWith this plugin, you regain control of your application's assets. :muscle:\n\nYou are given the knowledge of exactly which files are _going to be requested_ for each route of your application.\n\nIn turn, this means you can preemptively load the assets for `/blog` _before_ the client clicks and waits.\u003cbr\u003e\nYou can begin preloading the assets for any/all routes if you desire (although _all_ is not recommended), while still reaping the benefits of dynamic code-splitting, since the initial/critical code was kept as light as possible.\n\n***Further Reading***\n\n* https://github.com/GoogleChromeLabs/quicklink\n* https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content\n* https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/\n* https://w3c.github.io/preload/#x2.link-type-preload\n* https://github.com/lukeed/regexparam\n\n\n\n## Install\n\n```\n$ npm install webpack-route-manifest --save-dev\n```\n\n\n## Usage\n\n```js\n// webpack.config.js\nconst RouteManifest = require('webpack-route-manifest');\n\nmodule.exports = {\n  // ...\n  plugins: [\n    new RouteManifest({\n      routes(str) {\n        // Assume all entries are '../../../pages/Home' format\n        let out = str.replace('../../../pages', '').toLowerCase();\n        if (out === '/article') return '/blog/:title';\n        if (out === '/home') return '/';\n        return out;\n      }\n    })\n  ]\n}\n```\n\n\n## API\n\n### RouteManifest(options)\n\n#### options.routes\nType: `Function` or `Object`\u003cbr\u003e\nRequired: `true`\n\nMap your application's `import()` statements into the URL route patterns they'll operate on.\n\n\u003e **Note:** Check out the [supported route patterns](#route-patterns).\n\nWhen `routes` is a function, it receives the strings and expects a pattern (string) to be returned.\n\nWhen `routes` is an object, its keys must be the expected import paths and its values must be the pattern strings.\n\n\u003e **Important:** You may also return a falsey value to exclude the route from the manifest.\n\n***Example***\n\nLet's assume your `src/app.js` entry file imports pages from the sibling `src/pages/*` directory:\n\n```js\nimport React from 'react';\nimport Loadable from 'react-loadable';\nimport { Route } from 'react-router-dom';\n\n// Route-Split Components\nconst loading = () =\u003e \u003cdiv\u003eLoading...\u003c/div\u003e;\nconst load = loader =\u003e Loadable({ loader, loading });\n\n// Our Lazy-loaded Page Components\nconst Home = load(() =\u003e import('./pages/Home'));\nconst About = load(() =\u003e import('./pages/About'));\nconst Article = load(() =\u003e import('./pages/Article'));\nconst Blog = load(() =\u003e import('./pages/Blog'));\n\n// ...\n\n// Assigning Routes to Components\n\u003cRoute path=\"/\" exact component={ Home } /\u003e\n\u003cRoute path=\"/blog\" exact component={ Blog } /\u003e\n\u003cRoute path=\"/blog/:title\" component={ Article } /\u003e\n\u003cRoute path=\"/about\" exact component={ About } /\u003e\n```\n\nAt this point, your `routes` option will see:\n\n* `'./pages/Home'`\n* `'./pages/About'`\n* `'./pages/Article'`\n* `'./pages/Blog'`\n\nAs a function, `routes` should look like this:\n\n```js\nroutes(str) {\n  let out = str.replace('./pages', '').toLowerCase();\n  if (out === '/article') return '/blog/:title';\n  if (out === '/home') return '/';\n  return out;\n}\n```\n\nAs an object, `routes` should look like this:\n\n```js\nroutes: {\n  './pages/Home': '/',\n  './pages/About': '/about',\n  './pages/Article': '/blog/:title',\n  './pages/Blog': '/blog'\n}\n```\n\n\n#### options.assets\nType: `Function` or `Object`\n\nOptionally customize the `type` or `as` value of an asset.\n\n\u003e **Important:** You may also return a falsey value to exclude the asset from the manifest.\n\nThe `assets` option receives the fully formed, public-facing URL of the file (aka, including [`output.publicPath`](https://webpack.js.org/configuration/output/#outputpublicpath)).\n\nYour function or object must return a valid [resource \"destination\"](https://fetch.spec.whatwg.org/#concept-request-destination) value.\n\nBelow is the default `assets` parser:\n\n```js\nfunction assets(str) {\n  if (/\\.js$/i.test(str)) return 'script';\n  if (/\\.(svg|jpe?g|png)$/i.test(str)) return 'image';\n  if (/\\.(woff2?|otf|ttf|eot)$/i.test(str)) return 'font';\n  if (/\\.css$/i.test(str)) return 'style';\n  return false;\n}\n```\n\n\n#### options.headers\nType: `true` or `Function`\n\nOptionally include (and customize) a \"headers\" section per manifest entry.\n\n\u003e **Important:** When configured, the output format of your manifest file will change! See [Manifest Contents](#manifest-contents)\n\nWhen `true`, the default/internal function is used, which produces a [HTTP `Link` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link) per pattern, pointing to the pattern's assets.\n\nYou may also provide a function to define your own `Link` header and/or add additional headers per route.\u003cbr\u003e\nThis function will receive:\n\n* `assets` – the `Array\u003cAsset\u003e` files for this route\n* `pattern` – the current [route pattern](#route-patterns) string\n* `filemap` – the entire manifest file mapping (`{ pattern: Asset[] }`)\n\n\u003e **Note:** An `Asset` is defined as `{ type: string, href: string }` shape.\n\n\n#### options.filename\nType: `String`\u003cbr\u003e\nDefault: `manifest.json`\n\nThe output filename for the manifest.\n\nThis file is written to disk, in a compiler's configured [`output.path`](https://webpack.js.org/configuration/output/#outputpath) directory.\n\n\n#### options.minify\nType: `Boolean`\u003cbr\u003e\nDefault: `false`\n\nMinify the manifest's file contents.\n\n#### options.sort\nType: `Boolean`\u003cbr\u003e\nDefault: `true`\n\nIf route patterns should be sorted by specificity. By default, this is `true` as to ensure client consumers (eg, [`route-manifest`](https://github.com/lukeed/route-manifest)) find the correct entry for a URL path.\n\n\u003e **Note:** See `route-sort`s  [Specificity](https://github.com/lukeed/route-sort#specificity) explainer.\n\n#### options.inline\nType: `Boolean`\u003cbr\u003e\nDefault: `true`\n\nAttempts to inline the manifest file directly into your main entry file (eg; `bundle.xxxxx.js`).\u003cbr\u003eWhen successful, the manifest will be available globally as `window.__rmanifest`.\n\nWhile not required, it is strongly recommended that this option remains enabled so that the manifest contents are available to your Application _immediately_ upon loading. This saves a network request and the trouble of coordinating subsequent prefetches.\n\n\u003e **Note:** The `manifest.json` file will still be written to disk for easier developer analysis.\n\n\n## Route Patterns\n\nThe supported route pattern types are:\n\n* static – `/users`\n* named parameters – `/users/:id`\n* nested parameters – `/users/:id/books/:title`\n* optional parameters – `/users/:id?/books/:title?`\n* suffixed parameters – `/movies/:title.mp4`, `/movies/:title.(mp4|mov)`\n* wildcards – `/users/*`\n\n\n## Manifest Contents\n\nThe manifest file contains a JSON object whose keys are the [route patterns](#route-patterns) you've defined for your application via the [`options.routes`](#optionsroutes) mapping.\n\n\u003e **Note:** There will often be a `\"*\"` key, which signifies your common/catch-all route.\u003cbr\u003e\nThis typically contains your `bundle.(js|css)` files, and maybe some images that your main stylesheet requires.\n\nEach key will point to an \"Entry\" item whose data type will vary depending on your [`options.headers`](#optionsheaders) configuration. Either way, this Entry will always contain an \"Asset\" array, so let's define that first:\n\n```ts\ninterface Asset {\n  type: string;\n  href: string;\n}\n```\n\nNow, without `options.headers` (default), the manifest pairs patterns directly to its list of Assets:\n\n```ts\ntype Entry = Asset[];\n// keys are `[pattern: string]`\ntype Manifest = Record\u003cstring, Entry\u003e;\n```\n\nWith `options.headers` configured, each manifest Entry becomes object containing \"files\" and \"headers\" keys:\n\n```ts\ninterface Entry {\n  files: Asset[];\n  headers: any[]; // you decide its shape\n}\n\n// keys are `[pattern: string]`\ntype Manifest = Record\u003cstring, Entry\u003e;\n```\n\nLastly, if `options.headers === true`, the default function runs, providing you with this format:\n\n```ts\ninterface Header {\n  key: string;\n  value: string;\n}\n\ninterface Entry {\n  files: Asset[];\n  headers: Header[];\n}\n\n// keys are `[pattern: string]`\ntype Manifest = Record\u003cstring, Entry\u003e;\n```\n\n\n## License\n\nMIT © [Luke Edwards](https://lukeed.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Fwebpack-route-manifest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukeed%2Fwebpack-route-manifest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Fwebpack-route-manifest/lists"}