.htaccess generation
For Apache-hosted SPAs, you need a .htaccess that:
- Routes every non-asset URL back to
index.htmlso client-side routing works. - Forces HTTPS.
- Compresses responses.
- Sets sane cache headers.
@mongez/vite ships a bundled .htaccess template and writes it into the output directory when you opt in.
Default behaviour
mongezVite(); // htaccess: false (opt-in)The default is false — you have to opt in explicitly.
Opting in
mongezVite({ htaccess: true });After vite build, dist/.htaccess exists.
What’s in the template
The bundled .htaccess:
RewriteEngine OnOptions +FollowSymLinks -Indexes
# Force httpsRewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
RewriteCond %{HTTPS} !onRewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Prerender slot (filled if preRender is set, removed otherwise)
# Skip files that existRewriteCond %{REQUEST_FILENAME} -f [OR]RewriteCond %{REQUEST_FILENAME} -dRewriteRule \.(jpg|png|ico|jpeg|webp|gif|bmp|webp|svg)$ - [L]RewriteRule assets/(.*) assets/$1 [L]
# SPA fallback: everything else → index.htmlRewriteRule ^(.*)$ index.html [L,QSA]
# GZIP via mod_gzip and mod_deflate# ... <ifModule mod_gzip.c> ... </ifModule># ... <ifModule mod_deflate.c> ... </ifModule>
# 31-day Expires headers for asset types# ... <ifmodule mod_expires.c> ... </ifmodule>
# Cache-Control headers per file type# ... <ifmodule mod_headers.c> ... </ifmodule>Each block is wrapped in <ifModule> so an Apache install missing one of the modules degrades gracefully.
The prerender slot
If preRender is set, the plugin splices a crawler-routing rewrite block into the template before writing it out:
# PrerenderRewriteCond %{HTTP_USER_AGENT} .*(Googlebot|facebook|...|bot).* [NC]RewriteCond %{REQUEST_URI} !^(/public)RewriteRule (.*) prerender.php [L,QSA]If preRender: false (the default), the # Prerender marker is replaced with an empty string and no crawler routing happens.
See prerender/SKILL.md for the full prerender pipeline.
Cache behaviour
The template configures, per filetype:
| Filetype | Expires | Cache-Control |
|---|---|---|
ico, flv, jpg, jpeg, png, gif, css, swf | 31 days | max-age=2678400, public |
html, htm | 7200s (2h) | max-age=7200, private, must-revalidate |
pdf | 31 days | max-age=2678400, public |
Tune these by post-processing the emitted file in your own deploy step — the plugin does not expose options for them today.
When the plugin does nothing
htaccess: false(the default).
Gotchas
- Asset-name extensions are hard-coded. The rewrite rule skipping rule lists
(jpg|png|ico|jpeg|webp|gif|bmp|webp|svg)$. If you emit.avifor.webm, add a custom rule by post-processing the htaccess, or sethtaccess: falseand write your own. assets/is the only build-output subdir whitelisted. If you customise Vite’sassetsDir(e.g.static/), edit the template.- The force-HTTPS rule applies even in dev when Apache is in front of localhost. Usually you wouldn’t deploy with vite dev, but if you do, expect redirects to
https://localhost. - The template lives at
src/.htaccessin the package. If you want to customise wholesale, fork or shadow it via your own plugin.