diff --git a/playgrounds/nuxt5/test.mjs b/playgrounds/nuxt5/test.mjs index 169622cc..9b8f7341 100644 --- a/playgrounds/nuxt5/test.mjs +++ b/playgrounds/nuxt5/test.mjs @@ -31,6 +31,12 @@ async function waitForServer() { try { await waitForServer() + const page = await fetchWithTimeout(origin) + assert.equal(page.status, 200) + const pageHtml = await page.text() + assert.match(pageHtml, /class="iconify i-ph:acorn-bold"/) + assert.match(pageHtml, /data:image\/svg\+xml/) + const bundled = await fetchWithTimeout(`${origin}/api/_nuxt_icon/ph.json?icons=acorn-bold`) assert.equal(bundled.status, 200) const bundledData = await bundled.json() diff --git a/src/runtime/plugin.ts b/src/runtime/plugin.ts index f33fb0cc..48af655c 100644 --- a/src/runtime/plugin.ts +++ b/src/runtime/plugin.ts @@ -8,11 +8,15 @@ export default defineNuxtPlugin({ setup() { const configs = useRuntimeConfig() const options = useAppConfig().icon as NuxtIconRuntimeOptions - const $fetch = useRequestFetch() + const requestFetch = useRequestFetch() + const nativeFetch = (requestFetch as { native?: typeof globalThis.fetch }).native - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore type incompatible - _api.setFetch($fetch.native) + _api.setFetch((input, init) => { + const nitroFetch = (globalThis as typeof globalThis & { + $fetch?: { native?: typeof globalThis.fetch } + }).$fetch?.native + return (nativeFetch || nitroFetch || globalThis.fetch)(input, init) + }) const resources: string[] = [] if (options.provider === 'server') { @@ -33,7 +37,7 @@ export default defineNuxtPlugin({ async function customIconLoader(icons: string[], prefix: string): Promise { try { - const data = await $fetch(resources[0] + '/' + prefix + '.json', { + const data = await requestFetch(resources[0] + '/' + prefix + '.json', { query: { icons: icons.join(','), }, diff --git a/test/fixtures/ssr-runtime/app.vue b/test/fixtures/ssr-runtime/app.vue new file mode 100644 index 00000000..a6417b00 --- /dev/null +++ b/test/fixtures/ssr-runtime/app.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/ssr-runtime/nuxt.config.ts b/test/fixtures/ssr-runtime/nuxt.config.ts new file mode 100644 index 00000000..13af7cb9 --- /dev/null +++ b/test/fixtures/ssr-runtime/nuxt.config.ts @@ -0,0 +1,11 @@ +import Module from '../../../src/module' + +export default defineNuxtConfig({ + modules: [Module], + icon: { + fallbackToApi: false, + serverBundle: { + collections: ['ph'], + }, + }, +}) diff --git a/test/ssr.test.ts b/test/ssr.test.ts new file mode 100644 index 00000000..6672da77 --- /dev/null +++ b/test/ssr.test.ts @@ -0,0 +1,22 @@ +import { fileURLToPath } from 'node:url' +import { describe, expect, it } from 'vitest' +import { fetch, getServerLogs, setup } from '@nuxt/test-utils/e2e' + +describe('SSR runtime icon loading', async () => { + await setup({ + rootDir: fileURLToPath(new URL('./fixtures/ssr-runtime', import.meta.url)), + build: true, + server: true, + browser: false, + }) + + it('renders icons from the local server provider', async () => { + const response = await fetch('/') + const html = await response.text() + + expect(response.status).toBe(200) + expect(html).toContain('class="iconify i-ph:acorn-bold"') + expect(html).toContain('data:image/svg+xml') + expect(getServerLogs().join('\n')).not.toContain('[Icon] failed to load icon') + }) +})