From 43ca2b7d35171d3ab3c1a0d32f9a836ee7d7c0eb Mon Sep 17 00:00:00 2001 From: Q Date: Thu, 13 Jul 2023 22:13:11 -0500 Subject: [PATCH 1/3] feat(vite-plugin-nitro): add support for rendering hooks during pre-rendering of routes Enabling ability to pass in functions during post-pre-render to modify pages during build --- packages/platform/src/lib/options.ts | 3 +- .../vite-plugin-nitro/src/lib/build-server.ts | 6 ++++ .../src/lib/hooks/post-rendering-hook.ts | 13 ++++++++ .../lib/hooks/post-rendering-hooks.spec.ts | 32 +++++++++++++++++++ packages/vite-plugin-nitro/src/lib/options.ts | 4 +++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts create mode 100644 packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts diff --git a/packages/platform/src/lib/options.ts b/packages/platform/src/lib/options.ts index 0ca265075..27d0ff9c8 100644 --- a/packages/platform/src/lib/options.ts +++ b/packages/platform/src/lib/options.ts @@ -1,5 +1,5 @@ import type { PluginOptions } from '@analogjs/vite-plugin-angular'; -import { NitroConfig } from 'nitropack'; +import { NitroConfig, PrerenderRoute } from 'nitropack'; import { SitemapConfig } from '@analogjs/vite-plugin-nitro'; export interface PrerenderOptions { @@ -13,6 +13,7 @@ export interface PrerenderOptions { */ routes?: string[] | (() => Promise<(string | undefined)[]>); sitemap?: SitemapConfig; + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; } export interface Options { diff --git a/packages/vite-plugin-nitro/src/lib/build-server.ts b/packages/vite-plugin-nitro/src/lib/build-server.ts index 7194896be..3fee859e4 100644 --- a/packages/vite-plugin-nitro/src/lib/build-server.ts +++ b/packages/vite-plugin-nitro/src/lib/build-server.ts @@ -1,6 +1,7 @@ import { loadEsmModule } from '@angular-devkit/build-angular/src/utils/load-esm'; import { NitroConfig } from 'nitropack'; import { Options } from './options'; +import { runPostRenderingHooks } from './hooks/post-rendering-hook'; export async function buildServer( options?: Options, @@ -14,6 +15,11 @@ export async function buildServer( preset: process.env['BUILD_PRESET'], ...nitroConfig, }); + + if (options?.prerender?.postRenderingHooks) { + runPostRenderingHooks(nitro, options.prerender.postRenderingHooks); + } + await prepare(nitro); await copyPublicAssets(nitro); diff --git a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts new file mode 100644 index 000000000..4fb8c69c5 --- /dev/null +++ b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts @@ -0,0 +1,13 @@ +import { Nitro, PrerenderRoute } from 'nitropack'; + +export function runPostRenderingHooks( + nitro: Nitro, + hooks: ((pr) => Promise)[] +): void { + hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => { + nitro.hooks.hook('prerender:generate', async (route: PrerenderRoute) => { + hook(route); + await Promise.resolve(true); + }); + }); +} diff --git a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts new file mode 100644 index 000000000..b6f45d2cd --- /dev/null +++ b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts @@ -0,0 +1,32 @@ +import { runPostRenderingHooks } from './post-rendering-hook'; +import { vi } from 'vitest'; +import { Nitro } from 'nitropack'; + +describe('postRenderingHook', () => { + const genRoute = { + route: 'test/testRoute', + contents: 'This is a test.', + }; + + const nitroMock = { + hooks: { + hook: vi.fn((name: string, callback: (route) => void) => + callback(genRoute) + ), + }, + } as Nitro; + + const mockFunc1 = vi.fn(); + const mockFunc2 = vi.fn(); + + it('should not attempt to call nitro mocks if no callbacks provided', () => { + runPostRenderingHooks(nitroMock, []); + expect(nitroMock.hooks.hook).not.toHaveBeenCalled(); + }); + + it('should call provided hooks', () => { + runPostRenderingHooks(nitroMock, [mockFunc1, mockFunc2]); + expect(mockFunc1).toHaveBeenCalledWith(genRoute); + expect(mockFunc2).toHaveBeenCalled(genRoute); + }); +}); diff --git a/packages/vite-plugin-nitro/src/lib/options.ts b/packages/vite-plugin-nitro/src/lib/options.ts index 94ededd20..3f9d5dc70 100644 --- a/packages/vite-plugin-nitro/src/lib/options.ts +++ b/packages/vite-plugin-nitro/src/lib/options.ts @@ -1,3 +1,5 @@ +import { PrerenderRoute } from 'nitropack'; + export interface Options { ssr?: boolean; ssrBuildDir?: string; @@ -20,6 +22,8 @@ export interface PrerenderOptions { */ routes?: string[] | (() => Promise<(string | undefined)[]>); sitemap?: SitemapConfig; + /** List of functions that will run after pre-rendering is complete. */ + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; } export interface SitemapConfig { From cb1e22b0a3922e2798dd8265ee56795b326d3fb4 Mon Sep 17 00:00:00 2001 From: Q Date: Thu, 13 Jul 2023 22:26:06 -0500 Subject: [PATCH 2/3] feat(vite-plugin-nitro): add support for rendering hooks during pre-rendering of routes Fix type mismatch downstream --- packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts | 2 +- packages/vite-plugin-nitro/src/lib/options.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts index 4fb8c69c5..f8f368c5b 100644 --- a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts +++ b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts @@ -2,7 +2,7 @@ import { Nitro, PrerenderRoute } from 'nitropack'; export function runPostRenderingHooks( nitro: Nitro, - hooks: ((pr) => Promise)[] + hooks: ((pr: PrerenderRoute) => Promise)[] ): void { hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => { nitro.hooks.hook('prerender:generate', async (route: PrerenderRoute) => { diff --git a/packages/vite-plugin-nitro/src/lib/options.ts b/packages/vite-plugin-nitro/src/lib/options.ts index 3f9d5dc70..fca60010d 100644 --- a/packages/vite-plugin-nitro/src/lib/options.ts +++ b/packages/vite-plugin-nitro/src/lib/options.ts @@ -23,7 +23,7 @@ export interface PrerenderOptions { routes?: string[] | (() => Promise<(string | undefined)[]>); sitemap?: SitemapConfig; /** List of functions that will run after pre-rendering is complete. */ - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; } export interface SitemapConfig { From 6d62b8d7715c49a826b6631ed12b1d9186aba2b6 Mon Sep 17 00:00:00 2001 From: Q Date: Fri, 14 Jul 2023 14:48:07 -0500 Subject: [PATCH 3/3] feat(vite-plugin-nitro): add support for rendering hooks during pre-rendering of routes Made changes based on comments left in the PR. --- packages/platform/src/lib/options.ts | 3 ++- packages/vite-plugin-nitro/src/lib/build-server.ts | 4 ++-- .../vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts | 7 +++---- .../src/lib/hooks/post-rendering-hooks.spec.ts | 6 +++--- packages/vite-plugin-nitro/src/lib/options.ts | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/platform/src/lib/options.ts b/packages/platform/src/lib/options.ts index 27d0ff9c8..b34e40740 100644 --- a/packages/platform/src/lib/options.ts +++ b/packages/platform/src/lib/options.ts @@ -13,7 +13,8 @@ export interface PrerenderOptions { */ routes?: string[] | (() => Promise<(string | undefined)[]>); sitemap?: SitemapConfig; - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; + /** List of functions that run for each route after pre-rendering is complete. */ + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; } export interface Options { diff --git a/packages/vite-plugin-nitro/src/lib/build-server.ts b/packages/vite-plugin-nitro/src/lib/build-server.ts index 3fee859e4..74fa96ce1 100644 --- a/packages/vite-plugin-nitro/src/lib/build-server.ts +++ b/packages/vite-plugin-nitro/src/lib/build-server.ts @@ -1,7 +1,7 @@ import { loadEsmModule } from '@angular-devkit/build-angular/src/utils/load-esm'; import { NitroConfig } from 'nitropack'; import { Options } from './options'; -import { runPostRenderingHooks } from './hooks/post-rendering-hook'; +import { addPostRenderingHooks } from './hooks/post-rendering-hook'; export async function buildServer( options?: Options, @@ -17,7 +17,7 @@ export async function buildServer( }); if (options?.prerender?.postRenderingHooks) { - runPostRenderingHooks(nitro, options.prerender.postRenderingHooks); + addPostRenderingHooks(nitro, options.prerender.postRenderingHooks); } await prepare(nitro); diff --git a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts index f8f368c5b..e22711997 100644 --- a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts +++ b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hook.ts @@ -1,13 +1,12 @@ import { Nitro, PrerenderRoute } from 'nitropack'; -export function runPostRenderingHooks( +export function addPostRenderingHooks( nitro: Nitro, - hooks: ((pr: PrerenderRoute) => Promise)[] + hooks: ((pr: PrerenderRoute) => Promise)[] ): void { hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => { - nitro.hooks.hook('prerender:generate', async (route: PrerenderRoute) => { + nitro.hooks.hook('prerender:generate', (route: PrerenderRoute) => { hook(route); - await Promise.resolve(true); }); }); } diff --git a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts index b6f45d2cd..5fe750779 100644 --- a/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts +++ b/packages/vite-plugin-nitro/src/lib/hooks/post-rendering-hooks.spec.ts @@ -1,4 +1,4 @@ -import { runPostRenderingHooks } from './post-rendering-hook'; +import { addPostRenderingHooks } from './post-rendering-hook'; import { vi } from 'vitest'; import { Nitro } from 'nitropack'; @@ -20,12 +20,12 @@ describe('postRenderingHook', () => { const mockFunc2 = vi.fn(); it('should not attempt to call nitro mocks if no callbacks provided', () => { - runPostRenderingHooks(nitroMock, []); + addPostRenderingHooks(nitroMock, []); expect(nitroMock.hooks.hook).not.toHaveBeenCalled(); }); it('should call provided hooks', () => { - runPostRenderingHooks(nitroMock, [mockFunc1, mockFunc2]); + addPostRenderingHooks(nitroMock, [mockFunc1, mockFunc2]); expect(mockFunc1).toHaveBeenCalledWith(genRoute); expect(mockFunc2).toHaveBeenCalled(genRoute); }); diff --git a/packages/vite-plugin-nitro/src/lib/options.ts b/packages/vite-plugin-nitro/src/lib/options.ts index fca60010d..8d7dea9d6 100644 --- a/packages/vite-plugin-nitro/src/lib/options.ts +++ b/packages/vite-plugin-nitro/src/lib/options.ts @@ -22,8 +22,8 @@ export interface PrerenderOptions { */ routes?: string[] | (() => Promise<(string | undefined)[]>); sitemap?: SitemapConfig; - /** List of functions that will run after pre-rendering is complete. */ - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; + /** List of functions that run for each route after pre-rendering is complete. */ + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; } export interface SitemapConfig {