diff --git a/.github/workflows/build-theme.yml b/.github/workflows/build-theme.yml index ffcf534..0818cf4 100644 --- a/.github/workflows/build-theme.yml +++ b/.github/workflows/build-theme.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - refactor_comment pull_request: branches: [ "main" ] diff --git a/_config.yml b/_config.yml index 6e44a2a..9426f28 100644 --- a/_config.yml +++ b/_config.yml @@ -21,8 +21,6 @@ pwa: # 实验性特性 experiments: - gradient: false # 使用CSS渐变作为文章封面 - fixedCover: "" # 主页面cover(为空则使用bing随机图片) debug: false # 使用debug模式启动 disableThemeComment: false # 禁用主题评论系统(一般用于关闭评论或让插件接管评论系统) usingRelative: false # _image.yml 使用相对路径 @@ -30,6 +28,11 @@ experiments: # 具体见https://docs.kaitaku.xyz/guide/theme.html#%E9%95%BF%E6%96%87%E7%AB%A0%E4%BC%98%E5%8C%96 mobileWidth: 820px # 移动版和桌面版导航栏最短切换长度 +homeConfig: + gradient: false # 使用CSS渐变作为文章封面 + # fixedCover 性能比默认的更好,且开启时将启用LCP优化和预加载 TODO + fixedCover: "" # 主页面cover(为空则使用bing随机图片) + # ShokaX 模块化分包引入设置 # 请关闭所有不使用的模块以优化主题 js 体积和性能 modules: @@ -41,11 +44,17 @@ modules: quiz: true # 启用文章内问题扩展支持 fancybox: true # 启用 fancybox 支持(不建议禁用) +styles: + postprocess: true # 启用后处理器 + modules: + mermaid: false + # 优化性能区 performance: # 使用preconnect预加载的网址(不建议超过三个) preConnect: - "https://lf9-cdn-tos.bytecdntp.com" + - "https://at.alicdn.com" # 使用dns-prefetch预解析的网址 dnsPrefetch: diff --git a/layout/_mixin/segment.pug b/layout/_mixin/segment.pug index 0bcb342..b685862 100644 --- a/layout/_mixin/segment.pug +++ b/layout/_mixin/segment.pug @@ -1,6 +1,6 @@ include postmeta.pug -mixin SMRender(item) +mixin SMRender(item, lazy) - var link1 = item.link || item.path - var gradient = theme?.experiments?.gradient if item.link @@ -11,7 +11,10 @@ mixin SMRender(item) div(class="cover" style=`background: linear-gradient(to bottom right, ${random_color()}, ${random_color()});`) else div(class="cover") - != _url(link1, '', {itemprop: 'url', title: postText}) + if lazy + != _url(link1, '', {itemprop: 'url', title: postText}) + else + != _url(link1, '', {itemprop: 'url', title: postText}) div(class="info") +PMRender(item) h3 diff --git a/layout/_partials/footer.pug b/layout/_partials/footer.pug index baffc48..00efe5a 100644 --- a/layout/_partials/footer.pug +++ b/layout/_partials/footer.pug @@ -34,7 +34,7 @@ div(class="status") if beianN && RC br a(target="_blank" href=`https://beian.mps.gov.cn/#/query/webSearch?code=${RC}`) - img(src=theme.statics + theme.assets + '/' + theme.footer.icp.icon style="max-width: 2em;display:inline;" width="20" height="20") + img(loading="lazy" decoding="async" data-src=theme.statics + theme.assets + '/' + theme.footer.icp.icon style="max-width: 2em;display:inline;" width="20" height="20") != beianN != shokax_inject('status') diff --git a/layout/_partials/head/head.pug b/layout/_partials/head/head.pug index b3067c4..ebfe83e 100644 --- a/layout/_partials/head/head.pug +++ b/layout/_partials/head/head.pug @@ -42,16 +42,11 @@ each dnsLink in dnslinks if fontConfig != _vendor_font() != _css('app.css') - -if theme.polyfill.enable - script(src=`https://polyfill.io/v3/polyfill.min.js?features=${theme.polyfill.features}` defer) - -!= vendor_js() -!= _js('siteInit.js') +!= preloadjs() include pwa.pug -else if wl - link(rel="stylesheet" href="https://npm.webcache.cn/@waline/client@v2/dist/waline.css" media="none" onload="this.media='all'") +if wl + link(rel="stylesheet" href="https://npm.webcache.cn/@waline/client@3.0.0-alpha.11/dist/waline.css" media="none" onload="this.media='all'") - var qw = theme?.qweather?.enable if qw diff --git a/layout/_partials/header.pug b/layout/_partials/header.pug index a655911..8de875d 100644 --- a/layout/_partials/header.pug +++ b/layout/_partials/header.pug @@ -10,7 +10,7 @@ nav(id="nav") a(href=config.root rel="start") != alternate || title ul(class="right" id="rightNav") - li(class="item theme" @click="changeThemeByBtn") + li(class="item theme") i(class="ic i-sun") li(class="item search") i(class="ic i-search") diff --git a/layout/_partials/layout.pug b/layout/_partials/layout.pug index bb513f8..de3d196 100644 --- a/layout/_partials/layout.pug +++ b/layout/_partials/layout.pug @@ -35,18 +35,18 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f != partial('_partials/header.pug', {}, {cache: true}) div(id="imgs" class="pjax") - if theme.experiments.gradient || theme.experiments.fixedCover + if theme.homeConfig.gradient || theme.homeConfig.fixedCover //- cover不可用时用Bing随机图片代替 - - var coverImage = theme.experiments.fixedCover || "https://7ed.net/bing/api" - img(src=coverImage) + - var coverImage = theme.homeConfig.fixedCover || "https://7ed.net/bing/api" + img(src=coverImage loading="eager" decoding="async" fetchpriority="high") else - var covers = _cover_index(page, 6) if covers.length === 6 ul each image in covers - li(class="item" data-background-image=image) + li(class="item" style=`background-image: url("${image}");`) else - img(src=covers) + img(src=covers loading="eager" decoding="async" fetchpriority="high") div(id="waves") svg(class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto") defs @@ -119,10 +119,12 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f != partial('_partials/third-party/baidu-analytics.pug', {}, {cache: true}) != partial('_partials/third-party/clarity.pug', {}, {cache: true}) != partial('_partials/third-party/google-analytics.pug', {}, {cache: true}) - if theme.twikoo.enable - != _new_comments('twikoo') - else if theme.waline.enable - != _new_comments('waline') + + != vendor_js() + if theme.polyfill.enable + script(src=`https://polyfill.io/v3/polyfill.min.js?features=${theme.polyfill.features}` defer) + + != _js('siteInit.js') != shokax_inject('bodyEnd') diff --git a/layout/_partials/post/post.pug b/layout/_partials/post/post.pug index db0da51..c5a9e77 100644 --- a/layout/_partials/post/post.pug +++ b/layout/_partials/post/post.pug @@ -11,7 +11,7 @@ article(itemscope itemtype="http://schema.org/Article" class="post block" lang=t if post.photos && post.photos.length div(class="gallery" itemscope itemtype="http://schema.org/ImageGallery") each photo in post.photos - img(loading="lazy" data-src=_image_url(photo, post.path) itemprop="contentUrl") + img(loading="lazy" decoding="async" data-src=_image_url(photo, post.path) itemprop="contentUrl") if theme.summary.enable && page.layout === 'post' div(class='tabs' id='summary') div(class="show-btn") diff --git a/layout/_partials/sidebar/overview.pug b/layout/_partials/sidebar/overview.pug index c1b9fa9..52491ec 100644 --- a/layout/_partials/sidebar/overview.pug +++ b/layout/_partials/sidebar/overview.pug @@ -1,6 +1,6 @@ div(class="author" itemprop="author" itemscope itemtype="http://schema.org/Person") - img(loading="lazy" class="image" itemprop="image" alt=author - data-src=url_for(theme.statics + theme.assets + '/'+ theme.sidebar.avatar)) + img(loading="eager" decoding="async" class="image" itemprop="image" alt=author + src=url_for(theme.statics + theme.assets + '/'+ theme.sidebar.avatar)) p(class="name" itemprop="name") != author div(class="description" itemprop="description") diff --git a/layout/index.pug b/layout/index.pug index 9900092..2eced5b 100644 --- a/layout/index.pug +++ b/layout/index.pug @@ -12,7 +12,7 @@ block content - var sticky = page.sticky.toArray() div(class="segments sticky") each post in sticky - +SMRender(post) + +SMRender(post, false) if page.catlist.length > 0 h2(class="divider") != __('index.category') @@ -27,7 +27,7 @@ block content != __('index.posts') div(class="segments posts") each post in posts - +SMRender(post) + +SMRender(post, true) include _partials/pagination.pug diff --git a/package.json b/package.json index e26490e..c6045ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-shokax", - "version": "0.4.0-alpha.3", + "version": "0.4.0-alpha.4", "description": "a hexo theme based on shoka", "main": "index.js", "repository": "https://github.com/theme-shoka-x/hexo-theme-shokaX", diff --git a/scripts/generaters/script.ts b/scripts/generaters/script.ts index 65c1993..57041ff 100644 --- a/scripts/generaters/script.ts +++ b/scripts/generaters/script.ts @@ -59,7 +59,7 @@ hexo.extend.generator.register('script', function (locals) { twikoo: { envId: theme.twikoo.envId, region: theme.twikoo.region - }, + } } if (config?.algolia) { @@ -148,8 +148,6 @@ hexo.extend.generator.register('script', function (locals) { } }) } - fs.unlinkSync(`./shokaxTemp/${file}`) }) - fs.rmSync('./shokaxTemp', { force: true, recursive: true }) return res }) diff --git a/scripts/helpers/asset.ts b/scripts/helpers/asset.ts index 0447975..62bb5dd 100644 --- a/scripts/helpers/asset.ts +++ b/scripts/helpers/asset.ts @@ -61,20 +61,20 @@ hexo.extend.helper.register('_css', function (...urls) { return urls.map(url => htmlTag('link', { rel: 'stylesheet', href: url_for.call(this, `${statics}${css}/${url}?v=${theme_env.version}`) - })).join('') + }), '').join('') }) hexo.extend.helper.register('_js', function (...urls) { const { statics, js } = hexo.theme.config - return urls.map(url => htmlTag('script', { src: url_for.call(this, `${statics}${js}/${url}?v=${theme_env.version}`), type: 'module',fetchpriority: 'high' }, '')).join('') + return urls.map(url => htmlTag('script', { src: url_for.call(this, `${statics}${js}/${url}?v=${theme_env.version}`), type: 'module', fetchpriority: 'high', defer: true }, '')).join('') }) hexo.extend.helper.register('vendor_js', function () { const vendors = hexo.theme.config.vendors as VendorsConfig let res = '' for (const jsSync in vendors.js) { - res += htmlTag('script', { src: getVendorLink(hexo, vendors.js[jsSync]) }, '') + res += htmlTag('script', { src: getVendorLink(hexo, vendors.js[jsSync]), async: true }, '') } // for (const jsAsync in vendors.async_js) { // res += htmlTag('script', { src: getVendorLink(hexo, vendors.async_js[jsAsync]), async: true }, '') diff --git a/scripts/helpers/engine.ts b/scripts/helpers/engine.ts index eb18bc8..1536ed4 100644 --- a/scripts/helpers/engine.ts +++ b/scripts/helpers/engine.ts @@ -2,6 +2,8 @@ // @ts-ignore import { htmlTag, url_for } from 'hexo-util' +import fs from 'node:fs' +import theme_env from '../../package.json' const randomServer = parseInt(String(Math.random() * 4), 10) + 1 @@ -53,6 +55,17 @@ const randomBG = function (count = 1, image_server:string = null, image_list:str return parseImage(image_list[Math.floor(Math.random() * image_list.length)], 'mw690') } +hexo.extend.helper.register('preloadjs', function () { + const { statics, js } = hexo.theme.config + let res = '' + fs.readdirSync('./shokaxTemp').forEach((file) => { + if (file.endsWith('.js')) { + res += htmlTag('link', { rel: 'modulepreload', href: url_for.call(this, `${statics}${js}/${file}`) }, '') + } + }) + return res +}) + // 注册hexo主题中的URL帮助方法 hexo.extend.helper.register('_url', function (path, text, options = {}) { // 如果未提供URL路径,则返回 @@ -104,7 +117,7 @@ hexo.extend.helper.register('_cover_index', function (item) { } else if (item.photos && item.photos.length > 0) { return this._image_url(item.photos[0], item.path) } else { - return randomBG(1, image_server, index_images.length === 0 ? image_list : index_images) + return randomBG(6, image_server, index_images.length === 0 ? image_list : index_images) } }) diff --git a/scripts/plugin/index.ts b/scripts/plugin/index.ts index 385df4f..9a5807a 100644 --- a/scripts/plugin/index.ts +++ b/scripts/plugin/index.ts @@ -11,6 +11,7 @@ import * as fs from 'node:fs' hexo.on('generateBefore', () => { // 加载`theme_injects`过滤器 injects(hexo) + fs.rmSync('./shokaxTemp', { force: true, recursive: true }) if (fs.existsSync('request.lock')) { fs.unlinkSync('request.lock') } diff --git a/source/css/_common/scaffolding/base.styl b/source/css/_common/scaffolding/base.styl index d3b46bb..7cc83cc 100644 --- a/source/css/_common/scaffolding/base.styl +++ b/source/css/_common/scaffolding/base.styl @@ -149,12 +149,12 @@ input, textarea { @font-face { font-family: 'ic'; font-display: swap; - src: url('//at.alicdn.com/t/c/font_' + $iconfont + '.eot'); - src: url('//at.alicdn.com/t/c/font_' + $iconfont + '.eot?#iefix') format('embedded-opentype'), - url('//at.alicdn.com/t/c/font_' + $iconfont + '.woff2') format('woff2'), - url('//at.alicdn.com/t/c/font_' + $iconfont + '.woff') format('woff'), - url('//at.alicdn.com/t/c/font_' + $iconfont + '.ttf') format('truetype'), - url('//at.alicdn.com/t/c/font_' + $iconfont + '.svg#ic') format('svg'); + src: url('https://at.alicdn.com/t/c/font_' + $iconfont + '.eot'); + src: url('https://at.alicdn.com/t/c/font_' + $iconfont + '.eot?#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/c/font_' + $iconfont + '.woff2') format('woff2'), + url('https://at.alicdn.com/t/c/font_' + $iconfont + '.woff') format('woff'), + url('https://at.alicdn.com/t/c/font_' + $iconfont + '.ttf') format('truetype'), + url('https://at.alicdn.com/t/c/font_' + $iconfont + '.svg#ic') format('svg'); } @font-face { diff --git a/source/css/comment.styl b/source/css/comment.styl deleted file mode 100644 index f975a3b..0000000 --- a/source/css/comment.styl +++ /dev/null @@ -1,3 +0,0 @@ -@import "_variables.styl"; - -@import "_mixins.styl"; diff --git a/source/js/_app/globals/handles.ts b/source/js/_app/globals/handles.ts index a82e32a..aac68eb 100644 --- a/source/js/_app/globals/handles.ts +++ b/source/js/_app/globals/handles.ts @@ -22,7 +22,7 @@ import { } from './globalVars' import { changeMetaTheme } from './themeColor' import { Loader } from './thirdparty' -import {getHeight, setWidth} from '../library/proto' +import { getHeight, setWidth } from '../library/proto' export const resizeHandle = () => { // 获取 siteNav 的高度 @@ -119,5 +119,5 @@ export const visibilityListener = () => { }, 2000)) break } - }) + }, { passive: true }) } diff --git a/source/js/_app/page/search.ts b/source/js/_app/page/search.ts index 636e5b2..b7fa0b0 100644 --- a/source/js/_app/page/search.ts +++ b/source/js/_app/page/search.ts @@ -5,18 +5,8 @@ import { searchBox, configure, stats, hits, pagination } from 'instantsearch.js/ import type { HitHighlightResult } from 'instantsearch.js/es/types/results' import instantsearch from 'instantsearch.js' import algoliasearch from 'algoliasearch/lite' -import {createChild} from "../library/proto"; export function algoliaSearch (pjax) { - if (CONFIG.search === null) { return } - - if (!siteSearch) { - setSiteSearch(createChild(BODY, 'div', { - id: 'search', - innerHTML: '