File tree Expand file tree Collapse file tree 10 files changed +5656
-3234
lines changed Expand file tree Collapse file tree 10 files changed +5656
-3234
lines changed Original file line number Diff line number Diff line change 1
- # Nuxt 3 Minimal Starter
1
+ # Netlify Cache Inspector
2
2
3
- Look at the [ Nuxt 3 documentation ] ( https://nuxt.com/docs/getting-started/introduction ) to learn more.
3
+ Utility web app for inspecting and comparing cache headers for requests to Netlify sites
4
4
5
- ## Setup
5
+ ## Development
6
6
7
- Make sure to install the dependencies:
7
+ Install dependencies:
8
8
9
9
``` bash
10
- # npm
11
- npm install
12
-
13
- # pnpm
14
10
pnpm install
15
-
16
- # yarn
17
- yarn install
18
-
19
- # bun
20
- bun install
21
11
```
22
12
23
- ## Development Server
13
+ ### Dev Server
24
14
25
15
Start the development server on ` http://localhost:3000 ` :
26
16
27
17
``` bash
28
- # npm
29
- npm run dev
30
-
31
- # pnpm
32
18
pnpm run dev
33
-
34
- # yarn
35
- yarn dev
36
-
37
- # bun
38
- bun run dev
39
19
```
40
20
41
- ## Production
21
+ ### Production build
42
22
43
23
Build the application for production:
44
24
45
25
``` bash
46
- # npm
47
- npm run build
48
-
49
- # pnpm
50
26
pnpm run build
51
-
52
- # yarn
53
- yarn build
54
-
55
- # bun
56
- bun run build
57
27
```
58
28
59
- Locally preview production build:
29
+ ### Locally preview of a production build
60
30
61
31
``` bash
62
- # npm
63
- npm run preview
64
-
65
- # pnpm
66
32
pnpm run preview
67
-
68
- # yarn
69
- yarn preview
70
-
71
- # bun
72
- bun run preview
73
33
```
74
34
75
- Check out the [ deployment documentation] ( https://nuxt.com/docs/getting-started/deployment ) for more information.
35
+ ## Deployment
36
+
37
+ This site deploys automatically to Netlify.
Original file line number Diff line number Diff line change 1
1
<template >
2
- <div >
3
- <NuxtRouteAnnouncer />
4
- <NuxtWelcome />
5
- </div >
2
+ <NuxtRouteAnnouncer />
3
+
4
+ <header >
5
+ <h1 >Netlify Cache Inspector</h1 >
6
+
7
+ <p class =" subheading" >
8
+ Inspect and compare cache headers for requests to Netlify sites
9
+ </p >
10
+ </header >
11
+
12
+ <main >
13
+ <RequestForm />
14
+ </main >
6
15
</template >
16
+
17
+ <style >
18
+ body {
19
+ /* Override weird default from Netlify Examples style */
20
+ text-align : left ;
21
+ }
22
+ </style >
23
+ <style scoped>
24
+ header {
25
+ text-align : center ;
26
+ }
27
+
28
+ .subheading {
29
+ font-size : 1.5em ;
30
+ }
31
+
32
+ main {
33
+ margin-top : 3em ;
34
+ }
35
+ </style >
Original file line number Diff line number Diff line change
1
+ <script setup lang="ts">
2
+ const props = defineProps <{
3
+ cacheHeaders: Record <string , string >;
4
+ }>();
5
+
6
+ const id = useId ();
7
+ const el = useTemplateRef (id );
8
+ const highlightJson = () => {
9
+ hljs .highlightElement (el .value );
10
+ };
11
+ onMounted (highlightJson );
12
+ onUpdated (highlightJson );
13
+ </script >
14
+
15
+ <template >
16
+ <pre >
17
+ <code :ref =" id" class =" hljs language-json" >{{ JSON.stringify(props.cacheHeaders, null, 2) }}</code >
18
+ </pre >
19
+ </template >
Original file line number Diff line number Diff line change
1
+ <script setup lang="ts">
2
+ const inputUrl = ref ();
3
+ const runs = ref ([]);
4
+
5
+ const inspectUrl = async (): void => {
6
+ if (! inputUrl .value .startsWith (" http" )) {
7
+ inputUrl .value = ` https://${inputUrl .value } ` ;
8
+ }
9
+
10
+ try {
11
+ // Destructuring would be confusing, since the response body contains fields named `status` and
12
+ // `headers` (it's a request about a request...)
13
+ const responseBody = await $fetch (
14
+ ` /api/inspect-url/${encodeURIComponent (inputUrl .value )} ` ,
15
+ );
16
+
17
+ runs .value .push ({
18
+ url: inputUrl .value ,
19
+ status: responseBody .status ,
20
+ cacheHeaders: getCacheHeaders (responseBody .headers ),
21
+ durationInMs: responseBody .durationInMs ,
22
+ });
23
+ } catch (err ) {
24
+ // TODO(serhalp) Proper error handling. ErrorBoundary?
25
+ console .error (" Error fetching URL" , err );
26
+ return ;
27
+ }
28
+ };
29
+ </script >
30
+
31
+ <template >
32
+ <div class =" form" >
33
+ <label class =" url-input" >
34
+ <strong >URL:</strong >
35
+ <input v-model.trim =" inputUrl" @keyup.enter =" inspectUrl()" />
36
+ </label >
37
+ <button @click =" inspectUrl()" >Inspect</button >
38
+ </div >
39
+
40
+ <!-- TODO(serhalp) Move this into another component. Wrong place. -->
41
+ <div class =" flex-btwn" >
42
+ <div v-for =" run in runs" >
43
+ <h3 >{{ run.url }}</h3 >
44
+ <small >HTTP {{ run.status }} ({{ run.durationInMs }} ms)</small >
45
+ <RawCacheHeaders :cacheHeaders =" run.cacheHeaders" />
46
+ </div >
47
+ </div >
48
+ </template >
49
+
50
+ <style scoped>
51
+ .form {
52
+ display : flex ;
53
+ gap : 1em ;
54
+ align-content : center ;
55
+ align-items : center ;
56
+ }
57
+
58
+ label {
59
+ display : flex ;
60
+ gap : 1em ;
61
+ align-content : center ;
62
+ align-items : center ;
63
+
64
+ >* {
65
+ /* Override default from Netlify Examples style to vertically center easily */
66
+ margin-bottom : 0 ;
67
+ }
68
+ }
69
+
70
+ .url-input {
71
+ flex : 1 ;
72
+ }
73
+ </style >
Original file line number Diff line number Diff line change
1
+ const CACHE_HEADER_NAMES = [
2
+ "Age" ,
3
+ "CDN-Cache-Control" ,
4
+ "Cache-Control" ,
5
+ "Cache-Status" ,
6
+ "Content-Encoding" ,
7
+ "Content-Type" ,
8
+ "Date" ,
9
+ "ETag" ,
10
+ "Netlify-CDN-Cache-Control" ,
11
+ "Vary" ,
12
+ "X-BB-Deploy-Id" ,
13
+ "X-BB-Gen" ,
14
+ "X-NF-Cache-Info" ,
15
+ "X-NF-Cache-Result" ,
16
+ ] ;
17
+
18
+ export default function getCacheHeaders ( headersObj : Record < string , string > ) {
19
+ // Use a Headers instance for case insensitivity and multi-value handling
20
+ const headers = new Headers ( headersObj ) ;
21
+
22
+ // I'd rather avoid mutations here but it's really awkward to handle nil values otherwise
23
+ const cacheHeaders = new Headers ( ) ;
24
+ for ( const name of CACHE_HEADER_NAMES ) {
25
+ const val = headers . get ( name ) ;
26
+ if ( val != null ) cacheHeaders . set ( name , val ) ;
27
+ }
28
+
29
+ return Object . fromEntries ( cacheHeaders ) ;
30
+ }
Original file line number Diff line number Diff line change
1
+ // @ts -check
2
+ import withNuxt from "./.nuxt/eslint.config.mjs" ;
3
+
4
+ export default withNuxt ( ) . override ( "nuxt/vue" , {
5
+ rules : {
6
+ "vue/html-self-closing" : [
7
+ "error" ,
8
+ {
9
+ html : {
10
+ // The default config here isn't compatible with prettier:
11
+ // https://github.com/vuejs/eslint-plugin-vue/issues/2232.
12
+ void : "always" ,
13
+ } ,
14
+ } ,
15
+ ] ,
16
+ } ,
17
+ } ) ;
Original file line number Diff line number Diff line change @@ -3,4 +3,51 @@ export default defineNuxtConfig({
3
3
compatibilityDate : "2024-09-13" ,
4
4
future : { compatibilityVersion : 4 } ,
5
5
devtools : { enabled : true } ,
6
+
7
+ app : {
8
+ head : {
9
+ link : [
10
+ // See https://example-styles.netlify.app/.
11
+ {
12
+ rel : "preload" ,
13
+ href : "https://example-styles.netlify.app/fonts/PacaembuVar-latin.woff2" ,
14
+ as : "font" ,
15
+ type : "font/woff2" ,
16
+ crossorigin : "" ,
17
+ } ,
18
+ {
19
+ rel : "preload" ,
20
+ href : "https://example-styles.netlify.app/fonts/MulishVar-latin.woff2" ,
21
+ as : "font" ,
22
+ type : "font/woff2" ,
23
+ crossorigin : "" ,
24
+ } ,
25
+ {
26
+ rel : "stylesheet" ,
27
+ href : "https://example-styles.netlify.app/styles.css" ,
28
+ } ,
29
+ {
30
+ rel : "stylesheet" ,
31
+ href : "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/styles/default.min.css" ,
32
+ } ,
33
+ ] ,
34
+ script : [
35
+ {
36
+ src : "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/highlight.min.js" ,
37
+ } ,
38
+ // TODO(serhalp) Check if this is really the idiomatic way to do this...
39
+ {
40
+ children : "hljs.highlightAll();" ,
41
+ } ,
42
+ ] ,
43
+ } ,
44
+ } ,
45
+
46
+ routeRules : {
47
+ "/" : {
48
+ prerender : true ,
49
+ } ,
50
+ } ,
51
+
52
+ modules : [ "@nuxt/eslint" ] ,
6
53
} ) ;
Original file line number Diff line number Diff line change 1
1
{
2
- "name" : " nuxt-app" ,
2
+ "name" : " netlify-cache-inspector" ,
3
+ "description" : " Inspect and compare cache headers for requests to Netlify sites" ,
3
4
"private" : true ,
4
5
"type" : " module" ,
5
6
"scripts" : {
6
7
"build" : " nuxt build" ,
7
8
"dev" : " nuxt dev" ,
8
9
"generate" : " nuxt generate" ,
9
10
"preview" : " nuxt preview" ,
10
- "postinstall" : " nuxt prepare"
11
+ "postinstall" : " nuxt prepare" ,
12
+ "typecheck" : " npx nuxi typecheck"
11
13
},
12
14
"dependencies" : {
15
+ "@nuxt/eslint" : " ^0.5.7" ,
13
16
"nuxt" : " ^3.13.0" ,
14
17
"vue" : " latest" ,
15
18
"vue-router" : " latest"
19
+ },
20
+ "devDependencies" : {
21
+ "typescript" : " ^5.6.2" ,
22
+ "vue-tsc" : " ^2.1.6"
16
23
}
17
24
}
You can’t perform that action at this time.
0 commit comments