From 2f4748a08f19ce996a199c78cab75701020f74b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Filho?= Date: Fri, 20 Jun 2025 13:56:24 -0300 Subject: [PATCH 1/2] feat: add OpenNextjs preset --- packages/config/src/types.ts | 1 + packages/presets/src/index.ts | 1 + .../presets/src/presets/opennextjs/config.ts | 58 ++++++++++++++ .../presets/src/presets/opennextjs/index.ts | 6 ++ .../src/presets/opennextjs/metadata.ts | 7 ++ .../src/presets/opennextjs/prebuild.ts | 80 +++++++++++++++++++ 6 files changed, 153 insertions(+) create mode 100644 packages/presets/src/presets/opennextjs/config.ts create mode 100644 packages/presets/src/presets/opennextjs/index.ts create mode 100644 packages/presets/src/presets/opennextjs/metadata.ts create mode 100644 packages/presets/src/presets/opennextjs/prebuild.ts diff --git a/packages/config/src/types.ts b/packages/config/src/types.ts index 9095200c..688c36d7 100644 --- a/packages/config/src/types.ts +++ b/packages/config/src/types.ts @@ -543,6 +543,7 @@ export interface BundlerSetup { export interface BuildContext { production: boolean; handler: BuildEntryPoint; + skipProjectBuild?: boolean; } export type PresetMetadata = { diff --git a/packages/presets/src/index.ts b/packages/presets/src/index.ts index 9debfb3b..186df063 100644 --- a/packages/presets/src/index.ts +++ b/packages/presets/src/index.ts @@ -11,6 +11,7 @@ export * from './presets/javascript'; export * from './presets/jekyll'; export * from './presets/next'; export * from './presets/nuxt'; +export * from './presets/opennextjs'; export * from './presets/preact'; export * from './presets/qwik'; export * from './presets/react'; diff --git a/packages/presets/src/presets/opennextjs/config.ts b/packages/presets/src/presets/opennextjs/config.ts new file mode 100644 index 00000000..367680c7 --- /dev/null +++ b/packages/presets/src/presets/opennextjs/config.ts @@ -0,0 +1,58 @@ +import type { AzionBuild, AzionConfig } from 'azion/config'; + +const config: AzionConfig = { + build: { + entry: '.open-next/worker.js', + polyfills: true, + bundler: 'esbuild', + preset: 'opennextjs', + } as AzionBuild, + origin: [ + { + name: 'origin-storage-default', + type: 'object_storage', + }, + ], + functions: [ + { + name: 'handler', + path: '.edge/functions/handler.js', + }, + ], + rules: { + request: [ + { + name: 'Set Storage Origin for All Requests', + match: '^\\/_next\\/static\\/', // starts with '/_next/static/' + behavior: { + setOrigin: { + name: 'origin-storage-default', + type: 'object_storage', + }, + deliver: true, + }, + }, + { + name: 'Deliver Static Assets', + match: '.(css|js|ttf|woff|woff2|pdf|svg|jpg|jpeg|gif|bmp|png|ico|mp4|json)$', + behavior: { + setOrigin: { + name: 'origin-storage-default', + type: 'object_storage', + }, + deliver: true, + }, + }, + { + name: 'Execute Edge Function', + match: '^/', + behavior: { + runFunction: 'handler', + forwardCookies: true, + }, + }, + ], + }, +}; + +export default config; diff --git a/packages/presets/src/presets/opennextjs/index.ts b/packages/presets/src/presets/opennextjs/index.ts new file mode 100644 index 00000000..5495a0b8 --- /dev/null +++ b/packages/presets/src/presets/opennextjs/index.ts @@ -0,0 +1,6 @@ +import type { AzionBuildPreset } from 'azion/config'; +import config from './config'; +import metadata from './metadata'; +import prebuild from './prebuild'; + +export const opennextjs: AzionBuildPreset = { config, metadata, prebuild }; diff --git a/packages/presets/src/presets/opennextjs/metadata.ts b/packages/presets/src/presets/opennextjs/metadata.ts new file mode 100644 index 00000000..c75857ae --- /dev/null +++ b/packages/presets/src/presets/opennextjs/metadata.ts @@ -0,0 +1,7 @@ +import type { PresetMetadata } from 'azion/config'; + +const metadata: PresetMetadata = { + name: 'opennextjs', +}; + +export default metadata; diff --git a/packages/presets/src/presets/opennextjs/prebuild.ts b/packages/presets/src/presets/opennextjs/prebuild.ts new file mode 100644 index 00000000..6b0eb895 --- /dev/null +++ b/packages/presets/src/presets/opennextjs/prebuild.ts @@ -0,0 +1,80 @@ +import { BuildConfiguration, BuildContext } from 'azion/config'; +import { exec } from 'azion/utils/node'; +import { readFile } from 'fs/promises'; +import path from 'path'; + +/** + * Runs custom prebuild actions for OpenNextjs + */ +async function prebuild(buildConfig: BuildConfiguration, ctx: BuildContext): Promise { + const pkgOpenNextjsName = '@aziontech/opennextjs-azion'; + const openNextjsCommand = 'npm exec opennextjs-azion'; + + // Check if the OpenNextjs Azion is installed + const isOpenNextjsInstalled = await checkIfOpenNextjsIsInstalled(); + if (!isOpenNextjsInstalled) { + const packageManager = await indentifyPackageManager(); + const execCommand = + packageManager === 'yarn' + ? `yarn add -D ${pkgOpenNextjsName}` + : packageManager === 'pnpm' + ? `pnpm add -D ${pkgOpenNextjsName}` + : `npm i -D ${pkgOpenNextjsName}`; + await exec(execCommand, { + scope: 'OpenNextjs', + verbose: true, + interactive: true, + }); + } + // Run OpenNextjs command build + if (ctx.production || !ctx.skipProjectBuild) { + const skipBuild = ctx.skipProjectBuild ? '--skipBuild' : ''; + await exec(`${openNextjsCommand} build -- ${skipBuild}`, { + scope: 'OpenNextjs', + verbose: true, + interactive: true, + }); + } + + // Run OpenNextjs commands to populate assets + if (ctx.production) { + await exec(`${openNextjsCommand} populateAssets`, { + scope: 'OpenNextjs', + verbose: true, + }); + } + + // Run OpenNextjs commands to populate cache + if (ctx.production) { + await exec(`${openNextjsCommand} populateCache`, { + scope: 'OpenNextjs', + verbose: true, + }); + } +} + +async function checkIfOpenNextjsIsInstalled(): Promise { + const packageJsonPath = path.resolve(process.cwd(), 'package.json'); + const packageJson = await readFile(packageJsonPath, 'utf-8'); + const packageJsonObj = JSON.parse(packageJson); + if (!packageJsonObj.devDependencies || !packageJsonObj.devDependencies['@aziontech/opennextjs-azion']) { + return false; + } + return true; +} + +async function indentifyPackageManager(): Promise { + const lockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']; + for (const lockFile of lockFiles) { + const filePath = path.resolve(process.cwd(), lockFile); + try { + await readFile(filePath, 'utf-8'); + return lockFile.includes('yarn') ? 'yarn' : lockFile.includes('pnpm') ? 'pnpm' : 'npm'; + } catch (error) { + // File not found, continue to the next one + } + } + return 'npm'; // Default to npm if no lock file is found +} + +export default prebuild; From bfd9d938557673ab9171b809a3d29e5e573f6112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Filho?= Date: Fri, 20 Jun 2025 14:56:01 -0300 Subject: [PATCH 2/2] chore: update request rule name for consistency in OpenNextjs preset --- packages/presets/src/presets/opennextjs/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/presets/src/presets/opennextjs/config.ts b/packages/presets/src/presets/opennextjs/config.ts index 367680c7..b6fdccce 100644 --- a/packages/presets/src/presets/opennextjs/config.ts +++ b/packages/presets/src/presets/opennextjs/config.ts @@ -22,7 +22,7 @@ const config: AzionConfig = { rules: { request: [ { - name: 'Set Storage Origin for All Requests', + name: 'Set storage origin for all requests _next_static', match: '^\\/_next\\/static\\/', // starts with '/_next/static/' behavior: { setOrigin: {