Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Static Laravel Package

vormkracht10/laravel-static

A Laravel package for generating and serving static HTML versions of your routes. Cache pages as flat files to reduce server load, speed up responses, and deploy static content while preserving your existing Laravel routing and Blade views.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its config:

composer require backstagephp/laravel-static
php artisan vendor:publish --tag=static-config

Look at the config file first — it governs what gets written to disk, and every number in the new static:status output maps back to a setting there. Read it alongside the command output so you can connect "1.7 MB on disk" to the specific lever that produced it.

The first use case is the obvious one: put the cache in front of your public, anonymous, GET-only pages (marketing pages, docs, blog index, product listing) and leave everything session-dependent out of it.

Then, the first thing to do after deploying is not pruning — it's measuring:

php artisan static:status

You get file count, size on disk, cached pages (compressed copies excluded), distinct URLs, and — the headline — a warning when a meaningful share of your pages are query-string variants of the same URLs:

  WARN  6 of 17 cached pages (35%) are extra query-string variants of 11 distinct URLs.

That single line tells you whether your cache is growing because you have a lot of content, or because bots and newsletters are minting a new file for every ?utm_source=….

Implementation Patterns

Measure, then prune, then fix. Use static:status as the diagnostic step in a three-part loop:

php artisan static:status                      # where is the size?
php artisan static:clear --only-with-query-strings   # reclaim the junk
# then: canonicalise or block the parameters at the edge

Pruning without the third step just means the cache refills with the same variants next week.

Normalise query strings before the cache sees them. The most effective long-term pattern is to handle tracking parameters above the static layer — a middleware or edge rule that 301s ?utm_*/?fbclid to the clean URL, or a robots.txt/rel=canonical discipline so crawlers never generate them. Anything that survives to the cache layer is a permanent file.

Use the parameter table as a backlog. static:status reports the most common query parameters and the top URLs by variant count. When utm_source or fbclid is at the top, that's a concrete, prioritised task, not a vague "cache is big" ticket. When it's page or filter, that's real product surface and you probably want to keep it (and revisit your disk budget instead).

Wire --json into monitoring. Add a scheduled command or a health check that runs:

php artisan static:status --json --limit=20

and alerts on total size or on the variant ratio crossing a threshold. Size on disk is the metric that pages your webserver, and it's the one nobody watches until it's urgent.

Inspect the right disk. On multi-disk or unusual deployments, pass --disk= explicitly rather than assuming the default; a status report for the wrong filesystem is worse than no report.

Budget in CI/pre-deploy where it makes sense. For content-heavy sites, a deploy-time check that the cache size is within an expected band catches a bad route change or a crawler storm before it becomes an outage.

Use --limit and pass-through collapsing when reading the directory report. The du-style output collapses intermediate levels, which keeps the report readable; raise --limit only when you're drilling into a specific subtree.

Gotchas and Tips

Nothing is evicted. Ever. This is the core mental model: no LRU, no TTL sweep, no size cap. Entries leave only via static:clear (full) or static:clear --only-with-query-strings. Treat the static cache as an append-only structure and design your key space accordingly.

Query strings produce separate files, per URI, including the query string. A single canonical page can occupy dozens of files. Every newsletter link, ad campaign, and bot crawl with a tracking parameter is a new permanent file. This is by far the most common cause of "the cache filled the disk."

Be careful with --only-with-query-strings in production. It's a blunt instrument: it will also delete legitimately cached variants — paginated pages, faceted/filtered product listings, search results you deliberately cached. Before running it, read the "top URLs by number of cached variants" section and confirm the variants are tracking noise rather than product surface. If in doubt, run static:status --json first and inspect.

Compressed siblings count towards size but not towards page count. gzip/brotli copies inflate disk usage without inflating the page counter — the per-host and per-file-type breakdown is where that multiplication shows up. Enabling compression will therefore never look like cache growth in the page count, but it absolutely affects your disk bill. Don't compare page counts across a compression change and conclude nothing happened.

Memory scales with distinct URL paths, not files. The command is designed for multi-million-file caches, but a pathological site with millions of distinct paths is a different story. If it's slow, the distinct-path count in the summary tells you why.

Only local disks can be inspected. Remote disks are rejected by design — walking one would be an API call per file. If your cache lives on S3 or a network mount, you need a different approach; static:status will not help you there.

The report deliberately shows the config settings that govern cache growth alongside the numbers. Use it that way — the intended workflow is "read the number, read the lever, change the lever," all on one screen. Keeping them side by side is the point of the command, not decoration.

Treat --json output as a monitoring contract. Pin your alert thresholds to fields you understand, and re-check the shape after each minor upgrade; the human-readable output is more likely to change than the semantics of the numbers.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums