Skip to content

Commit 84576b4

Browse files
committed
chore: add plugin + fix nitro configuration
1 parent 256ed1a commit 84576b4

File tree

4 files changed

+108
-22
lines changed

4 files changed

+108
-22
lines changed

src/module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ export default defineNuxtModule<ModuleOptions>({
3333
logger: useLogger(`nuxt:${NAME}`),
3434
options,
3535
resolvedOptions: {
36-
detectBrowser: false,
37-
detectOS: false,
36+
detectBrowser: options.detectBrowser ?? false,
37+
detectOS: options.detectOS ?? false,
3838
userAgent: [],
3939
network: [],
4040
device: [],

src/runtime/server/index.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { eventHandler } from 'h3'
2-
import { useNitro } from '@nuxt/kit'
2+
import { useRuntimeConfig } from 'nitropack/runtime'
33
import { parseUserAgent } from 'detect-browser-es'
44
import type { HttpClientHintsState, ResolvedHttpClientHintsOptions } from '../shared-types/types'
55
import { extractBrowser } from '../utils/detect'
@@ -12,8 +12,9 @@ export default eventHandler(async (event) => {
1212
const url = event.path
1313
console.log(url)
1414
try {
15-
const nitro = useNitro()
16-
const options = nitro.options.runtimeConfig.public.httpClientHints as ResolvedHttpClientHintsOptions
15+
const runtimeConfig = useRuntimeConfig(event)
16+
console.log(runtimeConfig)
17+
const options = runtimeConfig.public.httpClientHints as ResolvedHttpClientHintsOptions
1718
const critical = !!options.critical
1819
const device = options.device.length > 0
1920
const network = options.network.length > 0

src/runtime/server/plugin.ts

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { defineNitroPlugin, useAppConfig } from 'nitropack/runtime'
2+
import { parseUserAgent } from 'detect-browser-es'
3+
import type { HttpClientHintsState, ResolvedHttpClientHintsOptions } from '../shared-types/types'
4+
import { extractBrowser } from '../utils/detect'
5+
import { extractCriticalHints } from '../utils/critical'
6+
import { extractDeviceHints } from '../utils/device'
7+
import { extractNetworkHints } from '../utils/network'
8+
9+
interface ServerRuntimeConfig extends Omit<ResolvedHttpClientHintsOptions, 'serverImages'> {
10+
serverImages: string[]
11+
}
12+
13+
export default defineNitroPlugin((nitroApp) => {
14+
const { serverImages, ...rest } = useAppConfig().httpClientHints as ServerRuntimeConfig
15+
const options: ResolvedHttpClientHintsOptions = {
16+
...rest,
17+
serverImages: serverImages.map(r => new RegExp(r)),
18+
}
19+
console.log(options)
20+
nitroApp.hooks.hook('afterResponse', async (event) => {
21+
// we should add the vary header to the response
22+
})
23+
nitroApp.hooks.hook('request', async (event) => {
24+
// expose the client hints in the context
25+
const url = event.path
26+
console.log(url)
27+
try {
28+
const critical = !!options.critical
29+
const device = options.device.length > 0
30+
const network = options.network.length > 0
31+
const detect = options.detectOS || options.detectBrowser || options.userAgent.length > 0
32+
if (!critical && !device && !network && !detect) {
33+
return undefined
34+
}
35+
36+
// expose the client hints in the context
37+
// const url = event.path
38+
if (options.serverImages?.some(r => url.match(r))) {
39+
const userAgentHeader = event.headers.get('user-agent')
40+
const requestHeaders: { [key in Lowercase<string>]?: string } = {}
41+
for (const [key, value] of event.headers.entries()) {
42+
requestHeaders[key.toLowerCase() as Lowercase<string>] = value
43+
}
44+
const userAgent = userAgentHeader
45+
? parseUserAgent(userAgentHeader)
46+
: null
47+
const clientHints: HttpClientHintsState = {}
48+
if (detect) {
49+
clientHints.browser = await extractBrowser(options, requestHeaders as Record<string, string>, userAgentHeader ?? undefined)
50+
}
51+
if (critical) {
52+
clientHints.critical = extractCriticalHints(options, requestHeaders, userAgent)
53+
}
54+
if (device) {
55+
clientHints.device = extractDeviceHints(options, requestHeaders, userAgent)
56+
}
57+
if (network) {
58+
clientHints.network = extractNetworkHints(options, requestHeaders, userAgent)
59+
}
60+
event.context.httpClientHints = clientHints
61+
}
62+
}
63+
catch (err) {
64+
console.error(err)
65+
}
66+
})
67+
})

src/utils/configuration.ts

+35-17
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import type { Nuxt } from '@nuxt/schema'
22
import type { Resolver } from '@nuxt/kit'
33
import {
4-
addDevServerHandler,
5-
addServerHandler,
4+
// addDevServerHandler,
5+
// addServerHandler,
66
// addServerImportsDir,
77
addPlugin,
88
addPluginTemplate,
9+
addServerPlugin,
910
} from '@nuxt/kit'
10-
import defu from 'defu'
11+
// import defu from 'defu'
1112
import type { HttpClientHintsOptions } from '../types'
1213
import type { ResolvedHttpClientHintsOptions } from '../runtime/shared-types/types'
1314

@@ -62,7 +63,7 @@ export function configure(ctx: HttpClientHintsContext, nuxt: Nuxt) {
6263
const clientOnly = nuxt.options._generate || !nuxt.options.ssr
6364

6465
// we register the client detector only if needed and not in SSR mode
65-
if ((options.detectBrowser || options.detectOS || resolvedOptions.userAgent.length) && clientOnly) {
66+
if ((resolvedOptions.detectBrowser || resolvedOptions.detectOS || resolvedOptions.userAgent.length) && clientOnly) {
6667
nuxt.options.build.transpile.push(runtimeDir)
6768
nuxt.hook('prepare:types', ({ references }) => {
6869
references.push({ path: resolver.resolve(runtimeDir, 'plugins/types') })
@@ -128,7 +129,7 @@ export function configure(ctx: HttpClientHintsContext, nuxt: Nuxt) {
128129

129130
addPlugin(resolver.resolve(runtimeDir, 'plugins/init.server'))
130131

131-
if (options.detectBrowser || options.detectOS || resolvedOptions.userAgent.length) {
132+
if (resolvedOptions.detectBrowser || resolvedOptions.detectOS || resolvedOptions.userAgent.length) {
132133
clientDependsOn.push('detect')
133134
serverDependsOn.push('detect')
134135
addPlugin(resolver.resolve(runtimeDir, 'plugins/detect.client'))
@@ -148,17 +149,17 @@ export function configure(ctx: HttpClientHintsContext, nuxt: Nuxt) {
148149
}
149150

150151
// Add utils to nitro config
151-
nuxt.hook('nitro:config', (nitroConfig) => {
152+
/* nuxt.hook('nitro:config', (nitroConfig) => {
152153
nitroConfig.alias = nitroConfig.alias || {}
153154
154155
// Inline module runtime in Nitro bundle
155156
nitroConfig.externals = defu(
156157
typeof nitroConfig.externals === 'object' ? nitroConfig.externals : {},
157158
{
158-
inline: [resolver.resolve('./runtime/server/utils/index.js')],
159+
inline: [resolver.resolve('./runtime/server/utils/index')],
159160
},
160161
)
161-
})
162+
}) */
162163

163164
resolvedOptions.serverImages = serverImages
164165
? serverImages === true
@@ -169,24 +170,41 @@ export function configure(ctx: HttpClientHintsContext, nuxt: Nuxt) {
169170
: undefined
170171

171172
if (resolvedOptions.serverImages?.length) {
173+
addServerPlugin(resolver.resolve(runtimeDir, 'server/plugin'))
174+
const { serverImages, ...rest } = resolvedOptions
175+
nuxt.options.appConfig.httpClientHints = {
176+
...rest,
177+
serverImages: serverImages.map(r => r.source),
178+
}
179+
/* nuxt.hook('nitro:init', (nitro) => {
180+
nitro.options.appConfig.public ??= {}
181+
nitro.options.appConfig.public.httpClientHints = resolvedOptions
182+
})
183+
nuxt.hook('nitro:config', (nitroConfig) => {
184+
nitroConfig.runtimeConfig ??= {}
185+
nitroConfig.runtimeConfig.public ??= {}
186+
nitroConfig.runtimeConfig.public.httpClientHints = resolvedOptions
187+
}) */
172188
// Add utils to server imports
173189
// addServerImportsDir(resolver.resolve('./runtime/utils'))
174190
// addServerImportsDir(resolver.resolve('./runtime/server'))
175191
if (nuxt.options.dev) {
176-
addDevServerHandler({
192+
/* addDevServerHandler({
177193
method: 'get',
178194
handler: resolver.resolve(runtimeDir, 'server/index'),
179-
})
195+
}) */
180196
/* nuxt.hook('nitro:init', (nitro) => {
181197
nitro.options.devHandlers.unshift({
182198
route: '',
183199
handler: resolver.resolve(runtimeDir, 'server/index'),
184200
})
185201
}) */
186-
/* nuxt.options.devServerHandlers.push({
187-
route: '',
202+
/* nuxt.options.devServerHandlers.unshift({
203+
// route: '',
204+
method: 'get',
188205
handler: resolver.resolve(runtimeDir, 'server/index'),
189-
})
206+
}) */
207+
/*
190208
addDevServerHandler({
191209
route: '',
192210
handler: defineEventHandler(async (event) => {
@@ -195,18 +213,18 @@ export function configure(ctx: HttpClientHintsContext, nuxt: Nuxt) {
195213
}) */
196214
}
197215
else {
198-
addServerHandler({
216+
/* addServerHandler({
199217
method: 'get',
200218
handler: resolver.resolve(runtimeDir, 'server/index'),
201-
})
219+
}) */
202220
/* nuxt.hook('nitro:init', (nitro) => {
203221
nitro.options.handlers.unshift({
204222
route: '',
205223
handler: resolver.resolve(runtimeDir, 'server/index'),
206224
})
207225
}) */
208-
/* nuxt.options.serverHandlers.push({
209-
route: '',
226+
/* nuxt.options.serverHandlers.unshift({
227+
// route: '',
210228
handler: resolver.resolve(runtimeDir, 'server/index'),
211229
}) */
212230
/* addServerHandler({

0 commit comments

Comments
 (0)