关于我的 butterfly 主题美化配置 | 字数总计: 2.4k | 阅读时长: 10分钟 | 阅读量:
本文仅适用于 hexo 主题: Butterfly , 版本: 4.3.0
前言
本篇文章用于记录关于本博客 Butterfly 主题的所有美化/配置,后续如有新增变更会持续更新
CDN - 静态资源加速
为什么需要改 CDN ?
国内因复杂的网络环境 ,框架默认使用的 cdn 服务位于国外,有时访问不了
加速资源加载 ,减少用户等待资源加载的时间
我们可以使用来自 官网 提供的配置模板:
供应商
格式
备注
Staticfile(七牛云)
https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file}
同步 cdnjs
BootCDN
https://cdn.bootcdn.net/ajax/libs/${cdnjs_name}/${version}/${min_cdnjs_file}
同步 cdnjs
Baomitu(360)
最新版本: https://lib.baomitu.com/${cdnjs_name}/latest/${min_cdnjs_file}
同步 cdnjs
指定版本: https://lib.baomitu.com/${cdnjs_name}/${version}/${min_cdnjs_file}
Elemecdn
最新版本: https://npm.elemecdn.com/${name}@latest/${file}
同步 npm
指定版本: https://npm.elemecdn.com/${name}@${version}/${file}
此处我们使用 七牛云 用于博客加速:
需要注意的是我们需要修改 fancybox_css_v4 和 fancybox_v4 的链接指向,因为其默认格式不正确
CDN: internal_provider: custom third_party_provider: custom custom_format: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file} version: false option: fancybox_css_v4: https://cdn.staticfile.org/fancyapps-ui/4.0.18/fancybox.min.css fancybox_v4: https://cdn.staticfile.org/fancyapps-ui/4.0.18/fancybox.umd.min.js
PWA - 离线化浏览
为什么需要 PWA ?
访问不受网络影响 :比如打开了本篇文章,不妨试试断开网络后刷新当前页面,你会发现页面依然可以展示
加速资源加载访问 :我们可以选择策略,当访问资源时,存在缓存则返回,再去发起网络请求资源更新缓存,因博客变化变更周期不大,因此资源文件/文章可长期缓存,不过缺点是发生变更后,需要多刷新一次
PWA 启用需要什么?
网站为 https
或者 127.0.0.1
(本地)
manifest.json
网页清单
一个在设备上代表应用的图标
注册 Service Worker
我们可以使用 google 的 workbox 使博客支持 PWA 便于 离线化访问
相关 workbox 策略参考官网 ,支持的策略有:
策略名
流程图
描述
StaleWhileRevalidate
页面发起的请求被 SW 代理
SW 查看缓存是否存在,若存在则转 3,若不存在则转 4
SW 获取缓存内容返回请求,转 4
SW 向网络发起请求,若返回的内容合法则更新缓存
CacheFirst
页面发起的请求被 SW 代理
SW 查看缓存是否存在,若存在则直接返回,若不存在则转 3
SW 向网络发起请求,若返回合法则更新缓存,并返回
CacheOnly
页面发起的请求被 SW 代理
SW 查看缓存是否存在,若存在则直接返回,若不存在则返回失败
NetworkFirst
页面发起的请求被 SW 代理
SW 向网络发起请求,若返回合法则缓存,并返回,若请求失败,则转 3
SW 从缓存中获取,并返回
NetworkOnly
页面发起的请求被 SW 代理
SW 向网络发起请求,若返回合法则缓存,并返回,若请求失败则返回失败
我选用 StaleWhileRevalidate 策略,因为它既 不会更新太慢 ,也 不会影响加载速度 ,同时还兼顾了 离线化阅读 的需求
此处部分配置参考了这篇 文章,并加以改进
为此,我们还需要以下几个步骤以启用 PWA :
配置 PWA
的 manifest.json
配置生成 workbox
的 sw.js
文件,配置 service worker
的策略文件
启用 butterfly
的 pwa 配置,配置 sw.js
注册
1) 配置 PWA
的 manifest.json
为什么要配置 manifest.json
?
PWA 要求的
manifest.json
里包含提供了一些信息(如名称,作者,图标和描述),便于 Web 应用程序安装到设备的主屏幕时所展示
具体 manifest.json
要求请参考 官网
我们需要各个尺寸图标,用于代表应用的图标,将自己喜爱的图片裁剪成所需尺寸,放置于 source/images/pwa
下,再按照如下样例所配
本博客的 manifest.json
配置如下所示(该文件放置于 source/manifest.json
):
{ "name" : "报时's Blog" , "short_name" : "Boss Blog" , "theme_color" : "#49b1f5" , "background_color" : "#49b1f5" , "display" : "standalone" , "scope" : "/" , "start_url" : "/" , "id" : "/" , "icons" : [ { "src" : "/images/pwa/36.png" , "sizes" : "36x36" , "type" : "image/png" } , { "src" : "/images/pwa/48.png" , "sizes" : "48x48" , "type" : "image/png" } , { "src" : "/images/pwa/96.png" , "sizes" : "96x96" , "type" : "image/png" } , { "src" : "/images/pwa/144.png" , "sizes" : "144x144" , "type" : "image/png" } , { "src" : "/images/pwa/192.png" , "sizes" : "192x192" , "type" : "image/png" } , { "src" : "/images/pwa/512.png" , "sizes" : "512x512" , "type" : "image/png" } ] , "splash_pages" : null }
2) 配置生成 workbox
的 sw.js
文件,配置 service worker
的策略文件
安装 workbox
:
yarn add workbox-build -D
添加 scripts/events/pwa.js
文件,注册 before_generate
事件,在 hexo
生成文件之前生成 sw.js
:
const path = require ("path" );const workbox = require ("workbox-build" );const fs = require ('fs' );hexo.extend .filter .register ('before_generate' , async () => { fs.existsSync (hexo.public_dir ) && fs.readdirSync (hexo.public_dir ).forEach (file => { if (file.match (/^workbox-[^.]+.js(.map)?$/ )) { fs.unlinkSync (path.join (hexo.public_dir , file)); } }); let offline = require (path.join (hexo.base_dir , '/hexo-offline.config.cjs' )); await workbox.generateSW (offline); } )
添加 hexo-offline.config.cjs
策略配置文件,其配置文件格式参考官网 :
module .exports = { globPatterns : [], globDirectory : 'public/' , swDest : 'public/sw.js' , maximumFileSizeToCacheInBytes : 20971520 , skipWaiting : true , clientsClaim : true , cleanupOutdatedCaches : true , runtimeCaching : [ { urlPattern : /^http(s)?:\/\/hm\.baidu\.com\/.*/ , handler : 'NetworkOnly' , method : 'GET' }, { urlPattern : /^http:\/\/127\.0\.0\.1(:[0-9]+)?\/.*/ , handler : 'NetworkOnly' , method : 'GET' }, { urlPattern : /.*/ , handler : 'StaleWhileRevalidate' , method : 'GET' } ] }
此步过后,当我们执行 hexo g
后,我们会有 public/sw.js
以及 public/workbox-*.js
两个文件,到此 service worker
文件生成完了
接下来我们需要在各个页面去注册执行 sw.js
3) 启用 butterfly
的 pwa 配置,配置 sw.js
注册
编辑主题配置文件 _config.butterfly.yml
启用 pwa
,如下:
pwa: enable: true manifest: /manifest.json apple_touch_icon: /pwa/apple-touch-icon.png favicon_32_32: /images/pwa/32.png favicon_16_16: /images/pwa/16.png mask_icon: /pwa/safari-pinned-tab.svg
主题配置文件 _config.butterfly.yml
中配置加入脚本,为 pwa
提供注册以及提醒更新功能,如下:
inject: head: - '<link rel="stylesheet" href="/third/pwa/pwa.css">' bottom: - '<div class="app-refresh" id="app-refresh"><div class="app-refresh-wrap"> <label>✨ 网站已更新最新版本 👉</label> <a href="javascript:void(0)" onclick="location.reload()">点击刷新</a> </div></div>' - '<script src="/third/pwa/pwa.js"></script>'
添加提示更新的 css 文件,source/third/pwa/pwa.css
:
.app-refresh { position : fixed; top : -2.2rem ; left : 0 ; right : 0 ; z-index : 99999 ; padding : 0 1rem ; font-size : 15px ; height : 2.2rem ; transition : all .3s ease } .app-refresh-wrap { display : flex; color : #fff ; height : 100% ; align-items : center; justify-content : center } .app-refresh-wrap a { color : #fff ; text-decoration : underline; cursor : pointer }
添加用于注册 service worker
以及提示 service worker
更新的脚本:
function showNotification ( ) { if (GLOBAL_CONFIG .Snackbar ) { var t = "light" === document .documentElement .getAttribute ("data-theme" ) ? GLOBAL_CONFIG .Snackbar .bgLight : GLOBAL_CONFIG .Snackbar .bgDark , e = GLOBAL_CONFIG .Snackbar .position ; Snackbar .show ({ text : "已更新最新版本" , backgroundColor : t, duration : 5e5 , pos : e, actionText : "点击刷新" , actionTextColor : "#fff" , onActionClick : function (t ) { location.reload () } }) } else { var o = `top: 0; background: ${"light" === document .documentElement.getAttribute("data-theme" ) ? "#49b1f5" : "#1f1f1f" } ;` ; document .getElementById ("app-refresh" ).style .cssText = o; } } "serviceWorker" in navigator && (navigator.serviceWorker .controller && navigator.serviceWorker .addEventListener ("controllerchange" , function ( ) { showNotification (); }), window .addEventListener ("load" , function ( ) { navigator.serviceWorker .register ("/sw.js" ); }));
hexo
配置文件 _config.yml
中,排除手动加入的资源文件解析:
skip_render: - manifest.json - third/**
在 scripts/events/pwa.js
处配置 hexo
的 generate事件拦截 ,生成 sw.js
以及 workbox-*.js
,文件路径为 :
const path = require ("path" );const workbox = require ("workbox-build" );const fs = require ('fs' );hexo.extend .filter .register ('before_generate' , async () => { fs.existsSync (hexo.public_dir ) && fs.readdirSync (hexo.public_dir ).forEach (file => { if (file.match (/^workbox-[^.]+.js(.map)?$/ )) { fs.unlinkSync (path.join (hexo.public_dir , file)); } }); let offline = require (path.join (hexo.base_dir , '/hexo-offline.config.cjs' )); await workbox.generateSW (offline); } )
启用更新 提示框 ,并配置提示背景色:
snackbar: enable: true position: top-right bg_light: '#1f1f1f' bg_dark: '#49b1f5'
我们在本地访问生成的页面时,打开 应用程序
,见到如下便可视为 成功注册 :
当 service worker
发生变化时 (当 sw.js
字节发生变更),会出现如下图所示的提示: