Add support for webmanifest files in .htaccess and nginx configuration
This commit is contained in:
@@ -8,6 +8,14 @@ server {
|
|||||||
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
|
||||||
|
location ~ ^/(?:.+/)?(?<webmanifest_path>(?:assets/)?manifest\.webmanifest)$ {
|
||||||
|
types { application/manifest+json webmanifest; }
|
||||||
|
default_type application/manifest+json;
|
||||||
|
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
try_files /$webmanifest_path =404;
|
||||||
|
}
|
||||||
|
|
||||||
location ~ ^/(release-entry|release-manifest)\.json$ {
|
location ~ ^/(release-entry|release-manifest)\.json$ {
|
||||||
add_header Cache-Control "no-store";
|
add_header Cache-Control "no-store";
|
||||||
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
Options -MultiViews
|
Options -MultiViews
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_mime.c>
|
||||||
|
AddType application/manifest+json .webmanifest
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
|
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ test.describe("public .htaccess static fallback", () => {
|
|||||||
expect(source).not.toContain("/index.html");
|
expect(source).not.toContain("/index.html");
|
||||||
expect(source).toContain("index.html [L]");
|
expect(source).toContain("index.html [L]");
|
||||||
expect(source).toContain("R=404");
|
expect(source).toContain("R=404");
|
||||||
|
expect(source).toContain("AddType application/manifest+json .webmanifest");
|
||||||
|
|
||||||
for (const token of [...STATIC_DIRECTORIES, ...STATIC_FILES, "workbox-"]) {
|
for (const token of [...STATIC_DIRECTORIES, ...STATIC_FILES, "workbox-"]) {
|
||||||
expect(sourceWithoutRegexEscapes).toContain(token);
|
expect(sourceWithoutRegexEscapes).toContain(token);
|
||||||
@@ -297,6 +298,7 @@ test.describe("public .htaccess static fallback", () => {
|
|||||||
expect(source).toContain("static_asset_path");
|
expect(source).toContain("static_asset_path");
|
||||||
expect(source).toContain("static_file_path");
|
expect(source).toContain("static_file_path");
|
||||||
expect(source).toContain("=404");
|
expect(source).toContain("=404");
|
||||||
|
expect(source).toContain("application/manifest+json webmanifest");
|
||||||
|
|
||||||
for (const token of [...STATIC_DIRECTORIES, ...STATIC_FILES, "workbox-"]) {
|
for (const token of [...STATIC_DIRECTORIES, ...STATIC_FILES, "workbox-"]) {
|
||||||
expect(sourceWithoutRegexEscapes).toContain(token);
|
expect(sourceWithoutRegexEscapes).toContain(token);
|
||||||
@@ -341,6 +343,29 @@ test.describe("public .htaccess static fallback", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("does not emit conflicting Workbox precache URLs", async () => {
|
||||||
|
const serviceWorker = await fs.readFile(path.join(DIST_DIR, "sw.js"), "utf8");
|
||||||
|
const precacheEntries = Array.from(serviceWorker.matchAll(/\{url:"([^"]+)",revision:(null|"[^"]+")/g), (match) => ({
|
||||||
|
url: match[1],
|
||||||
|
revision: match[2],
|
||||||
|
}));
|
||||||
|
const revisionsByUrl = new Map<string, Set<string>>();
|
||||||
|
|
||||||
|
for (const entry of precacheEntries) {
|
||||||
|
const revisions = revisionsByUrl.get(entry.url) || new Set<string>();
|
||||||
|
revisions.add(entry.revision);
|
||||||
|
revisionsByUrl.set(entry.url, revisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const conflictingUrls = Array.from(revisionsByUrl.entries())
|
||||||
|
.filter(([, revisions]) => revisions.size > 1)
|
||||||
|
.map(([url]) => url);
|
||||||
|
|
||||||
|
expect(precacheEntries.length).toBeGreaterThan(0);
|
||||||
|
expect(conflictingUrls).toEqual([]);
|
||||||
|
expect(precacheEntries.filter((entry) => entry.url === "assets/manifest.webmanifest")).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
test("serves the app shell from root, deep links, and release-prefixed paths", async ({ request }) => {
|
test("serves the app shell from root, deep links, and release-prefixed paths", async ({ request }) => {
|
||||||
for (const appPath of [
|
for (const appPath of [
|
||||||
"/",
|
"/",
|
||||||
|
|||||||
+2
-2
@@ -554,8 +554,8 @@ export default defineConfig(({ mode }) => {
|
|||||||
cleanupOutdatedCaches: true,
|
cleanupOutdatedCaches: true,
|
||||||
skipWaiting: true,
|
skipWaiting: true,
|
||||||
clientsClaim: true,
|
clientsClaim: true,
|
||||||
globPatterns: ['**/*.{js,css,html,ico,svg,png,webmanifest,woff2}'],
|
globPatterns: ['**/*.{js,css,html,ico,svg,png,woff2}'],
|
||||||
globIgnores: ['**/registerSW.js', '**/sw.js'],
|
globIgnores: ['**/registerSW.js', '**/sw.js', '**/*.webmanifest'],
|
||||||
runtimeCaching: [
|
runtimeCaching: [
|
||||||
{
|
{
|
||||||
// cache API responses
|
// cache API responses
|
||||||
|
|||||||
Reference in New Issue
Block a user