Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make site work with the Cloudflare OpenNext adapter #7383

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ cache
tsconfig.tsbuildinfo

dist/

# Ignore the blog-data json that we generate during dev and build
apps/site/public/blog-data.json

# Ignore worker artifacts
apps/site/.open-next
apps/site/.wrangler

This file was deleted.

6 changes: 3 additions & 3 deletions apps/site/layouts/Blog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import type { BlogCategory } from '@/types';

import styles from './layouts.module.css';

const getBlogCategory = async (pathname: string) => {
const getBlogCategory = (pathname: string) => {
// pathname format can either be: /en/blog/{category}
// or /en/blog/{category}/page/{page}
// hence we attempt to interpolate the full /en/blog/{category}/page/{page}
// and in case of course no page argument is provided we define it to 1
// note that malformed routes can't happen as they are all statically generated
const [, , category = 'all', , page = 1] = pathname.split('/');

const { posts, pagination } = await getBlogData(
const { posts, pagination } = getBlogData(
category as BlogCategory,
Number(page)
);
Expand All @@ -38,7 +38,7 @@ const BlogLayout: FC = async () => {
link: `/blog/${category}`,
}));

const blogData = await getBlogCategory(pathname);
const blogData = getBlogCategory(pathname);

return (
<>
Expand Down
42 changes: 10 additions & 32 deletions apps/site/next-data/blogData.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
import {
ENABLE_STATIC_EXPORT,
IS_DEV_ENV,
NEXT_DATA_URL,
VERCEL_ENV,
VERCEL_REGION,
} from '@/next.constants.mjs';
import type { BlogCategory, BlogPostsRSC } from '@/types';

const getBlogData = (
cat: BlogCategory,
page?: number
): Promise<BlogPostsRSC> => {
const IS_NOT_VERCEL_RUNTIME_ENV =
(!IS_DEV_ENV && VERCEL_ENV && !VERCEL_REGION) ||
(!IS_DEV_ENV && !VERCEL_ENV);

// When we're using Static Exports the Next.js Server is not running (during build-time)
// hence the self-ingestion APIs will not be available. In this case we want to load
// the data directly within the current thread, which will anyways be loaded only once
// We use lazy-imports to prevent `provideBlogData` from executing on import
if (ENABLE_STATIC_EXPORT || IS_NOT_VERCEL_RUNTIME_ENV) {
return import('@/next-data/providers/blogData').then(
({ provideBlogPosts, providePaginatedBlogPosts }) =>
page ? providePaginatedBlogPosts(cat, page) : provideBlogPosts(cat)
);
}

const fetchURL = `${NEXT_DATA_URL}blog-data/${cat}/${page ?? 0}`;
import {
provideBlogPosts,
providePaginatedBlogPosts,
} from './providers/blogData';

// This data cannot be cached because it is continuously updated. Caching it would lead to
// outdated information being shown to the user.
return fetch(fetchURL)
.then(response => response.text())
.then(JSON.parse);
const getBlogData = (cat: BlogCategory, page?: number): BlogPostsRSC => {
return page && page >= 1
? // This allows us to blindly get all blog posts from a given category
// if the page number is 0 or something smaller than 1
providePaginatedBlogPosts(cat, page)
: provideBlogPosts(cat);
};

export default getBlogData;
10 changes: 8 additions & 2 deletions apps/site/next-data/providers/blogData.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { cache } from 'react';

import generateBlogData from '@/next-data/generators/blogData.mjs';
import { BLOG_POSTS_PER_PAGE } from '@/next.constants.mjs';
import { blogData } from '@/next.json.mjs';
import type { BlogCategory, BlogPostsRSC } from '@/types';

const { categories, posts } = await generateBlogData();
const { categories, posts } = {
...blogData,
posts: blogData.posts.map(post => ({
...post,
date: new Date(post.date),
})),
};

export const provideBlogCategories = cache(() => categories);

Expand Down
4 changes: 4 additions & 0 deletions apps/site/next.json.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import _authors from './authors.json' with { type: 'json' };
import _siteNavigation from './navigation.json' with { type: 'json' };
import _blogData from './public/blog-data.json' with { type: 'json' };
import _siteRedirects from './redirects.json' with { type: 'json' };
import _siteConfig from './site.json' with { type: 'json' };

Expand All @@ -16,3 +17,6 @@ export const siteRedirects = _siteRedirects;

/** @type {import('./types').SiteConfig} */
export const siteConfig = _siteConfig;

/** @type {import('./types').BlogData} */
export const blogData = _blogData;
6 changes: 6 additions & 0 deletions apps/site/open-next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
import kvIncrementalCache from '@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache';

export default defineCloudflareConfig({
incrementalCache: kvIncrementalCache,
});
17 changes: 13 additions & 4 deletions apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"type": "module",
"scripts": {
"scripts:release-post": "cross-env NODE_NO_WARNINGS=1 node scripts/release-post/index.mjs",
"dev": "cross-env NODE_NO_WARNINGS=1 next dev --turbopack",
"serve": "npm run dev",
"dev": "npm run build-blog-data:watch & sleep 1 && cross-env NODE_NO_WARNINGS=1 next dev --turbopack",
"serve": "npm run build-blog-data:watch & sleep 1 && npm run dev",
"prebuild": "npm run build-blog-data",
"build": "cross-env NODE_NO_WARNINGS=1 next build",
"start": "cross-env NODE_NO_WARNINGS=1 next start",
"deploy": "cross-env NEXT_PUBLIC_STATIC_EXPORT=true npm run build",
Expand All @@ -16,9 +17,14 @@
"lint": "turbo run lint:md lint:snippets lint:js lint:css",
"lint:fix": "turbo run lint:md lint:js lint:css --no-cache -- --fix",
"sync-orama": "node ./scripts/orama-search/sync-orama-cloud.mjs",
"build-blog-data": "node ./scripts/blog-data/generate.mjs",
"build-blog-data:watch": "node --watch --watch-path=pages/en ./scripts/blog-data/generate.mjs",
"test:unit": "cross-env NODE_NO_WARNINGS=1 jest",
"test:unit:watch": "npm run test:unit -- --watch",
"test": "turbo test:unit"
"test": "turbo test:unit",
"build:worker": "npx opennextjs-cloudflare build",
"cf:preview": "npm run build:worker && npx wrangler dev",
"cf:deploy": "npx wrangler deploy"
},
"dependencies": {
"@heroicons/react": "~2.2.0",
Expand Down Expand Up @@ -69,6 +75,7 @@
"devDependencies": {
"@eslint/compat": "~1.2.7",
"@next/eslint-plugin-next": "15.2.0",
"@opennextjs/cloudflare": "^0.6.4",
"@testing-library/jest-dom": "~6.6.3",
"@testing-library/react": "~16.2.0",
"@testing-library/user-event": "~14.6.1",
Expand All @@ -91,6 +98,8 @@
"stylelint-selector-bem-pattern": "4.0.1",
"typescript": "~5.7.2",
"typescript-eslint": "~8.25.0",
"user-agent-data-types": "0.4.2"
"user-agent-data-types": "0.4.2",
"wrangler": "https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/14242618656/npm-package-wrangler-8771",
"@dario-hacking/wrangler-build-time-fs-assets-polyfilling": "^0.0.1"
}
}
14 changes: 14 additions & 0 deletions apps/site/scripts/blog-data/generate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { writeFileSync } from 'node:fs';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

import generateBlogData from '../../next-data/generators/blogData.mjs';

const blogData = await generateBlogData();

const __dirname = dirname(fileURLToPath(import.meta.url));
writeFileSync(
`${__dirname}/../../public/blog-data.json`,
JSON.stringify(blogData),
'utf8'
);
32 changes: 32 additions & 0 deletions apps/site/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"main": ".open-next/worker.js",
"name": "nodejs-website",
"compatibility_date": "2024-11-07",
"compatibility_flags": ["nodejs_compat"],
"account_id": "8ed4d03ac99f77561d0e8c9cbcc76cb6",
"minify": true,
"keep_names": false,
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS",
},
"observability": {
"enabled": true,
"head_sampling_rate": 1,
},
"build": {
"command": "wrangler-build-time-fs-assets-polyfilling --assets pages --assets snippets --assets-output-dir .open-next/assets",
},
"alias": {
"node:fs": "./.wrangler/fs-assets-polyfilling/polyfills/node/fs.ts",
"node:fs/promises": "./.wrangler/fs-assets-polyfilling/polyfills/node/fs/promises.ts",
"fs": "./.wrangler/fs-assets-polyfilling/polyfills/node/fs.ts",
"fs/promises": "./.wrangler/fs-assets-polyfilling/polyfills/node/fs/promises.ts",
},
"kv_namespaces": [
{
"binding": "NEXT_CACHE_WORKERS_KV",
"id": "32e8e26d2d2647fd96789baf83209fa9",
},
],
}
2 changes: 2 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default [
'global.d.ts',
'junit.xml',
'storybook-static/**',
'**/.wrangler',
'**/.open-next',
],
},
{
Expand Down
Loading
Loading