[Persönliche Website] So integrieren Sie die Notion-Datenbank in Next
Um eine Notion-Datenbank in ein Next.js-Projekt zu integrieren, können Sie Notion als Content-Management-System (CMS) verwenden und dessen Inhalte auf Ihrer Website anzeigen. Nachfolgend finden Sie eine einfache Schritt-für-Schritt-Anleitung, die Ihnen bei der Integration der Notion-Datenbank in Next.js hilft.
Grundlegende Vorbereitung
Erhalten Sie den Notion-API-Schlüssel und die Datenbank-ID
- Notion-API-Schlüssel abrufen: Gehen Sie zum Notion-Entwicklerportal und erstellen Sie eine neue Integration. Nach der Erstellung erhalten Sie einen API-Schlüssel.
- Datenbank-ID abrufen: Navigieren Sie zu der Notion-Datenbank, die Sie integrieren möchten, und kopieren Sie die URL der Datenbankseite. Die Datenbank-ID ist die Zeichenfolge zwischen https://www.notion.so/ und ?v= in der URL.
还不清楚的可以看上篇文章:【01.【个人网站】如何使用Notion作为数据库进行全栈开发】
Verwendung des offiziellen SDK
Schritt 1: Abhängigkeiten installieren
Zuerst müssen Sie das offizielle SDK von Notion, @notionhq/client, installieren, um mit der Notion-API zu kommunizieren. Sie können es mit npm oder Yarn installieren:
npm install @notionhq/client # or yarn add @notionhq/client
Schritt 2: Richten Sie den Notion Client ein
Erstellen Sie eine Datei lib/notion.js im Stammverzeichnis Ihres Next.js-Projekts und konfigurieren Sie den Notion-Client wie folgt:
// lib/notion.js import { Client } from '@notionhq/client'; const notion = new Client({ auth: process.env.NOTION_API_KEY, }); export const getDatabase = async (databaseId) => { const response = await notion.databases.query({ database_id: databaseId }); return response.results; };
Stellen Sie sicher, dass Sie Ihren Notion-API-Schlüssel in einer Umgebungsvariablen NOTION_API_KEY.(.env.local)
speichern
NOTION_API_KEY=your_secret_api_key
Schritt 3: Datenbankinhalt abrufen
Auf Ihrer Next.js-Seite können Sie getStaticProps oder getServerSideProps verwenden, um den Inhalt aus der Notion-Datenbank abzurufen.
// pages/index.js import { getDatabase } from '../lib/notion'; export const getStaticProps = async () => { const databaseId = process.env.NOTION_DATABASE_ID; const posts = await getDatabase(databaseId); return { props: { posts, }, revalidate: 1, // ISR (Incremental Static Regeneration) }; }; export default function Home({ posts }) { return ( <div> <h1>My Notion Blog</h1> <ul> {posts.map((post) => ( <li key={post.id}> {post.properties.Name.title[0].plain_text} </li> ))} </ul> </div> ); }
Stellen Sie sicher, dass Ihre Notion-Datenbank-ID in NOTION_DATABASE_ID als Umgebungsvariable gespeichert ist.
NOTION_DATABASE_ID=your_database_id
Schritt 4: Bereitstellung und Überprüfung
Stellen Sie abschließend Ihr Next.js-Projekt auf Vercel oder einer anderen Plattform bereit und überprüfen Sie, ob Sie erfolgreich Daten aus der Notion-Datenbank abrufen und anzeigen können.
Zusätzliche Tipps
- Sie können verschiedene Eigenschaften von Notion-Seiten (wie Name, Tags, Datum usw.) auf Ihrer Seite anzeigen.
- Erwägen Sie die Verwendung von getServerSideProps, um Daten bei jeder Anfrage abzurufen, oder verwenden Sie getStaticProps mit ISR (Inkrementelle statische Regeneration), um die Leistung zu optimieren.
Indem Sie diese Schritte befolgen, können Sie eine Notion-Datenbank erfolgreich in Ihr Next.js-Projekt integrieren und zum Verwalten und Anzeigen von Inhalten verwenden.
Verwendung der Notion-API mit umschlossenen URLs
Schließlich habe ich diese Methode aus Bequemlichkeitsgründen bei der Integration mit den React-Notion-X-Komponenten verwendet.
Stellen Sie sicher, dass Sie Ihre Notion-Datenbank-ID und Ihren Notion-API-Schlüssel zur .env.local-Datei hinzufügen:
NOTION_DATABASE_ID=your_database_id NOTION_API_KEY=your_secret_api_key
Schritt 1: Installieren Sie die erforderlichen Abhängigkeiten
Installieren Sie zunächst die erforderlichen Abhängigkeiten wie Notion-Types und Notion-Utils und bearbeiten Sie Anfragen an die Notion-API.
npm install notion-types notion-utils got p-map
Schritt 2: Erstellen Sie eine Datei, um Notion-API-Interaktionen zu kapseln
Erstellen Sie in Ihrem Next.js-Projekt eine Datei, zum Beispiel lib/NotionAPI.ts, die Interaktionen mit der Notion-API kapselt. Diese Datei enthält Methoden zum Aufrufen von Notion-API-Endpunkten, um Daten von Seiten und Sammlungen abzurufen.
// lib/NotionAPI.ts import * as notion from "notion-types"; import got, { OptionsOfJSONResponseBody } from "got"; import { getBlockCollectionId, getPageContentBlockIds, parsePageId, uuidToId, } from "notion-utils"; import pMap from "p-map"; // 定义权限记录接口 export interface SignedUrlRequest { permissionRecord: PermissionRecord; url: string; } export interface PermissionRecord { table: string; id: notion.ID; } export interface SignedUrlResponse { signedUrls: string[]; } // 定义NotionAPI类 export class NotionAPI { private readonly _apiBaseUrl: string; private readonly _authToken?: string; private readonly _activeUser?: string; private readonly _userTimeZone: string; constructor({ apiBaseUrl = "<https://www.notion.so/api/v3>", authToken, activeUser, userTimeZone = "America/New_York", }: { apiBaseUrl?: string; authToken?: string; userLocale?: string; userTimeZone?: string; activeUser?: string; } = {}) { this._apiBaseUrl = apiBaseUrl; this._authToken = authToken; this._activeUser = activeUser; this._userTimeZone = userTimeZone; } // 获取页面内容 public async getPage( pageId: string, { concurrency = 3, fetchMissingBlocks = true, fetchCollections = true, signFileUrls = true, chunkLimit = 100, chunkNumber = 0, gotOptions, }: { concurrency?: number; fetchMissingBlocks?: boolean; fetchCollections?: boolean; signFileUrls?: boolean; chunkLimit?: number; chunkNumber?: number; gotOptions?: OptionsOfJSONResponseBody; } = {} ): Promise<notion.ExtendedRecordMap> { const page = await this.getPageRaw(pageId, { chunkLimit, chunkNumber, gotOptions, }); const recordMap = page?.recordMap as notion.ExtendedRecordMap; if (!recordMap?.block) { throw new Error(`Notion page not found "${uuidToId(pageId)}"`); } recordMap.collection = recordMap.collection ?? {}; recordMap.collection_view = recordMap.collection_view ?? {}; recordMap.notion_user = recordMap.notion_user ?? {}; recordMap.collection_query = {}; recordMap.signed_urls = {}; if (fetchMissingBlocks) { while (true) { const pendingBlockIds = getPageContentBlockIds(recordMap).filter( (id) => !recordMap.block[id] ); if (!pendingBlockIds.length) { break; } const newBlocks = await this.getBlocks( pendingBlockIds, gotOptions ).then((res) => res.recordMap.block); recordMap.block = { ...recordMap.block, ...newBlocks }; } } const contentBlockIds = getPageContentBlockIds(recordMap); if (fetchCollections) { const allCollectionInstances: Array<{ collectionId: string; collectionViewId: string; }> = contentBlockIds.flatMap((blockId) => { const block = recordMap.block[blockId].value; const collectionId = block && (block.type === "collection_view" || block.type === "collection_view_page") && getBlockCollectionId(block, recordMap); if (collectionId) { return block.view_ids?.map((collectionViewId) => ({ collectionId, collectionViewId, })); } else { return []; } }); await pMap( allCollectionInstances, async (collectionInstance) => { const { collectionId, collectionViewId } = collectionInstance; const collectionView = recordMap.collection_view[collectionViewId]?.value; try { const collectionData = await this.getCollectionData( collectionId, collectionViewId, collectionView, { gotOptions, } ); recordMap.block = { ...recordMap.block, ...collectionData.recordMap.block, }; recordMap.collection = { ...recordMap.collection, ...collectionData.recordMap.collection, }; recordMap.collection_view = { ...recordMap.collection_view, ...collectionData.recordMap.collection_view, }; recordMap.notion_user = { ...recordMap.notion_user, ...collectionData.recordMap.notion_user, }; recordMap.collection_query![collectionId] = { ...recordMap.collection_query![collectionId], [collectionViewId]: (collectionData.result as any) ?.reducerResults, }; } catch (err: any) { console.warn( "NotionAPI collectionQuery error", pageId, err.message ); } }, { concurrency, } ); } if (signFileUrls) { await this.addSignedUrls({ recordMap, contentBlockIds, gotOptions }); } return recordMap; } public async addSignedUrls({ recordMap, contentBlockIds, gotOptions = {}, }: { recordMap: notion.ExtendedRecordMap; contentBlockIds?: string[]; gotOptions?: OptionsOfJSONResponseBody; }) { recordMap.signed_urls = {}; if (!contentBlockIds) { contentBlockIds = getPageContentBlockIds(recordMap); } const allFileInstances = contentBlockIds.flatMap((blockId) => { const block = recordMap.block[blockId]?.value; if ( block && (block.type === "pdf" || block.type === "audio" || (block.type === "image" && block.file_ids?.length) || block.type === "video" || block.type === "file" || block.type === "page") ) { const source = block.type === "page" ? block.format?.page_cover : block.properties?.source?.[0]?.[0]; if (source) { if (!source.includes("secure.notion-static.com")) { return []; } return { permissionRecord: { table: "block", id: block.id, }, url: source, }; } } return []; }); if (allFileInstances.length > 0) { try { const { signedUrls } = await this.getSignedFileUrls( allFileInstances, gotOptions ); if (signedUrls.length === allFileInstances.length) { for (let i = 0; i < allFileInstances.length; ++i) { const file = allFileInstances[i]; const signedUrl = signedUrls[i]; recordMap.signed_urls[file.permissionRecord.id] = signedUrl; } } } catch (err) { console.warn("NotionAPI getSignedfileUrls error", err); } } } public async getPageRaw( pageId: string, { gotOptions, chunkLimit = 100, chunkNumber = 0, }: { chunkLimit?: number; chunkNumber?: number; gotOptions?: OptionsOfJSONResponseBody; } = {} ): Promise<notion.PageChunk> { const parsedPageId = parsePageId(pageId); if (!parsedPageId) { throw new Error(`invalid notion pageId "${pageId}"`); } const body = { pageId: parsedPageId, limit: chunkLimit, chunkNumber: chunkNumber, cursor: { stack: [] }, verticalColumns: false, }; return this.fetch<notion.PageChunk>({ endpoint: "loadPageChunk", body, gotOptions, }); } public async getCollectionData( collectionId: string, collectionViewId: string, collectionView?: any, { limit = 9999, searchQuery = "", userTimeZone = this._userTimeZone, loadContentCover = true, gotOptions, }: { limit?: number; searchQuery?: string; userTimeZone?: string; loadContentCover?: boolean; gotOptions?: OptionsOfJSONResponseBody; } = {} ) { const type = collectionView?.type; const isBoardType = type === "board"; const groupBy = isBoardType ? collectionView?.format?.board_columns_by : collectionView?.format?.collection_group_by; let filters = []; if (collectionView?.format?.property_filters) { filters = collectionView.format?.property_filters.map( (filterObj : any) => ({ property: filterObj?.property, filter: { operator: "and", filters: filterObj?.filter?.filters, }, }) ); } const body = { collection: { id: collectionId, }, collectionView: { id: collectionViewId, }, loader: { type: "reducer", reducers: { collection_group_results: { type: "results", limit, loadContentCover, }, }, userTimeZone, limit, loadContentCover, searchQuery, userLocale: "en", ...(filters.length > 0 ? { filters } : {}), ...(groupBy ? { groupBy, } : {}), }, }; return this.fetch<notion.CollectionInstance>({ endpoint: "queryCollection", body, gotOptions, }); } private async fetch<R>({ endpoint, body, gotOptions, }: { endpoint: string; body: unknown; gotOptions?: OptionsOfJSONResponseBody; }) { const url = `${this._apiBaseUrl}/${endpoint}`; const json = true; const method = "POST"; const headers: Record<string, string> = { "Content-Type": "application/json", }; if (this._authToken) { headers.cookie = `token_v2=${this._authToken}`; } if (this._activeUser) { headers["x-notion-active-user-header"] = this._activeUser; } try { const res = await got.post(url, { ...gotOptions, json, method, body, headers, }); return res.body as R; } catch (err) { console.error(`NotionAPI error: ${err.message}`); throw err; } } private async getSignedFileUrls( urls: SignedUrlRequest[], gotOptions?: OptionsOfJSONResponseBody ): Promise<SignedUrlResponse> { return this.fetch<SignedUrlResponse>({ endpoint: "getSignedFileUrls", body: { urls }, gotOptions, }); } private async getBlocks( blockIds: string[], gotOptions?: OptionsOfJSONResponseBody ): Promise<notion.PageChunk> { return this.fetch<notion.PageChunk>({ endpoint: "syncRecordValues", body: { requests: blockIds.map((blockId) => ({ id: blockId, table: "block", version: -1, })), }, gotOptions, }); } }
Schritt 3: Verwenden Sie die gekapselte API in Next.js-Seiten
Um Notion-Datenbankinhalte in Ihren Next.js-Seiten abzurufen, können Sie die gekapselte NotionAPI-Klasse verwenden und die abgerufenen Daten zum Rendern an React-Notion-X-Komponenten übergeben.
// pages/[pageId].tsx import { GetServerSideProps } from 'next'; import { NotionAPI } from '../lib/NotionAPI'; import { NotionRenderer } from 'react-notion-x'; import 'react-notion-x/src/styles.css'; export const getServerSideProps: GetServerSideProps = async (context) => { const { pageId } = context.params; const notion = new NotionAPI(); const recordMap = await notion.getPage(pageId as string); return { props: { recordMap, }, }; }; const NotionPage = ({ recordMap }) => { return <NotionRenderer recordMap={recordMap} fullPage={true} darkMode={false} />; }; export default NotionPage;
Schritt 4: Routing in Next.js konfigurieren
Um sicherzustellen, dass die Datei [pageId].tsx verschiedene Notion-Seiten dynamisch rendern kann, müssen Sie dynamisches Routing in Next.js einrichten. Dadurch können Sie den pageId-Parameter abgleichen und den entsprechenden Notion-Seiteninhalt abrufen.
So können Sie dynamische Routen konfigurieren:
- Erstellen Sie eine dynamische Routendatei im Seitenverzeichnis:
Erstellen Sie in Ihrem Seitenverzeichnis eine neue Datei mit dem Namen [pageId].tsx:
pages/[pageId].tsx
- Dynamisches Seiten-Rendering implementieren:
Rufen Sie in der Datei [pageId].tsx den Notion-Inhalt basierend auf der pageId von der URL ab und rendern Sie ihn dynamisch.
Beispielcode:
import { GetStaticProps, GetStaticPaths } from 'next'; import { NotionRenderer } from 'react-notion-x'; import { getNotionPageData } from '../lib/NotionAPI'; import 'react-notion-x/src/styles.css'; export default function NotionPage({ pageData }) { return ( <div> <NotionRenderer recordMap={pageData} fullPage={true} darkMode={false} /> </div> ); } export const getStaticProps: GetStaticProps = async ({ params }) => { const { pageId } = params!; const pageData = await getNotionPageData(pageId as string); return { props: { pageData, }, revalidate: 10, // Revalidate content every 10 seconds (ISR) }; }; export const getStaticPaths: GetStaticPaths = async () => { return { paths: [], // We’ll use fallback to handle dynamic routes fallback: 'blocking', // Generate pages on the fly if not pre-rendered }; };
- Explanation:
- getStaticPaths: Since your content is dynamic, we return an empty array for paths and set fallback: 'blocking' to generate pages on demand.
- getStaticProps: Fetches the Notion page content based on the pageId passed in the URL.
Summary
By following the steps above, you can now encapsulate Notion API requests and render Notion pages dynamically in your Next.js project using react-notion-x. This setup allows you to efficiently integrate Notion as a CMS while ensuring scalability and maintainability in your Next.js application.
Das obige ist der detaillierte Inhalt von[Persönliche Website] So integrieren Sie die Notion-Datenbank in Next. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Sowohl Python als auch JavaScripts Entscheidungen in Entwicklungsumgebungen sind wichtig. 1) Die Entwicklungsumgebung von Python umfasst Pycharm, Jupyternotebook und Anaconda, die für Datenwissenschaft und schnelles Prototyping geeignet sind. 2) Die Entwicklungsumgebung von JavaScript umfasst Node.JS, VSCODE und WebPack, die für die Entwicklung von Front-End- und Back-End-Entwicklung geeignet sind. Durch die Auswahl der richtigen Tools nach den Projektbedürfnissen kann die Entwicklung der Entwicklung und die Erfolgsquote der Projekte verbessert werden.

C und C spielen eine wichtige Rolle in der JavaScript -Engine, die hauptsächlich zur Implementierung von Dolmetschern und JIT -Compilern verwendet wird. 1) C wird verwendet, um JavaScript -Quellcode zu analysieren und einen abstrakten Syntaxbaum zu generieren. 2) C ist für die Generierung und Ausführung von Bytecode verantwortlich. 3) C implementiert den JIT-Compiler, optimiert und kompiliert Hot-Spot-Code zur Laufzeit und verbessert die Ausführungseffizienz von JavaScript erheblich.
