diff --git a/.env.local b/.env.local index d7ba778d..7def2aa4 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=4.0.1 \ No newline at end of file +NEXT_PUBLIC_VERSION=4.0.3 \ No newline at end of file diff --git a/blog.config.js b/blog.config.js index 548466a0..97169215 100644 --- a/blog.config.js +++ b/blog.config.js @@ -73,9 +73,9 @@ const BLOG = { '"Segoe UI Symbol"', '"Apple Color Emoji"' ], - FONT_AWESOME: process.env.NEXT_PUBLIC_FONT_AWESOME_PATH || '/css/all.min.css', // font-awesome 字体图标地址、默认读取本地; 可选 https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css + FONT_AWESOME: process.env.NEXT_PUBLIC_FONT_AWESOME_PATH || 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', // font-awesome 字体图标地址; 可选 /css/all.min.css , https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css - CUSTOM_RIGHT_CLICK_CONTEXT_MENU: process.env.NEXT_PUBLIC_FONT_AWESOME_PATH || true, // 自定义右键菜单,覆盖系统菜单 + CUSTOM_RIGHT_CLICK_CONTEXT_MENU: process.env.NEXT_PUBLIC_CUSTOM_RIGHT_CLICK_CONTEXT_MENU || true, // 自定义右键菜单,覆盖系统菜单 // 自定义外部脚本,外部样式 CUSTOM_EXTERNAL_JS: [''], // e.g. ['http://xx.com/script.js','http://xx.com/script.js'] @@ -103,7 +103,7 @@ const BLOG = { CODE_COLLAPSE: process.env.NEXT_PUBLIC_CODE_COLLAPSE || 'false', // 是否折叠代码框 // Mermaid 图表CDN - MERMAID_CDN: process.env.NEXT_PUBLIC_MERMAID_CDN || 'https://cdn.jsdelivr.net/npm/mermaid@10.2.2/dist/mermaid.min.js', // CDN + MERMAID_CDN: process.env.NEXT_PUBLIC_MERMAID_CDN || 'https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.2.4/mermaid.min.js', // CDN BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc BACKGROUND_DARK: '#000000', // use hex value, don't forget '#' diff --git a/components/CommonHead.js b/components/CommonHead.js index fcc4981f..f4f9a772 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -16,56 +16,66 @@ const CommonHead = ({ meta, children }) => { const category = meta?.category || BLOG.KEYWORDS || '軟體科技' // section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 return ( - - {title} - - - - - {BLOG.SEO_GOOGLE_SITE_VERIFICATION && ( - - )} - {BLOG.SEO_BAIDU_SITE_VERIFICATION && ()} - - - - - - - - - - - - + + {title} + + + + + {BLOG.SEO_GOOGLE_SITE_VERIFICATION && ( + + )} + {BLOG.SEO_BAIDU_SITE_VERIFICATION && ()} + + + + + + + + + + + + - {BLOG.COMMENT_WEBMENTION.ENABLE && ( - <> - - - - )} - {BLOG.COMMENT_WEBMENTION.ENABLE && BLOG.COMMENT_WEBMENTION.AUTH !== '' && ( - - )} + {/* 预加载字体 */} + {BLOG.FONT_AWESOME && <> + + + } + {BLOG.FONT_URL?.map((fontUrl, index) => { + return + })} - {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } - {meta?.type === 'Post' && ( - <> - - - - - - )} - {children} - + {BLOG.COMMENT_WEBMENTION.ENABLE && ( + <> + + + + )} + + {BLOG.COMMENT_WEBMENTION.ENABLE && BLOG.COMMENT_WEBMENTION.AUTH !== '' && ( + + )} + + {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } + {meta?.type === 'Post' && ( + <> + + + + + + )} + {children} + ) } diff --git a/components/ExternalScript.js b/components/ExternalScript.js index 66fe457c..62b6e95c 100644 --- a/components/ExternalScript.js +++ b/components/ExternalScript.js @@ -1,15 +1,15 @@ +'use client' + import BLOG from '@/blog.config' -import { loadExternalResource } from '@/lib/utils' -import { useEffect } from 'react' +import { isBrowser, loadExternalResource } from '@/lib/utils' /** * 自定义引入外部JS 和 CSS * @returns */ const ExternalScript = () => { - useEffect(() => { + if (isBrowser()) { // 静态导入本地自定义样式 - loadExternalResource(BLOG.FONT_AWESOME, 'css') loadExternalResource('/css/custom.css', 'css') loadExternalResource('/js/custom.js', 'js') @@ -28,12 +28,7 @@ const ExternalScript = () => { loadExternalResource(url, 'css') } } - // 渲染所有字体 - BLOG.FONT_URL?.forEach(e => { - loadExternalResource(e, 'css') - }) - }, []) - + } return null } diff --git a/components/GoogleAdsense.js b/components/GoogleAdsense.js index e7847674..9cdaa406 100644 --- a/components/GoogleAdsense.js +++ b/components/GoogleAdsense.js @@ -34,7 +34,10 @@ export default function GoogleAdsense() { const router = useRouter() useEffect(() => { - initGoogleAdsense() + // 延迟3秒加载 + setTimeout(() => { + initGoogleAdsense() + }, 3000) }, [router]) return null diff --git a/components/LazyImage.js b/components/LazyImage.js new file mode 100644 index 00000000..28b48ef8 --- /dev/null +++ b/components/LazyImage.js @@ -0,0 +1,104 @@ +import Head from 'next/head' +import React, { useEffect, useRef, useState } from 'react' + +/** + * 默认懒加载占位图 + */ +const loadingSVG = ( + + + +) + +/** + * 图片懒加载 + * @param {*} param0 + * @returns + */ +export default function LazyImage({ + priority, + id, + src, + alt, + placeholderSrc = loadingSVG, + className, + width, + height, + onLoad, + style +}) { + const imageRef = useRef(null) + const [imageLoaded, setImageLoaded] = useState(false) + + const handleImageLoad = () => { + setImageLoaded(true) + if (typeof onLoad === 'function') { + onLoad() // 触发传递的onLoad回调函数 + } + } + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const lazyImage = entry.target + lazyImage.src = src + observer.unobserve(lazyImage) + } + }) + }, + { rootMargin: '50px 0px' } // Adjust the rootMargin as needed to trigger the loading earlier or later + ) + + if (imageRef.current) { + observer.observe(imageRef.current) + } + + return () => { + if (imageRef.current) { + observer.unobserve(imageRef.current) + } + } + }, [src]) + + // 动态添加width、height和className属性,仅在它们为有效值时添加 + const imgProps = { + ref: imageRef, + src: imageLoaded ? src : placeholderSrc, + alt: alt, + onLoad: handleImageLoad + } + + if (id) { + imgProps.id = id + } + + if (width && width !== 'auto') { + imgProps.width = width + } + + if (height && height !== 'auto') { + imgProps.height = height + } + if (className) { + imgProps.className = className + } + if (style) { + imgProps.style = style + } + return (<> + {/* eslint-disable-next-line @next/next/no-img-element */} + + {/* 预加载 */} + {priority && + + } + ) +} diff --git a/components/NotionIcon.js b/components/NotionIcon.js index cb6ae846..e60b0640 100644 --- a/components/NotionIcon.js +++ b/components/NotionIcon.js @@ -1,3 +1,5 @@ +import LazyImage from './LazyImage' + /** * notion的图标icon * 可能是emoji 可能是 svg 也可能是 图片 @@ -9,9 +11,7 @@ const NotionIcon = ({ icon }) => { } if (icon.startsWith('http') || icon.startsWith('data:')) { - // return - // eslint-disable-next-line @next/next/no-img-element - return + return } return {icon} diff --git a/lib/sitemap.xml.js b/lib/sitemap.xml.js index bb5239f1..e2725f23 100644 --- a/lib/sitemap.xml.js +++ b/lib/sitemap.xml.js @@ -21,9 +21,11 @@ export async function generateSitemapXml({ allPages }) { changefreq: 'daily' }] + // 循环页面生成 allPages?.forEach(post => { + const slugWithoutLeadingSlash = post?.slug?.startsWith('/') ? post?.slug?.slice(1) : post.slug urls.push({ - loc: `${BLOG.LINK}/${post.slug}`, + loc: `${BLOG.LINK}/${slugWithoutLeadingSlash}`, lastmod: new Date(post?.publishTime).toISOString().split('T')[0], changefreq: 'daily' }) diff --git a/package.json b/package.json index 8ea3be05..a415d7b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "4.0.1", + "version": "4.0.3", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { diff --git a/pages/_app.js b/pages/_app.js index d20f396c..a6a11399 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -28,9 +28,9 @@ const MyApp = ({ Component, pageProps }) => { return ( - - + + ) } diff --git a/pages/sitemap.xml.js b/pages/sitemap.xml.js index a613a277..58011385 100644 --- a/pages/sitemap.xml.js +++ b/pages/sitemap.xml.js @@ -39,8 +39,9 @@ export const getServerSideProps = async (ctx) => { } ] const postFields = allPages?.filter(p => p.status === BLOG.NOTION_PROPERTY_NAME.status_publish)?.map(post => { + const slugWithoutLeadingSlash = post?.slug.startsWith('/') ? post?.slug?.slice(1) : post.slug return { - loc: `${BLOG.LINK}/${post.slug}`, + loc: `${BLOG.LINK}/${slugWithoutLeadingSlash}`, lastmod: new Date(post?.publishTime).toISOString().split('T')[0], changefreq: 'daily', priority: '0.7' diff --git a/themes/example/components/BlogPostCard.js b/themes/example/components/BlogPostCard.js index 03f38ec6..faf1753d 100644 --- a/themes/example/components/BlogPostCard.js +++ b/themes/example/components/BlogPostCard.js @@ -2,6 +2,7 @@ import BLOG from '@/blog.config' import CONFIG from '../config' import Link from 'next/link' import TwikooCommentCount from '@/components/TwikooCommentCount' +import LazyImage from '@/components/LazyImage' const BlogPostCard = ({ post }) => { const showPageCover = CONFIG.POST_LIST_COVER && post?.pageCoverThumbnail @@ -41,7 +42,7 @@ const BlogPostCard = ({ post }) => { {showPageCover && (
-
+
)} diff --git a/themes/fukasawa/components/ArticleDetail.js b/themes/fukasawa/components/ArticleDetail.js index 1ea23429..a1297dd2 100644 --- a/themes/fukasawa/components/ArticleDetail.js +++ b/themes/fukasawa/components/ArticleDetail.js @@ -6,6 +6,7 @@ import { useGlobal } from '@/lib/global' import Link from 'next/link' import ArticleAround from './ArticleAround' import { AdSlot } from '@/components/GoogleAdsense' +import LazyImage from '@/components/LazyImage' /** * @@ -23,8 +24,7 @@ export default function ArticleDetail(props) {
{post?.type && !post?.type !== 'Page' && post?.pageCover && (
- {/* eslint-disable-next-line @next/next/no-img-element */} - {post.title} +
)} diff --git a/themes/fukasawa/components/BlogCard.js b/themes/fukasawa/components/BlogCard.js index 9074c7c4..ec9070f4 100644 --- a/themes/fukasawa/components/BlogCard.js +++ b/themes/fukasawa/components/BlogCard.js @@ -3,6 +3,7 @@ import Link from 'next/link' import TagItemMini from './TagItemMini' import React from 'react' import CONFIG_FUKA from '../config' +import LazyImage from '@/components/LazyImage' const BlogCard = ({ index, post, showSummary, siteInfo }) => { const showPreview = CONFIG_FUKA.POST_LIST_PREVIEW && post.blockMap @@ -26,12 +27,11 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => { {showPageCover && (
- {/* eslint-disable-next-line @next/next/no-img-element */} - {post?.title + />
)} diff --git a/themes/gitbook/components/InfoCard.js b/themes/gitbook/components/InfoCard.js index a18408dc..13fe31c8 100644 --- a/themes/gitbook/components/InfoCard.js +++ b/themes/gitbook/components/InfoCard.js @@ -1,4 +1,5 @@ import BLOG from '@/blog.config' +import LazyImage from '@/components/LazyImage' import Router from 'next/router' import React from 'react' import SocialButton from './SocialButton' @@ -8,8 +9,7 @@ const InfoCard = (props) => { return
{ Router.push('/about') }}> - {/* eslint-disable-next-line @next/next/no-img-element */} - {BLOG.AUTHOR}/ +
{BLOG.AUTHOR}
{BLOG.BIO}
diff --git a/themes/gitbook/components/LogoBar.js b/themes/gitbook/components/LogoBar.js index 803a4fa3..70c96b46 100644 --- a/themes/gitbook/components/LogoBar.js +++ b/themes/gitbook/components/LogoBar.js @@ -1,4 +1,5 @@ import BLOG from '@/blog.config' +import LazyImage from '@/components/LazyImage' import { useGitBookGlobal } from '@/themes/gitbook' import Link from 'next/link' @@ -20,8 +21,7 @@ export default function LogoBar(props) {
- {/* eslint-disable-next-line @next/next/no-img-element */} - {BLOG.AUTHOR} + {siteInfo?.title}
diff --git a/themes/heo/components/ArticleRecommend.js b/themes/heo/components/ArticleRecommend.js index 8679a2e8..f7f6c738 100644 --- a/themes/heo/components/ArticleRecommend.js +++ b/themes/heo/components/ArticleRecommend.js @@ -2,6 +2,7 @@ import Link from 'next/link' import CONFIG from '../config' import BLOG from '@/blog.config' import { useGlobal } from '@/lib/global' +import LazyImage from '@/components/LazyImage' /** * 关联推荐文章 @@ -35,8 +36,8 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
{recommendPosts.map(post => { const headerImage = post?.pageCoverThumbnail - ? `url("${post.pageCoverThumbnail}")` - : `url("${siteInfo?.pageCover}")` + ? post.pageCoverThumbnail + : siteInfo?.pageCover return ( ( -
-
-
+
+
+
{post.title}
+
) diff --git a/themes/heo/components/BlogPostArchive.js b/themes/heo/components/BlogPostArchive.js index 0b092fb2..4f471444 100644 --- a/themes/heo/components/BlogPostArchive.js +++ b/themes/heo/components/BlogPostArchive.js @@ -3,6 +3,7 @@ import Link from 'next/link' import BLOG from '@/blog.config' import CONFIG from '../config' import TagItemMini from './TagItemMini' +import LazyImage from '@/components/LazyImage' /** * 博客归档列表 * @param posts 所有文章 @@ -29,13 +30,13 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => { post.pageCoverThumbnail = siteInfo?.pageCover } const showPageCover = CONFIG.POST_LIST_COVER && post?.pageCoverThumbnail && !showPreview - return
+ return
{/* 图片封面 */} {showPageCover && (
-
+
)} @@ -44,7 +45,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
{/* 分类 */} - {post?.category &&