mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-01 07:26:47 +00:00
SEO 优化首屏加载体积
This commit is contained in:
@@ -405,6 +405,7 @@ const BLOG = {
|
|||||||
DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮
|
DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮
|
||||||
ENABLE_CACHE: process.env.ENABLE_CACHE || process.env.npm_lifecycle_event === 'build', // 缓存在开发调试和打包过程中选择性开启,正式部署开启此功能意义不大。
|
ENABLE_CACHE: process.env.ENABLE_CACHE || process.env.npm_lifecycle_event === 'build', // 缓存在开发调试和打包过程中选择性开启,正式部署开启此功能意义不大。
|
||||||
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
|
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
|
||||||
|
BUNDLE_ANALYZER: process.env.ANALYZE === 'true' || true, // 编译时是否展示内容
|
||||||
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
|
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
components/AOSAnimation.js
Normal file
12
components/AOSAnimation.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import AOS from 'aos'
|
||||||
|
import { isBrowser } from 'react-notion-x'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载滚动动画
|
||||||
|
* https://michalsnik.github.io/aos/
|
||||||
|
*/
|
||||||
|
export default function AOSAnimation() {
|
||||||
|
if (isBrowser) {
|
||||||
|
AOS.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,12 @@ const katexSettings = {
|
|||||||
strict: false
|
strict: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数学公式
|
||||||
|
* @param {} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const Equation = ({ block, math, inline = false, className, ...rest }) => {
|
export const Equation = ({ block, math, inline = false, className, ...rest }) => {
|
||||||
// const { recordMap } = useNotionContext()
|
|
||||||
math = math || getBlockTitle(block, null)
|
math = math || getBlockTitle(block, null)
|
||||||
if (!math) return null
|
if (!math) return null
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ const VConsole = dynamic(() => import('@/components/VConsole'), { ssr: false })
|
|||||||
const CustomContextMenu = dynamic(() => import('@/components/CustomContextMenu'), { ssr: false })
|
const CustomContextMenu = dynamic(() => import('@/components/CustomContextMenu'), { ssr: false })
|
||||||
const DisableCopy = dynamic(() => import('@/components/DisableCopy'), { ssr: false })
|
const DisableCopy = dynamic(() => import('@/components/DisableCopy'), { ssr: false })
|
||||||
const AdBlockDetect = dynamic(() => import('@/components/AdBlockDetect'), { ssr: false })
|
const AdBlockDetect = dynamic(() => import('@/components/AdBlockDetect'), { ssr: false })
|
||||||
|
const LoadingProgress = dynamic(() => import('@/components/LoadingProgress'), { ssr: false })
|
||||||
|
const AosAnimation = dynamic(() => import('@/components/AosAnimation'), { ssr: false })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 各种插件脚本
|
* 各种插件脚本
|
||||||
@@ -91,6 +93,8 @@ const ExternalPlugin = (props) => {
|
|||||||
{WEB_WHIZ_ENABLED && <WebWhiz />}
|
{WEB_WHIZ_ENABLED && <WebWhiz />}
|
||||||
{AD_WWADS_BLOCK_DETECT && <AdBlockDetect />}
|
{AD_WWADS_BLOCK_DETECT && <AdBlockDetect />}
|
||||||
<VConsole />
|
<VConsole />
|
||||||
|
<LoadingProgress />
|
||||||
|
<AosAnimation />
|
||||||
|
|
||||||
{CHATBASE_ID && (<>
|
{CHATBASE_ID && (<>
|
||||||
<script id={CHATBASE_ID} src="https://www.chatbase.co/embed.min.js" defer />
|
<script id={CHATBASE_ID} src="https://www.chatbase.co/embed.min.js" defer />
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import KaTeX from 'katex'
|
import KaTeX from 'katex'
|
||||||
import React from 'react'
|
import { memo, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数学公式
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
const TeX = ({
|
const TeX = ({
|
||||||
children,
|
children,
|
||||||
math,
|
math,
|
||||||
@@ -13,9 +18,9 @@ const TeX = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const Component = asComponent || (block ? 'div' : 'span')
|
const Component = asComponent || (block ? 'div' : 'span')
|
||||||
const content = (children ?? math)
|
const content = (children ?? math)
|
||||||
const [state, setState] = React.useState({ innerHtml: '' })
|
const [state, setState] = useState({ innerHtml: '' })
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const innerHtml = KaTeX.renderToString(content, {
|
const innerHtml = KaTeX.renderToString(content, {
|
||||||
displayMode: true,
|
displayMode: true,
|
||||||
@@ -50,4 +55,4 @@ const TeX = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(TeX)
|
export default memo(TeX)
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import { useGlobal } from '@/lib/global'
|
|||||||
import { loadExternalResource } from '@/lib/utils'
|
import { loadExternalResource } from '@/lib/utils'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网页动画
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export default function Live2D() {
|
export default function Live2D() {
|
||||||
const { theme, switchTheme } = useGlobal()
|
const { theme, switchTheme } = useGlobal()
|
||||||
const showPet = JSON.parse(siteConfig('WIDGET_PET'))
|
const showPet = JSON.parse(siteConfig('WIDGET_PET'))
|
||||||
|
|||||||
29
components/LoadingProgress.js
Normal file
29
components/LoadingProgress.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import NProgress from 'nprogress'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出现页面加载进度条
|
||||||
|
*/
|
||||||
|
export default function LoadingProgress() {
|
||||||
|
const router = useRouter()
|
||||||
|
// 加载进度条
|
||||||
|
useEffect(() => {
|
||||||
|
const handleStart = (url) => {
|
||||||
|
NProgress.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleStop = () => {
|
||||||
|
NProgress.done()
|
||||||
|
}
|
||||||
|
|
||||||
|
router.events.on('routeChangeStart', handleStart)
|
||||||
|
router.events.on('routeChangeError', handleStop)
|
||||||
|
router.events.on('routeChangeComplete', handleStop)
|
||||||
|
return () => {
|
||||||
|
router.events.off('routeChangeStart', handleStart)
|
||||||
|
router.events.off('routeChangeComplete', handleStop)
|
||||||
|
router.events.off('routeChangeError', handleStop)
|
||||||
|
}
|
||||||
|
}, [router])
|
||||||
|
}
|
||||||
@@ -1,20 +1,25 @@
|
|||||||
import { NotionRenderer } from 'react-notion-x'
|
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
import mediumZoom from '@fisch0920/medium-zoom'
|
import mediumZoom from '@fisch0920/medium-zoom'
|
||||||
import React, { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
// import { Code } from 'react-notion-x/build/third-party/code'
|
|
||||||
import TweetEmbed from 'react-tweet-embed'
|
|
||||||
import 'katex/dist/katex.min.css'
|
import 'katex/dist/katex.min.css'
|
||||||
import { mapImgUrl } from '@/lib/notion/mapImage'
|
import { mapImgUrl } from '@/lib/notion/mapImage'
|
||||||
import { isBrowser } from '@/lib/utils'
|
import { isBrowser } from '@/lib/utils'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
|
||||||
|
// Notion渲染
|
||||||
|
const NotionRenderer = dynamic(() => import('react-notion-x').then(async (m) => {
|
||||||
|
return m.NotionRenderer
|
||||||
|
}), {
|
||||||
|
ssr: false
|
||||||
|
})
|
||||||
|
|
||||||
const Code = dynamic(() =>
|
const Code = dynamic(() =>
|
||||||
import('react-notion-x/build/third-party/code').then(async (m) => {
|
import('react-notion-x/build/third-party/code').then(async (m) => {
|
||||||
return m.Code
|
return m.Code
|
||||||
}), { ssr: false }
|
}), { ssr: false }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 公式
|
||||||
const Equation = dynamic(() =>
|
const Equation = dynamic(() =>
|
||||||
import('@/components/Equation').then(async (m) => {
|
import('@/components/Equation').then(async (m) => {
|
||||||
// 化学方程式
|
// 化学方程式
|
||||||
@@ -36,6 +41,13 @@ const PrismMac = dynamic(() => import('@/components/PrismMac'), {
|
|||||||
ssr: false
|
ssr: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tweet嵌入
|
||||||
|
*/
|
||||||
|
const TweetEmbed = dynamic(() => import('react-tweet-embed'), {
|
||||||
|
ssr: false
|
||||||
|
})
|
||||||
|
|
||||||
const Collection = dynamic(() =>
|
const Collection = dynamic(() =>
|
||||||
import('react-notion-x/build/third-party/collection').then((m) => m.Collection), { ssr: true }
|
import('react-notion-x/build/third-party/collection').then((m) => m.Collection), { ssr: true }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,29 +1,21 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useRouter } from 'next/router'
|
import dynamic from 'next/dynamic'
|
||||||
import React from 'react'
|
|
||||||
import ShareButtons from './ShareButtons'
|
|
||||||
|
|
||||||
|
const ShareButtons = dynamic(() => import('@/components/ShareButtons'), { ssr: false })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分享栏
|
||||||
|
* @param {} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
const ShareBar = ({ post }) => {
|
const ShareBar = ({ post }) => {
|
||||||
const router = useRouter()
|
|
||||||
const title = siteConfig('TITLE')
|
|
||||||
|
|
||||||
if (!JSON.parse(siteConfig('POST_SHARE_BAR_ENABLE')) || !post || post?.type !== 'Post') {
|
if (!JSON.parse(siteConfig('POST_SHARE_BAR_ENABLE')) || !post || post?.type !== 'Post') {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
const shareUrl = siteConfig('LINK') + router.asPath
|
|
||||||
|
|
||||||
return <div className='m-1 overflow-x-auto'>
|
return <div className='m-1 overflow-x-auto'>
|
||||||
<div className='flex w-full md:justify-end'>
|
<div className='flex w-full md:justify-end'>
|
||||||
<ShareButtons shareUrl={shareUrl} title={post.title} image={post.pageCover} body={
|
<ShareButtons post={post} />
|
||||||
post?.title +
|
|
||||||
' | ' +
|
|
||||||
title +
|
|
||||||
' ' +
|
|
||||||
shareUrl +
|
|
||||||
' ' +
|
|
||||||
post?.summary
|
|
||||||
} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { siteConfig } from '@/lib/config'
|
|||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -56,7 +57,13 @@ const QrCode = dynamic(() => import('@/components/QrCode'), { ssr: false })
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const ShareButtons = ({ shareUrl, title, body, image }) => {
|
const ShareButtons = ({ post }) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const shareUrl = siteConfig('LINK') + router.asPath
|
||||||
|
const title = post.title || siteConfig('TITLE')
|
||||||
|
const image = post.pageCover
|
||||||
|
const body = post?.title + ' | ' + title + ' ' + shareUrl + ' ' + post?.summary
|
||||||
|
|
||||||
const services = siteConfig('POSTS_SHARE_SERVICES').split(',')
|
const services = siteConfig('POSTS_SHARE_SERVICES').split(',')
|
||||||
const titleWithSiteInfo = title + ' | ' + siteConfig('TITLE')
|
const titleWithSiteInfo = title + ' | ' + siteConfig('TITLE')
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ import { generateLocaleDict, initLocale } from './lang'
|
|||||||
import { createContext, useContext, useEffect, useState } from 'react'
|
import { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { THEMES, initDarkMode, saveDarkModeToCookies } from '@/themes/theme'
|
import { THEMES, initDarkMode, saveDarkModeToCookies } from '@/themes/theme'
|
||||||
|
import { APPEARANCE, LANG, THEME } from 'blog.config'
|
||||||
import BLOG from '@/blog.config'
|
|
||||||
import NProgress from 'nprogress'
|
|
||||||
|
|
||||||
const GlobalContext = createContext()
|
const GlobalContext = createContext()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,10 +14,10 @@ const GlobalContext = createContext()
|
|||||||
export function GlobalContextProvider(props) {
|
export function GlobalContextProvider(props) {
|
||||||
const { children, siteInfo, categoryOptions, tagOptions, NOTION_CONFIG } = props
|
const { children, siteInfo, categoryOptions, tagOptions, NOTION_CONFIG } = props
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [lang, updateLang] = useState(NOTION_CONFIG?.LANG || BLOG.LANG) // 默认语言
|
const [lang, updateLang] = useState(NOTION_CONFIG?.LANG || LANG) // 默认语言
|
||||||
const [locale, updateLocale] = useState(generateLocaleDict(NOTION_CONFIG?.LANG || BLOG.LANG)) // 默认语言
|
const [locale, updateLocale] = useState(generateLocaleDict(NOTION_CONFIG?.LANG || LANG)) // 默认语言
|
||||||
const [theme, setTheme] = useState(NOTION_CONFIG?.THEME || BLOG.THEME) // 默认博客主题
|
const [theme, setTheme] = useState(NOTION_CONFIG?.THEME || THEME) // 默认博客主题
|
||||||
const [isDarkMode, updateDarkMode] = useState(NOTION_CONFIG?.APPEARANCE || BLOG.APPEARANCE === 'dark') // 默认深色模式
|
const [isDarkMode, updateDarkMode] = useState(NOTION_CONFIG?.APPEARANCE || APPEARANCE === 'dark') // 默认深色模式
|
||||||
const [onLoading, setOnLoading] = useState(false) // 抓取文章数据
|
const [onLoading, setOnLoading] = useState(false) // 抓取文章数据
|
||||||
|
|
||||||
// 切换主题
|
// 切换主题
|
||||||
@@ -62,7 +59,6 @@ export function GlobalContextProvider(props) {
|
|||||||
// 加载进度条
|
// 加载进度条
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleStart = (url) => {
|
const handleStart = (url) => {
|
||||||
NProgress.start()
|
|
||||||
const { theme } = router.query
|
const { theme } = router.query
|
||||||
if (theme && !url.includes(`theme=${theme}`)) {
|
if (theme && !url.includes(`theme=${theme}`)) {
|
||||||
const newUrl = `${url}${url.includes('?') ? '&' : '?'}theme=${theme}`
|
const newUrl = `${url}${url.includes('?') ? '&' : '?'}theme=${theme}`
|
||||||
@@ -71,7 +67,6 @@ export function GlobalContextProvider(props) {
|
|||||||
setOnLoading(true)
|
setOnLoading(true)
|
||||||
}
|
}
|
||||||
const handleStop = () => {
|
const handleStop = () => {
|
||||||
NProgress.done()
|
|
||||||
setOnLoading(false)
|
setOnLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
|
||||||
enabled: process.env.ANALYZE === 'true'
|
|
||||||
})
|
|
||||||
|
|
||||||
const { THEME } = require('./blog.config')
|
const { THEME } = require('./blog.config')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const BLOG = require('./blog.config')
|
||||||
|
|
||||||
|
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||||
|
enabled: BLOG.BUNDLE_ANALYZER
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扫描指定目录下的文件夹名,用于获取当前有几个主题
|
* 扫描指定目录下的文件夹名,用于获取当前有几个主题
|
||||||
|
|||||||
@@ -6,41 +6,38 @@ import '@/styles/utility-patterns.css'
|
|||||||
// core styles shared by all of react-notion-x (required)
|
// core styles shared by all of react-notion-x (required)
|
||||||
import 'react-notion-x/src/styles.css'
|
import 'react-notion-x/src/styles.css'
|
||||||
import '@/styles/notion.css' // 重写部分样式
|
import '@/styles/notion.css' // 重写部分样式
|
||||||
|
import 'aos/dist/aos.css' // You can also use <link> for styles
|
||||||
|
|
||||||
import { GlobalContextProvider } from '@/lib/global'
|
import { GlobalContextProvider } from '@/lib/global'
|
||||||
|
|
||||||
import AOS from 'aos'
|
|
||||||
import 'aos/dist/aos.css' // You can also use <link> for styles
|
|
||||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||||
import BLOG from '@/blog.config'
|
|
||||||
// 各种扩展插件 动画等
|
// 各种扩展插件 这个要阻塞引入
|
||||||
import ExternalPlugins from '@/components/ExternalPlugins'
|
import ExternalPlugins from '@/components/ExternalPlugins'
|
||||||
// const ExternalPlugins = dynamic(() => import('@/components/ExternalPlugins'))
|
import { CUSTOM_EXTERNAL_CSS, CUSTOM_EXTERNAL_JS, IMG_SHADOW } from '@/blog.config'
|
||||||
|
|
||||||
const MyApp = ({ Component, pageProps }) => {
|
const MyApp = ({ Component, pageProps }) => {
|
||||||
// 自定义样式css和js引入
|
// 自定义样式css和js引入
|
||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
// 初始化AOS动画
|
// 初始化AOS动画
|
||||||
AOS.init()
|
|
||||||
// 静态导入本地自定义样式
|
// 静态导入本地自定义样式
|
||||||
loadExternalResource('/css/custom.css', 'css')
|
loadExternalResource('/css/custom.css', 'css')
|
||||||
loadExternalResource('/js/custom.js', 'js')
|
loadExternalResource('/js/custom.js', 'js')
|
||||||
|
|
||||||
// 自动添加图片阴影
|
// 自动添加图片阴影
|
||||||
if (BLOG.IMG_SHADOW) {
|
if (IMG_SHADOW) {
|
||||||
loadExternalResource('/css/img-shadow.css', 'css')
|
loadExternalResource('/css/img-shadow.css', 'css')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入外部自定义脚本
|
// 导入外部自定义脚本
|
||||||
if (BLOG.CUSTOM_EXTERNAL_JS && BLOG.CUSTOM_EXTERNAL_JS.length > 0) {
|
if (CUSTOM_EXTERNAL_JS && CUSTOM_EXTERNAL_JS.length > 0) {
|
||||||
for (const url of BLOG.CUSTOM_EXTERNAL_JS) {
|
for (const url of CUSTOM_EXTERNAL_JS) {
|
||||||
loadExternalResource(url, 'js')
|
loadExternalResource(url, 'js')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入外部自定义样式
|
// 导入外部自定义样式
|
||||||
if (BLOG.CUSTOM_EXTERNAL_CSS && BLOG.CUSTOM_EXTERNAL_CSS.length > 0) {
|
if (CUSTOM_EXTERNAL_CSS && CUSTOM_EXTERNAL_CSS.length > 0) {
|
||||||
for (const url of BLOG.CUSTOM_EXTERNAL_CSS) {
|
for (const url of CUSTOM_EXTERNAL_CSS) {
|
||||||
loadExternalResource(url, 'css')
|
loadExternalResource(url, 'css')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import CONFIG from '../config'
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { formatDateFmt } from '@/lib/formatDate'
|
import { formatDateFmt } from '@/lib/formatDate'
|
||||||
|
|
||||||
export const ArticleInfo = (props) => {
|
/**
|
||||||
|
* 文章描述
|
||||||
|
* @param {*} props
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function ArticleInfo (props) {
|
||||||
const { post } = props
|
const { post } = props
|
||||||
|
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useEffect, useRef } from 'react'
|
|||||||
* @param validPassword(bool) 回调函数,校验正确回调入参为true
|
* @param validPassword(bool) 回调函数,校验正确回调入参为true
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const ArticleLock = props => {
|
export default function ArticleLock (props) {
|
||||||
const { validPassword } = props
|
const { validPassword } = props
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ import { AdSlot } from '@/components/GoogleAdsense'
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
|
|
||||||
export const BlogListPage = props => {
|
/**
|
||||||
|
* 博客列表
|
||||||
|
* @param {*} props
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function BlogListPage(props) {
|
||||||
const { page = 1, posts, postCount } = props
|
const { page = 1, posts, postCount } = props
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const totalPage = Math.ceil(postCount / parseInt(siteConfig('POSTS_PER_PAGE')))
|
const totalPage = Math.ceil(postCount / parseInt(siteConfig('POSTS_PER_PAGE')))
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import throttle from 'lodash.throttle'
|
|||||||
import { BlogItem } from './BlogItem'
|
import { BlogItem } from './BlogItem'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
|
||||||
export const BlogListScroll = props => {
|
/**
|
||||||
|
* 滚动博客列表
|
||||||
|
* @param {*} props
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function BlogListScroll (props) {
|
||||||
const { posts } = props
|
const { posts } = props
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import DarkModeButton from '@/components/DarkModeButton'
|
import DarkModeButton from '@/components/DarkModeButton'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
|
||||||
export const Footer = (props) => {
|
/**
|
||||||
|
* 页脚
|
||||||
|
* @param {*} props
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function Footer (props) {
|
||||||
const d = new Date()
|
const d = new Date()
|
||||||
const currentYear = d.getFullYear()
|
const currentYear = d.getFullYear()
|
||||||
const since = siteConfig('SINCE')
|
const since = siteConfig('SINCE')
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { compressImage } from '@/lib/notion/mapImage'
|
|||||||
* 网站顶部
|
* 网站顶部
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const Header = (props) => {
|
export default function Header (props) {
|
||||||
const { siteInfo } = props
|
const { siteInfo } = props
|
||||||
const avatar = compressImage(siteInfo?.icon || siteConfig('AVATAR'), 200)
|
const avatar = compressImage(siteInfo?.icon || siteConfig('AVATAR'), 200)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { MenuList } from './MenuList'
|
|||||||
* @param {*} props
|
* @param {*} props
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const NavBar = (props) => {
|
export default function NavBar (props) {
|
||||||
const [showSearchInput, changeShowSearchInput] = useState(false)
|
const [showSearchInput, changeShowSearchInput] = useState(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ import Live2D from '@/components/Live2D'
|
|||||||
import Announcement from './Announcement'
|
import Announcement from './Announcement'
|
||||||
import Catalog from './Catalog'
|
import Catalog from './Catalog'
|
||||||
|
|
||||||
export const SideBar = (props) => {
|
/**
|
||||||
|
* 侧边栏
|
||||||
|
* @param {*} props
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function SideBar (props) {
|
||||||
const { notice } = props
|
const { notice } = props
|
||||||
return (<>
|
return (<>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { siteConfig } from '@/lib/config'
|
|||||||
* 网站顶部 提示栏
|
* 网站顶部 提示栏
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const TopBar = (props) => {
|
export default function TopBar (props) {
|
||||||
const content = siteConfig('SIMPLE_TOP_BAR_CONTENT', null, CONFIG)
|
const content = siteConfig('SIMPLE_TOP_BAR_CONTENT', null, CONFIG)
|
||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
|
|||||||
@@ -1,31 +1,34 @@
|
|||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
import { BlogListPage } from './components/BlogListPage'
|
|
||||||
import { BlogListScroll } from './components/BlogListScroll'
|
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { isBrowser } from '@/lib/utils'
|
import { isBrowser } from '@/lib/utils'
|
||||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
|
||||||
import { ArticleLock } from './components/ArticleLock'
|
|
||||||
import NotionPage from '@/components/NotionPage'
|
|
||||||
import { ArticleInfo } from './components/ArticleInfo'
|
|
||||||
import Comment from '@/components/Comment'
|
|
||||||
import ArticleAround from './components/ArticleAround'
|
|
||||||
import ShareBar from '@/components/ShareBar'
|
|
||||||
import { AdSlot } from '@/components/GoogleAdsense'
|
|
||||||
import Link from 'next/link'
|
|
||||||
import { TopBar } from './components/TopBar'
|
|
||||||
import { Header } from './components/Header'
|
|
||||||
import { NavBar } from './components/NavBar'
|
|
||||||
import { siteConfig } from '@/lib/config'
|
|
||||||
import { SideBar } from './components/SideBar'
|
|
||||||
import JumpToTopButton from './components/JumpToTopButton'
|
|
||||||
import { Footer } from './components/Footer'
|
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import SearchInput from './components/SearchInput'
|
import { AdSlot } from '@/components/GoogleAdsense'
|
||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
import { Transition } from '@headlessui/react'
|
import { Transition } from '@headlessui/react'
|
||||||
|
import Link from 'next/link'
|
||||||
import { Style } from './style'
|
import { Style } from './style'
|
||||||
import replaceSearchResult from '@/components/Mark'
|
import replaceSearchResult from '@/components/Mark'
|
||||||
import CommonHead from '@/components/CommonHead'
|
import dynamic from 'next/dynamic'
|
||||||
import WWAds from '@/components/WWAds'
|
|
||||||
|
// 主题组件
|
||||||
|
const BlogListScroll = dynamic(() => import('./components/BlogListScroll'), { ssr: false });
|
||||||
|
const BlogArchiveItem = dynamic(() => import('./components/BlogArchiveItem'), { ssr: false });
|
||||||
|
const ArticleLock = dynamic(() => import('./components/ArticleLock'), { ssr: false });
|
||||||
|
const NotionPage = dynamic(() => import('@/components/NotionPage'), { ssr: false });
|
||||||
|
const ArticleInfo = dynamic(() => import('./components/ArticleInfo'), { ssr: false });
|
||||||
|
const Comment = dynamic(() => import('@/components/Comment'), { ssr: false });
|
||||||
|
const ArticleAround = dynamic(() => import('./components/ArticleAround'), { ssr: false });
|
||||||
|
const ShareBar = dynamic(() => import('@/components/ShareBar'), { ssr: false });
|
||||||
|
const TopBar = dynamic(() => import('./components/TopBar'), { ssr: false });
|
||||||
|
const Header = dynamic(() => import('./components/Header'), { ssr: false });
|
||||||
|
const NavBar = dynamic(() => import('./components/NavBar'), { ssr: false });
|
||||||
|
const SideBar = dynamic(() => import('./components/SideBar'), { ssr: false });
|
||||||
|
const JumpToTopButton = dynamic(() => import('./components/JumpToTopButton'), { ssr: false });
|
||||||
|
const Footer = dynamic(() => import('./components/Footer'), { ssr: false });
|
||||||
|
const SearchInput = dynamic(() => import('./components/SearchInput'), { ssr: false });
|
||||||
|
const CommonHead = dynamic(() => import('@/components/CommonHead'), { ssr: false });
|
||||||
|
const WWAds = dynamic(() => import('@/components/WWAds'), { ssr: false });
|
||||||
|
const BlogListPage = dynamic(() => import('./components/BlogListPage'), { ssr: false })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础布局
|
* 基础布局
|
||||||
|
|||||||
Reference in New Issue
Block a user