Repository navigation
perf(static): skip filesystem lookups for application routes - #11
Open
RomainLanz wants to merge 4 commits into
Open
RomainLanz wants to merge 4 commits into
RomainLanz wants to merge 4 commits into
Conversation
Static middleware probes public paths for application routes on every GET and HEAD request. Add an opt-in public directory index to skip known misses while preserving serve-static handling for possible hits. Index the whole directory instead of the Vite manifest so other public files remain accessible. Keep indexing disabled by default because new files require a process restart.
Skip the filesystem for paths ending with a slash when the directory has no index.html, so application routes such as "/" no longer probe the public directory. Fold index keys through lowercase before uppercase. Uppercasing alone reports existing files as missing for "ẞ" and "ϴ" on case-insensitive filesystems. Construct the middleware while booting the web environment so the scan does not delay the first request, and store keys relative to the public directory to reduce memory.
The index skipped lookups for missing paths, but it had to reproduce the path resolution of serve-static: URL decoding, case folding, Unicode normalization and symlinks. A mismatch between the two turns an existing file into a 404. The index also needed a scan at boot and a restart after adding files. Remove `indexFiles` and add a `prefixes` option. The middleware compares the request URL path with the prefixes and calls the next middleware without a filesystem lookup when none matches. Requests under a prefix go to serve-static as before, so a missing file under a prefix still costs one lookup. Without the option, the behavior does not change.
The option is documented on the AdonisJS website with the other static file server options.
RomainLanz
added a commit
to adonisjs/v7-docs
that referenced
this pull request
Oct 12, 2026
adonisjs/static#11 replaced the public files index with a list of URL path prefixes. Document the new option, and state that a public file with no matching prefix is not served.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The static middleware looks for a file in
public/on every request, including the requests that application routes handle.This adds an opt-in
prefixesoption. When it is set, the middleware compares the request URL path with the prefixes. A request with no matching prefix goes to the next middleware without a filesystem lookup.A request matches when its path equals a prefix or is nested under it.
/assets/app.jsmatches/assets, and/assets-old/app.jsdoes not. The prefixes do not change the file path:/assets/app.jsstill servespublic/assets/app.js.An earlier version of this PR indexed
public/at boot. I replaced it with prefixes after review feedback. The index had to reproduce the path resolution ofserve-static(URL decoding, case folding, Unicode normalization, symlinks), and it needed a restart after adding files. The prefix check is one string comparison per entry and has no state.Limits:
public/with no matching prefix is not served.Without the option, the behavior does not change.
Verification:
npm test(15 passed, including lint) andnpm run typecheck.