diff --git a/components/ExternalPlugins.js b/components/ExternalPlugins.js index 89c18688845..616792e84d6 100644 --- a/components/ExternalPlugins.js +++ b/components/ExternalPlugins.js @@ -6,7 +6,7 @@ import TianLiGPT from './TianliGPT' import WebWhiz from './Webwhiz' import { CUSTOM_EXTERNAL_CSS, CUSTOM_EXTERNAL_JS } from '@/blog.config' -import { mapPageUrl } from '@/lib/notion/mapPageUrl' +import { convertInnerUrl } from '@/lib/notion/convertInnerUrl' import { isBrowser, loadExternalResource } from '@/lib/utils' import { useRouter } from 'next/router' import { useEffect } from 'react' @@ -106,7 +106,7 @@ const ExternalPlugin = props => { } // 映射url - mapPageUrl(props?.allNavPages) + convertInnerUrl(props?.allNavPages) }, [router]) useEffect(() => { diff --git a/lib/db/getSiteData.js b/lib/db/getSiteData.js index 272c17f15cc..f113eb20593 100755 --- a/lib/db/getSiteData.js +++ b/lib/db/getSiteData.js @@ -7,16 +7,16 @@ import { getConfigMapFromConfigPage } from '@/lib/notion/getNotionConfig' import getPageProperties, { adjustPageProperties } from '@/lib/notion/getPageProperties' -import { fetchInBatches, getPostBlocks } from '@/lib/notion/getPostBlocks' +import { fetchInBatches, getPage } from '@/lib/notion/getPostBlocks' import { compressImage, mapImgUrl } from '@/lib/notion/mapImage' import { deepClone } from '@/lib/utils' import { idToUuid } from 'notion-utils' import { siteConfig } from '../config' -import { extractLangId, extractLangPrefix } from '../utils/pageId' +import { extractLangId, extractLangPrefix, getShortId } from '../utils/pageId' export { getAllTags } from '../notion/getAllTags' export { getPost } from '../notion/getNotionPost' -export { getPostBlocks } from '../notion/getPostBlocks' +export { getPage as getPostBlocks } from '../notion/getPostBlocks' /** * 获取博客数据; 基于Notion实现 @@ -77,7 +77,16 @@ export async function getNotionPageData({ pageId, from }) { } // 返回给前端的数据做处理 - const db = deepClone(data) + return compressData(deepClone(data)) +} + +/** + * 减少返回给前端的数据 + * 并脱敏 + * @param {*} db + */ +function compressData(db) { + // 清理多余数据 delete db.block delete db.schema delete db.rawMetadata @@ -91,42 +100,88 @@ export async function getNotionPageData({ pageId, from }) { // 清理多余的块 if (db?.notice) { db.notice = cleanBlock(db?.notice) + delete db.notice?.id } - if (db?.post) { - db.post = cleanBlock(db?.post) - } + + db.tagOptions = cleanIds(db?.tagOptions) + db.categoryOptions = cleanIds(db?.categoryOptions) + db.customMenu = cleanIds(db?.customMenu) + + db.latestPosts = shortenIds(db?.latestPosts) + db.allNavPages = shortenIds(db?.allNavPages) + // db.allPages = cleanBlocks(db?.allPages) + return db } /** - * 清理block数据 + * 清理一组数据的id + * @param {*} items + * @returns */ -function cleanBlock(post) { - const pageBlock = post?.blockMap?.block - for (const i in pageBlock) { - pageBlock[i] = cleanBlock(pageBlock[i]) - delete pageBlock[i]?.role - delete pageBlock[i]?.value?.version - delete pageBlock[i]?.value?.created_by_table - delete pageBlock[i]?.value?.created_by_id - delete pageBlock[i]?.value?.last_edited_by_table - delete pageBlock[i]?.value?.last_edited_by_id - delete pageBlock[i]?.value?.space_id - delete pageBlock[i]?.value?.version - delete pageBlock[i]?.value?.format?.copied_from_pointer - delete pageBlock[i]?.value?.format?.block_locked_by - delete pageBlock[i]?.value?.parent_table - delete pageBlock[i]?.value?.copied_from_pointer - delete pageBlock[i]?.value?.copied_from - delete pageBlock[i]?.value?.created_by_table - delete pageBlock[i]?.value?.created_by_id - delete pageBlock[i]?.value?.last_edited_by_table - delete pageBlock[i]?.value?.last_edited_by_id - delete pageBlock[i]?.value?.permissions - delete pageBlock[i]?.value?.alive +function shortenIds(items) { + if (items && Array.isArray(items)) { + return deepClone( + items.map(item => { + item.short_id = getShortId(item.id) + delete item.id + return item + }) + ) } + return items +} +/** + * 清理一组数据的id + * @param {*} items + * @returns + */ +function cleanIds(items) { + if (items && Array.isArray(items)) { + return deepClone( + items.map(item => { + delete item.id + return item + }) + ) + } + return items +} + +/** + * 清理block数据 + */ +function cleanBlock(item) { + const post = deepClone(item) + const pageBlock = post?.blockMap?.block + // delete post?.id // delete post?.blockMap?.collection + + if (pageBlock) { + for (const i in pageBlock) { + pageBlock[i] = cleanBlock(pageBlock[i]) + delete pageBlock[i]?.role + delete pageBlock[i]?.value?.version + delete pageBlock[i]?.value?.created_by_table + delete pageBlock[i]?.value?.created_by_id + delete pageBlock[i]?.value?.last_edited_by_table + delete pageBlock[i]?.value?.last_edited_by_id + delete pageBlock[i]?.value?.space_id + delete pageBlock[i]?.value?.version + delete pageBlock[i]?.value?.format?.copied_from_pointer + delete pageBlock[i]?.value?.format?.block_locked_by + delete pageBlock[i]?.value?.parent_table + delete pageBlock[i]?.value?.copied_from_pointer + delete pageBlock[i]?.value?.copied_from + delete pageBlock[i]?.value?.created_by_table + delete pageBlock[i]?.value?.created_by_id + delete pageBlock[i]?.value?.last_edited_by_table + delete pageBlock[i]?.value?.last_edited_by_id + delete pageBlock[i]?.value?.permissions + delete pageBlock[i]?.value?.alive + } + } return post } @@ -320,7 +375,7 @@ async function getNotice(post) { return null } - post.blockMap = await getPostBlocks(post.id, 'data-notice') + post.blockMap = await getPage(post.id, 'data-notice') return post } @@ -372,7 +427,7 @@ const EmptyData = pageId => { */ async function getDataBaseInfoByNotionAPI({ pageId, from }) { console.log('[Fetching Data]', pageId, from) - const pageRecordMap = await getPostBlocks(pageId, from) + const pageRecordMap = await getPage(pageId, from) if (!pageRecordMap) { console.error('can`t get Notion Data ; Which id is: ', pageId) return {} diff --git a/lib/notion/mapPageUrl.js b/lib/notion/convertInnerUrl.js similarity index 77% rename from lib/notion/mapPageUrl.js rename to lib/notion/convertInnerUrl.js index 80fe70d8e2b..f4539fb4835 100644 --- a/lib/notion/mapPageUrl.js +++ b/lib/notion/convertInnerUrl.js @@ -1,12 +1,12 @@ -import { uuidToId } from 'notion-utils' +import { idToUuid } from 'notion-utils' import { checkStrIsNotionId, getLastPartOfUrl, isBrowser } from '../utils' /** * 处理页面内连接跳转: - * 1. 若是本站域名,则在当前窗口打开、不开新窗口 - * 2. 若是Notion笔记中的内链,尝试转换成博客中现有的文章地址 + * 1.若是本站域名,则在当前窗口打开、不开新窗口 + * 2.url是notion-id,转成站内文章链接 */ -export const mapPageUrl = allPages => { +export const convertInnerUrl = allPages => { if (isBrowser) { const currentURL = window.location.origin + window.location.pathname const allAnchorTags = document.getElementsByTagName('a') // 或者使用 document.querySelectorAll('a') 获取 NodeList @@ -16,7 +16,9 @@ export const mapPageUrl = allPages => { // 如果url是一个Notion_id,尝试匹配成博客的文章内链 const slug = getLastPartOfUrl(anchorTag.href) if (checkStrIsNotionId(slug)) { - const slugPage = allPages?.find(page => uuidToId(page.id) === slug) + const slugPage = allPages?.find(page => { + return idToUuid(slug).indexOf(page.short_id) === 0 + }) if (slugPage) { anchorTag.href = slugPage?.href } diff --git a/lib/notion/getNotionConfig.js b/lib/notion/getNotionConfig.js index 889005f2a22..c0ef7c29a5f 100644 --- a/lib/notion/getNotionConfig.js +++ b/lib/notion/getNotionConfig.js @@ -9,7 +9,7 @@ import { getDateValue, getTextContent } from 'notion-utils' import { deepClone } from '../utils' import getAllPageIds from './getAllPageIds' -import { getPostBlocks } from './getPostBlocks' +import { getPage } from './getPostBlocks' /** * 从Notion中读取Config配置表 @@ -41,12 +41,12 @@ export async function getConfigMapFromConfigPage(allPages) { } const configPageId = configPage.id // console.log('[Notion配置]请求配置数据 ', configPage.id) - let pageRecordMap = await getPostBlocks(configPageId, 'config-table') + let pageRecordMap = await getPage(configPageId, 'config-table') // console.log('配置中心Page', configPageId, pageRecordMap) let content = pageRecordMap.block[configPageId].value.content for (const table of ['Config-Table', 'CONFIG-TABLE']) { if (content) break - pageRecordMap = await getPostBlocks(configPageId, table) + pageRecordMap = await getPage(configPageId, table) content = pageRecordMap.block[configPageId].value.content } diff --git a/lib/notion/getNotionPost.js b/lib/notion/getNotionPost.js index 3e096a1148b..f5aabb2a15a 100644 --- a/lib/notion/getNotionPost.js +++ b/lib/notion/getNotionPost.js @@ -2,7 +2,7 @@ import BLOG from '@/blog.config' import { idToUuid } from 'notion-utils' import { defaultMapImageUrl } from 'react-notion-x' import formatDate from '../utils/formatDate' -import { getPostBlocks } from './getPostBlocks' +import { getPage } from './getPostBlocks' /** * 根据页面ID获取内容 @@ -10,7 +10,7 @@ import { getPostBlocks } from './getPostBlocks' * @returns */ export async function getPost(pageId) { - const blockMap = await getPostBlocks(pageId, 'slug') + const blockMap = await getPage(pageId, 'slug') if (!blockMap) { return null } diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js index 0b151f17be9..8bac9e2ad3f 100644 --- a/lib/notion/getPostBlocks.js +++ b/lib/notion/getPostBlocks.js @@ -10,7 +10,7 @@ import { deepClone, delay } from '../utils' * @param {*} slice * @returns */ -export async function getPostBlocks(id, from, slice) { +export async function getPage(id, from, slice) { const cacheKey = 'page_block_' + id let pageBlock = await getDataFromCache(cacheKey) if (pageBlock) { @@ -27,28 +27,6 @@ export async function getPostBlocks(id, from, slice) { return pageBlock } -/** - * 针对在getDataBaseInfoByNotionAPI=>getPostBlocks中获取不到的溢出的block-id,用此方法另外抓取 - * @param {*} id - * @param {*} from - * @returns - */ -export async function getSingleBlock(id, from) { - const cacheKey = 'single_block_' + id - let pageBlock = await getDataFromCache(cacheKey) - if (pageBlock) { - // console.log('[API<<--缓存]', `from:${from}`, cacheKey) - return pageBlock - } - - pageBlock = await getPageWithRetry(id, 'single_' + from) - - if (pageBlock) { - await setDataToCache(cacheKey, pageBlock) - } - return pageBlock -} - /** * 调用接口,失败会重试 * @param {*} id @@ -162,6 +140,11 @@ function filterPostBlocks(id, blockMap, slice) { * @returns */ export const fetchInBatches = async (ids, batchSize = 100) => { + // 如果 ids 不是数组,则将其转换为数组 + if (!Array.isArray(ids)) { + ids = [ids] + } + const authToken = BLOG.NOTION_ACCESS_TOKEN || null const api = new NotionAPI({ authToken, @@ -171,7 +154,7 @@ export const fetchInBatches = async (ids, batchSize = 100) => { let fetchedBlocks = {} for (let i = 0; i < ids.length; i += batchSize) { const batch = ids.slice(i, i + batchSize) - console.log('[API-->>请求] Fetching missing blocks', ids.length) + console.log('[API-->>请求] Fetching missing blocks', batch, ids.length) const start = new Date().getTime() const pageChunk = await api.getBlocks(batch) const end = new Date().getTime() diff --git a/lib/utils/pageId.js b/lib/utils/pageId.js index e3c648e1649..c963df28b62 100644 --- a/lib/utils/pageId.js +++ b/lib/utils/pageId.js @@ -30,4 +30,18 @@ function extractLangId(str) { } } -module.exports = { extractLangPrefix, extractLangId } +/** + * 列表中用过来区分page只需要端的id足够 + */ + +function getShortId(uuid) { + if (!uuid || uuid.indexOf('-') < 0) { + return uuid + } + // 找到第一个 '-' 的位置 + const index = uuid.indexOf('-') + // 截取从开始到第一个 '-' 之前的部分 + return uuid.substring(0, index) +} + +module.exports = { extractLangPrefix, extractLangId, getShortId } diff --git a/package.json b/package.json index 5e7761c7e06..9d6259b0cdb 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "start": "next start", "post-build": "next-sitemap --config next-sitemap.config.js", "export": "next build && next-sitemap --config next-sitemap.config.js && next export", - "bundle-report": "cross-env ANALYZE=true yarn build" + "bundle-report": "cross-env ANALYZE=true next build", + "build-all-in-dev": "cross-env VERCEL_ENV=production next build" }, "dependencies": { "@headlessui/react": "^1.7.15", diff --git a/pages/[prefix]/[slug]/[...suffix].js b/pages/[prefix]/[slug]/[...suffix].js index 2050e81d8d0..475372666ca 100644 --- a/pages/[prefix]/[slug]/[...suffix].js +++ b/pages/[prefix]/[slug]/[...suffix].js @@ -92,7 +92,7 @@ export async function getStaticProps({ } // 文章内容加载 - if (!props?.posts?.blockMap) { + if (!props?.post?.blockMap) { props.post.blockMap = await getPostBlocks(props.post.id, from) } // 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA) diff --git a/pages/[prefix]/[slug]/index.js b/pages/[prefix]/[slug]/index.js index 2c844ebabe5..2b414ce4e49 100644 --- a/pages/[prefix]/[slug]/index.js +++ b/pages/[prefix]/[slug]/index.js @@ -81,7 +81,7 @@ export async function getStaticProps({ params: { prefix, slug }, locale }) { } // 文章内容加载 - if (!props?.posts?.blockMap) { + if (!props?.post?.blockMap) { props.post.blockMap = await getPostBlocks(props.post.id, from) } // 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA) diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js index 469ca617cdd..973ce32153c 100644 --- a/pages/[prefix]/index.js +++ b/pages/[prefix]/index.js @@ -145,7 +145,7 @@ export async function getStaticProps({ params: { prefix }, locale }) { } // 文章内容加载 - if (!props?.posts?.blockMap) { + if (!props?.post?.blockMap) { props.post.blockMap = await getPostBlocks(props.post.id, from) } diff --git a/themes/gitbook/index.js b/themes/gitbook/index.js index d70e152e003..c81110b0ce7 100644 --- a/themes/gitbook/index.js +++ b/themes/gitbook/index.js @@ -9,6 +9,7 @@ import ShareBar from '@/components/ShareBar' import { siteConfig } from '@/lib/config' import { useGlobal } from '@/lib/global' import { isBrowser } from '@/lib/utils' +import { getShortId } from '@/lib/utils/pageId' import { Transition } from '@headlessui/react' import dynamic from 'next/dynamic' import Link from 'next/link' @@ -54,14 +55,14 @@ function getNavPagesWithLatest(allNavPages, latestPosts, post) { localStorage.getItem('post_read_time') || '{}' ) if (post) { - postReadTime[post.id] = new Date().getTime() + postReadTime[getShortId(post.id)] = new Date().getTime() } // 更新 localStorage.setItem('post_read_time', JSON.stringify(postReadTime)) return allNavPages?.map(item => { const res = { - id: item.id, + short_id: item.short_id, title: item.title || '', pageCoverThumbnail: item.pageCoverThumbnail || '', category: item.category || null, @@ -74,9 +75,9 @@ function getNavPagesWithLatest(allNavPages, latestPosts, post) { } // 属于最新文章通常6篇 && (无阅读记录 || 最近更新时间大于上次阅读时间) if ( - latestPosts.some(post => post.id === item.id) && - (!postReadTime[item.id] || - postReadTime[item.id] < new Date(item.lastEditedDate).getTime()) + latestPosts.some(post => item?.short_id === post?.short_id) && + (!postReadTime[item.short_id] || + postReadTime[item.short_id] < new Date(item.lastEditedDate).getTime()) ) { return { ...res, isLatest: true } } else { @@ -412,11 +413,9 @@ const LayoutArchive = props => { */ const Layout404 = props => { return ( - <> -