Skip to content

Commit 6f1f994

Browse files
committed
2 parents ab78ffa + 84f36a7 commit 6f1f994

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1018
-598
lines changed

.env.local

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
2-
NEXT_PUBLIC_VERSION=4.5.2
2+
NEXT_PUBLIC_VERSION=4.5.3
33

44

55
# 可在此添加环境变量,去掉最左边的(# )注释即可

components/ExternalPlugins.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const ExternalPlugin = props => {
101101
// 异步渲染谷歌广告
102102
if (ADSENSE_GOOGLE_ID) {
103103
setTimeout(() => {
104-
initGoogleAdsense()
104+
initGoogleAdsense(ADSENSE_GOOGLE_ID)
105105
}, 1000)
106106
}
107107

components/GoogleAdsense.js

+13-11
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ function getNodesWithAdsByGoogleClass(node) {
6161
* 初始化谷歌广告
6262
* @returns
6363
*/
64-
export const initGoogleAdsense = async () => {
64+
export const initGoogleAdsense = async ADSENSE_GOOGLE_ID => {
6565
console.log('Load Adsense')
6666
loadExternalResource(
67-
`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${siteConfig('ADSENSE_GOOGLE_ID')}`,
67+
`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ADSENSE_GOOGLE_ID}`,
6868
'js'
6969
).then(url => {
7070
setTimeout(() => {
@@ -109,7 +109,9 @@ export const initGoogleAdsense = async () => {
109109
* 添加 可以在本地调试
110110
*/
111111
const AdSlot = ({ type = 'show' }) => {
112-
if (!siteConfig('ADSENSE_GOOGLE_ID')) {
112+
const ADSENSE_GOOGLE_ID = siteConfig('ADSENSE_GOOGLE_ID')
113+
const ADSENSE_GOOGLE_TEST = siteConfig('ADSENSE_GOOGLE_TEST')
114+
if (!ADSENSE_GOOGLE_ID) {
113115
return null
114116
}
115117
// 文章内嵌广告
@@ -120,8 +122,8 @@ const AdSlot = ({ type = 'show' }) => {
120122
style={{ display: 'block', textAlign: 'center' }}
121123
data-ad-layout='in-article'
122124
data-ad-format='fluid'
123-
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
124-
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
125+
data-adtest={ADSENSE_GOOGLE_TEST ? 'on' : 'off'}
126+
data-ad-client={ADSENSE_GOOGLE_ID}
125127
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_IN_ARTICLE')}></ins>
126128
)
127129
}
@@ -134,8 +136,8 @@ const AdSlot = ({ type = 'show' }) => {
134136
data-ad-format='fluid'
135137
data-ad-layout-key='-5j+cz+30-f7+bf'
136138
style={{ display: 'block' }}
137-
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
138-
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
139+
data-adtest={ADSENSE_GOOGLE_TEST ? 'on' : 'off'}
140+
data-ad-client={ADSENSE_GOOGLE_ID}
139141
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_FLOW')}></ins>
140142
)
141143
}
@@ -147,8 +149,8 @@ const AdSlot = ({ type = 'show' }) => {
147149
className='adsbygoogle'
148150
style={{ display: 'block', textAlign: 'center' }}
149151
data-ad-format='autorelaxed'
150-
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
151-
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
152+
data-adtest={ADSENSE_GOOGLE_TEST ? 'on' : 'off'}
153+
data-ad-client={ADSENSE_GOOGLE_ID}
152154
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_NATIVE')}></ins>
153155
)
154156
}
@@ -158,8 +160,8 @@ const AdSlot = ({ type = 'show' }) => {
158160
<ins
159161
className='adsbygoogle'
160162
style={{ display: 'block' }}
161-
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
162-
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
163+
data-ad-client={ADSENSE_GOOGLE_ID}
164+
data-adtest={ADSENSE_GOOGLE_TEST ? 'on' : 'off'}
163165
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_AUTO')}
164166
data-ad-format='auto'
165167
data-full-width-responsive='true'></ins>

lib/config.js

+39-5
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,39 @@ import { deepClone } from './utils'
1414
* @param {*} extendConfig ; 参考配置对象{key:val},如果notion中找不到优先尝试在这里面查找
1515
* @returns
1616
*/
17-
export const siteConfig = (key, defaultVal = null, extendConfig = null) => {
18-
let global = null
17+
export const siteConfig = (key, defaultVal = null, extendConfig = {}) => {
18+
if (!key) {
19+
return null
20+
}
21+
22+
// 特殊配置处理;某些配置只在服务端生效;而Global的NOTION_CONFIG仅限前端组件使用,因此需要从extendConfig中读取
23+
switch (key) {
24+
case 'NEXT_REVALIDATE_SECOND':
25+
case 'POST_RECOMMEND_COUNT':
26+
case 'IMAGE_COMPRESS_WIDTH':
27+
case 'PSEUDO_STATIC':
28+
case 'POSTS_SORT_BY':
29+
case 'POSTS_PER_PAGE':
30+
case 'POST_PREVIEW_LINES':
31+
case 'POST_URL_PREFIX':
32+
case 'POST_LIST_STYLE':
33+
case 'POST_LIST_PREVIEW':
34+
case 'POST_URL_PREFIX_MAPPING_CATEGORY':
35+
return convertVal(extendConfig[key] || defaultVal || BLOG[key])
36+
default:
37+
}
38+
39+
let global = {}
1940
try {
20-
const isClient = typeof window !== 'undefined'
41+
// const isClient = typeof window !== 'undefined'
2142
// eslint-disable-next-line react-hooks/rules-of-hooks
22-
global = isClient ? useGlobal() : {}
43+
global = useGlobal()
2344
// eslint-disable-next-line react-hooks/rules-of-hooks
2445
// global = useGlobal()
25-
} catch (error) {}
46+
} catch (error) {
47+
// 本地调试用
48+
// console.warn('SiteConfig警告', key, error)
49+
}
2650

2751
// 首先 配置最优先读取NOTION中的表格配置
2852
let val = null
@@ -66,6 +90,16 @@ export const siteConfig = (key, defaultVal = null, extendConfig = null) => {
6690
}
6791

6892
// 从Notion_CONFIG读取的配置通常都是字符串,适当转义
93+
return convertVal(val)
94+
}
95+
96+
/**
97+
* 配置默认都是string类型;
98+
* 识别配置的值是否数字、布尔、[]数组,若是则转成对应类型
99+
* @param {*} val
100+
* @returns
101+
*/
102+
export const convertVal = val => {
69103
if (typeof val === 'string') {
70104
// 解析布尔
71105
if (val === 'true' || val === 'false') {

lib/db/getSiteData.js

+22-25
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getConfigMapFromConfigPage } from '@/lib/notion/getNotionConfig'
77
import getPageProperties, {
88
adjustPageProperties
99
} from '@/lib/notion/getPageProperties'
10-
import { getPostBlocks, getSingleBlock } from '@/lib/notion/getPostBlocks'
10+
import { fetchInBatches, getPostBlocks } from '@/lib/notion/getPostBlocks'
1111
import { compressImage, mapImgUrl } from '@/lib/notion/mapImage'
1212
import { deepClone } from '@/lib/utils'
1313
import { idToUuid } from 'notion-utils'
@@ -236,12 +236,13 @@ function getCategoryOptions(schema) {
236236
* @param from
237237
* @returns {Promise<{title,description,pageCover,icon}>}
238238
*/
239-
function getSiteInfo({ collection, block, NOTION_CONFIG, pageId }) {
240-
const defaultTitle = siteConfig('TITLE', '', NOTION_CONFIG)
241-
const defaultDescription = siteConfig('DESCRIPTION', '', NOTION_CONFIG)
242-
const defaultPageCover = siteConfig('HOME_BANNER_IMAGE', '', NOTION_CONFIG)
243-
const defaultIcon = siteConfig('AVATAR', '', NOTION_CONFIG)
244-
const defaultLink = siteConfig('LINK', '', NOTION_CONFIG)
239+
function getSiteInfo({ collection, block, NOTION_CONFIG }) {
240+
const defaultTitle = NOTION_CONFIG?.TITLE || BLOG.TITLE
241+
const defaultDescription = NOTION_CONFIG?.DESCRIPTION || BLOG.DESCRIPTION
242+
const defaultPageCover =
243+
NOTION_CONFIG?.HOME_BANNER_IMAGE || BLOG.HOME_BANNER_IMAGE
244+
const defaultIcon = NOTION_CONFIG?.AVATAR || BLOG.AVATAR
245+
const defaultLink = NOTION_CONFIG?.LINK || BLOG.LINK
245246
if (!collection && !block) {
246247
return {
247248
title: defaultTitle,
@@ -370,13 +371,14 @@ const EmptyData = pageId => {
370371
* @returns {Promise<JSX.Element|null|*>}
371372
*/
372373
async function getDataBaseInfoByNotionAPI({ pageId, from }) {
374+
console.log('[Fetching Data]', pageId, from)
373375
const pageRecordMap = await getPostBlocks(pageId, from)
374376
if (!pageRecordMap) {
375377
console.error('can`t get Notion Data ; Which id is: ', pageId)
376378
return {}
377379
}
378380
pageId = idToUuid(pageId)
379-
const block = pageRecordMap.block || {}
381+
let block = pageRecordMap.block || {}
380382
const rawMetadata = block[pageId]?.value
381383
// Check Type Page-Database和Inline-Database
382384
if (
@@ -401,6 +403,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) {
401403
collectionView,
402404
viewIds
403405
)
406+
404407
if (pageIds?.length === 0) {
405408
console.error(
406409
'获取到的文章列表为空,请检查notion模板',
@@ -414,29 +417,22 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) {
414417
// console.log('有效Page数量', pageIds?.length)
415418
}
416419

417-
// 获取每篇文章基础数据
420+
// 抓取主数据库最多抓取1000个blocks,溢出的数block这里统一抓取一遍
421+
const blockIdsNeedFetch = []
418422
for (let i = 0; i < pageIds.length; i++) {
419423
const id = pageIds[i]
420424
const value = block[id]?.value
421425
if (!value) {
422-
// 如果找不到文章对应的block,说明发生了溢出,使用pageID再去请求
423-
const pageBlock = await getSingleBlock(id, from)
424-
if (pageBlock.block[id].value) {
425-
const properties =
426-
(await getPageProperties(
427-
id,
428-
pageBlock.block[id].value,
429-
schema,
430-
null,
431-
getTagOptions(schema)
432-
)) || null
433-
if (properties) {
434-
collectionData.push(properties)
435-
}
436-
}
437-
continue
426+
blockIdsNeedFetch.push(id)
438427
}
428+
}
429+
const fetchedBlocks = await fetchInBatches(blockIdsNeedFetch)
430+
block = Object.assign({}, block, fetchedBlocks)
439431

432+
// 获取每篇文章基础数据
433+
for (let i = 0; i < pageIds.length; i++) {
434+
const id = pageIds[i]
435+
const value = block[id]?.value || fetchedBlocks[id]?.value
440436
const properties =
441437
(await getPageProperties(
442438
id,
@@ -445,6 +441,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) {
445441
null,
446442
getTagOptions(schema)
447443
)) || null
444+
448445
if (properties) {
449446
collectionData.push(properties)
450447
}

lib/notion/getPageProperties.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function adjustPageProperties(properties, NOTION_CONFIG) {
186186
}
187187

188188
// 开启伪静态路径
189-
if (siteConfig('PSEUDO_STATIC', false, NOTION_CONFIG)) {
189+
if (JSON.parse(NOTION_CONFIG?.PSEUDO_STATIC || BLOG.PSEUDO_STATIC)) {
190190
if (
191191
!properties?.href?.endsWith('.html') &&
192192
!properties?.href?.startsWith('http')

lib/notion/getPostBlocks.js

+54-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import BLOG from '@/blog.config'
2-
import { NotionAPI } from 'notion-client'
32
import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager'
3+
import { NotionAPI } from 'notion-client'
44
import { deepClone, delay } from '../utils'
55

66
/**
@@ -41,7 +41,7 @@ export async function getSingleBlock(id, from) {
4141
return pageBlock
4242
}
4343

44-
pageBlock = await getPageWithRetry(id, from)
44+
pageBlock = await getPageWithRetry(id, 'single_' + from)
4545

4646
if (pageBlock) {
4747
await setDataToCache(cacheKey, pageBlock)
@@ -56,10 +56,18 @@ export async function getSingleBlock(id, from) {
5656
*/
5757
export async function getPageWithRetry(id, from, retryAttempts = 3) {
5858
if (retryAttempts && retryAttempts > 0) {
59-
console.log('[API-->>请求]', `from:${from}`, `id:${id}`, retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : '')
59+
console.log(
60+
'[API-->>请求]',
61+
`from:${from}`,
62+
`id:${id}`,
63+
retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : ''
64+
)
6065
try {
6166
const authToken = BLOG.NOTION_ACCESS_TOKEN || null
62-
const api = new NotionAPI({ authToken, userTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone })
67+
const api = new NotionAPI({
68+
authToken,
69+
userTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
70+
})
6371
const start = new Date().getTime()
6472
const pageData = await api.getPage(id)
6573
const end = new Date().getTime()
@@ -125,9 +133,13 @@ function filterPostBlocks(id, blockMap, slice) {
125133
}
126134

127135
// 如果是文件,或嵌入式PDF,需要重新加密签名
128-
if ((b?.value?.type === 'file' || b?.value?.type === 'pdf' || b?.value?.type === 'video' || b?.value?.type === 'audio') &&
129-
b?.value?.properties?.source?.[0][0] &&
130-
b?.value?.properties?.source?.[0][0].indexOf('amazonaws.com') > 0
136+
if (
137+
(b?.value?.type === 'file' ||
138+
b?.value?.type === 'pdf' ||
139+
b?.value?.type === 'video' ||
140+
b?.value?.type === 'audio') &&
141+
b?.value?.properties?.source?.[0][0] &&
142+
b?.value?.properties?.source?.[0][0].indexOf('amazonaws.com') > 0
131143
) {
132144
const oldUrl = b?.value?.properties?.source?.[0][0]
133145
const newUrl = `https://notion.so/signed/${encodeURIComponent(oldUrl)}?table=block&id=${b?.value?.id}`
@@ -141,3 +153,38 @@ function filterPostBlocks(id, blockMap, slice) {
141153
}
142154
return clonePageBlock
143155
}
156+
157+
/**
158+
* 根据[]ids,批量抓取blocks
159+
* 在获取数据库文章列表时,超过一定数量的block会被丢弃,因此根据pageId批量抓取block
160+
* @param {*} ids
161+
* @param {*} batchSize
162+
* @returns
163+
*/
164+
export const fetchInBatches = async (ids, batchSize = 100) => {
165+
const authToken = BLOG.NOTION_ACCESS_TOKEN || null
166+
const api = new NotionAPI({
167+
authToken,
168+
userTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
169+
})
170+
171+
let fetchedBlocks = {}
172+
for (let i = 0; i < ids.length; i += batchSize) {
173+
const batch = ids.slice(i, i + batchSize)
174+
console.log('[API-->>请求] Fetching missing blocks', ids.length)
175+
const start = new Date().getTime()
176+
const pageChunk = await api.getBlocks(batch)
177+
const end = new Date().getTime()
178+
console.log(
179+
`[API<<--响应] 耗时:${end - start}ms Fetching missing blocks count:${ids.length} `
180+
)
181+
182+
console.log('[API<<--响应]')
183+
fetchedBlocks = Object.assign(
184+
{},
185+
fetchedBlocks,
186+
pageChunk?.recordMap?.block
187+
)
188+
}
189+
return fetchedBlocks
190+
}

lib/robots.txt.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import fs from 'fs'
2-
import { siteConfig } from './config'
32

4-
export async function generateRobotsTxt(NOTION_CONFIG) {
5-
const LINK = siteConfig('LINK', '', NOTION_CONFIG)
3+
export async function generateRobotsTxt(props) {
4+
const { siteInfo } = props
5+
const LINK = siteInfo?.link
66
const content = `
77
# *
88
User-agent: *

0 commit comments

Comments
 (0)