Commit 5d12c1d
Changed files (14)
public
src
public/favicon/favicon-128x128.png
Binary file
public/favicon/favicon-180x180.png
Binary file
public/favicon/favicon-192x192.png
Binary file
public/favicon/favicon-32x32.png
Binary file
public/favicon.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"><path d="M2 28 10 2 20 2 28 28 22 28 15 6 8 28Z" fill="#ff788b"/><path d="M22 28 15 6 8 28 9 28 15 8.5 21 28Z" fill="#965664"/><path d="M2.88 25.14a1.2.4-35 0124.085-21.896C32.69 3.82 27.57 10.99 23.8 14.35l-.2-.65C30.22 7.52 32.6.7 20.9 4.925 9.2 9.15-4.64 23.99 3.08 24.49ZM18.2 18.9S14.91 21.47 10.42 23.38l.16-.52S14.15 21.48 18.06 18.4405Z" fill="#ffba76"/></svg>
\ No newline at end of file
src/constants/icon.ts
@@ -1,20 +0,0 @@
-import type { Favicon } from '@/types/config';
-
-export const defaultFavicons: Favicon[] = [
- {
- src: '/favicon/favicon-32x32.png',
- sizes: '32x32',
- },
- {
- src: '/favicon/favicon-128x128.png',
- sizes: '128x128',
- },
- {
- src: '/favicon/favicon-180x180.png',
- sizes: '180x180',
- },
- {
- src: '/favicon/favicon-192x192.png',
- sizes: '192x192',
- },
-];
src/layouts/GlobalLayout.astro
@@ -2,13 +2,13 @@
import { profileConfig, searchConfig, siteConfig, toolBarConfig } from '@/config';
import '@/styles/global.css';
import '@/styles/transition.css';
-import type { Favicon } from '@/types/config';
import Banner from '@components/Banner.astro';
import Navbar from '@components/Navbar.astro';
import PageFooter from '@components/PageFooter.astro';
import Search from '@components/Search.astro';
import SideToolBar from '@components/SideToolBar.astro';
-import { defaultFavicons } from '@constants/icon';
+import { pwaAssetsHead } from 'virtual:pwa-assets/head';
+import { pwaInfo } from 'virtual:pwa-info';
interface Props {
title?: string;
@@ -30,9 +30,6 @@ else
if (!lang) lang = `${siteConfig.lang}`;
const siteLang = lang.replace('_', '-');
-
-const favicons: Favicon[] =
- siteConfig.favicon.length > 0 ? siteConfig.favicon : defaultFavicons;
---
<!doctype html>
@@ -59,18 +56,13 @@ const favicons: Favicon[] =
<meta name="generator" content={Astro.generator} />
{
- favicons.map((favicon) => (
- <link
- rel="icon"
- href={
- favicon.src.startsWith('/')
- ? ['', import.meta.env.BASE_URL, favicon.src].join('/').replace(/\/+/g, '/')
- : favicon.src
- }
- sizes={favicon.sizes}
- />
- ))
+ pwaAssetsHead.themeColor && (
+ <meta name="theme-color" content={pwaAssetsHead.themeColor.content} />
+ )
}
+ {pwaAssetsHead.links.map((link) => <link {...link} />)}
+ {pwaInfo && <Fragment set:html={pwaInfo.webManifest.linkTag} />}
+ <script src="@scripts/pwa.ts"></script>
<link
rel="alternate"
src/scripts/pwa.ts
@@ -0,0 +1,11 @@
+import { registerSW } from 'virtual:pwa-register';
+
+registerSW({
+ immediate: true,
+ onRegisteredSW(swScriptUrl) {
+ console.log('SW registered: ', swScriptUrl);
+ },
+ onOfflineReady() {
+ console.log('PWA application ready to work offline');
+ },
+});
src/types/config.d.ts
@@ -123,12 +123,6 @@ export type SiteConfig = {
* 站点的语言。
*/
lang: string;
- /**
- * The favicon of the site.
- *
- * 站点的 favicon。
- */
- favicon: Favicon[];
/**
* The time when the site was created.
*
src/config.ts
@@ -1,6 +1,8 @@
// WARNING: This file will be bundled into the build product.
// DO NOT add any sensitive information here.
// 警告: 该文件会被打包到构建产物中, 不要在此添加任何敏感信息
+import I18nKey from './i18n/I18nKey';
+import { getRandomPost } from './scripts/utils';
import type {
ArticleConfig,
AsideConfig,
@@ -15,17 +17,11 @@ import type {
SiteConfig,
ToolBarConfig,
} from './types/config';
-import I18nKey from '@i18n/I18nKey';
-import { getRandomPost } from '@scripts/utils';
export const siteConfig: SiteConfig = {
title: 'Astral Halo',
subtitle: 'A static blog template powered by Astro',
- lang: 'en', // "en" | "zh_CN" | "zh_TW"
- favicon: [
- // Leave this array empty to use the default favicon.
- // 留空数组以使用默认的 favicon。
- ],
+ lang: 'zh_CN', // "en" | "zh_CN" | "zh_TW"
createAt: new Date('2025-01-01'),
postsPerPage: 10,
banner: {
src/env.d.ts
@@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />
+/// <reference types="vite-plugin-pwa/client" />
+/// <reference types="vite-plugin-pwa/info" />
+/// <reference types="vite-plugin-pwa/pwa-assets" />
astro.config.mjs
@@ -1,4 +1,5 @@
// @ts-check
+import { siteConfig } from './src/config.ts';
import { CDN } from './src/constants/cdn.ts';
import { rehypeComponentsList } from './src/plugins/rehype-components-list.ts';
import { rehypePrettierCodes } from './src/plugins/rehype-prettier-codes.ts';
@@ -18,6 +19,7 @@ import vue from '@astrojs/vue';
// import { transformerNotationDiff } from '@shikijs/transformers';
// import { transformerNotationHighlight } from '@shikijs/transformers';
import tailwindcss from '@tailwindcss/vite';
+import AstroPWA from '@vite-pwa/astro';
import icon from 'astro-icon';
import pagefind from 'astro-pagefind';
import { defineConfig } from 'astro/config';
@@ -38,6 +40,27 @@ export default defineConfig({
icon(),
sitemap({ filter: (page) => !page.includes('/archives/') && !page.includes('/about/') }),
pagefind(),
+ AstroPWA({
+ manifest: {
+ name: siteConfig.title,
+ short_name: siteConfig.title,
+ description: siteConfig.subtitle,
+ lang: siteConfig.lang,
+ theme_color: '#4f94c9', // Should be the same as the primary color in src/styles/global.css
+ background_color: '#f2e8e0', // Should be the same as the base-100 color in src/styles/global.css
+ },
+ pwaAssets: {
+ config: true,
+ },
+ workbox: {
+ navigateFallback: '/',
+ globPatterns: ['**/*.{css,js,html,svg,png,ico,txt}'],
+ },
+ devOptions: {
+ enabled: true,
+ navigateFallbackAllowlist: [/^\/$/],
+ },
+ }),
mdx(),
vue(),
],
@@ -97,5 +120,10 @@ export default defineConfig({
},
vite: {
plugins: [tailwindcss()],
+ build: {
+ rollupOptions: {
+ external: ['workbox-window'],
+ },
+ },
},
});
package.json
@@ -20,8 +20,8 @@
"@astrojs/vue": "^5.0.10",
"@iconify-json/material-symbols": "^1.2.19",
"@iconify-json/mdi": "^1.2.3",
- "@iconify-json/simple-icons": "^1.2.3",
"@iconify-json/mingcute": "^1.2.3",
+ "@iconify-json/simple-icons": "^1.2.3",
"@iconify/utils": "^2.3.0",
"@octokit/request": "^9.2.3",
"@shikijs/transformers": "^3.2.2",
@@ -32,6 +32,8 @@
"@swup/scripts-plugin": "^2.1.0",
"@swup/scroll-plugin": "^3.3.2",
"@tailwindcss/vite": "^4.1.4",
+ "@vite-pwa/assets-generator": "^1.0.0",
+ "@vite-pwa/astro": "^1.0.1",
"astro": "^5.7.0",
"astro-compress": "2.3.5",
"astro-icon": "^1.1.5",
@@ -61,6 +63,7 @@
"tailwindcss": "^4.1.4",
"typescript": "^5.8.3",
"unist-util-visit": "^5.0.0",
+ "vite-plugin-pwa": "^1.0.0",
"vue": "^3.5.13"
},
"devDependencies": {
pwa-assets.config.ts
@@ -0,0 +1,28 @@
+import {
+ createAppleSplashScreens,
+ defineConfig,
+ minimal2023Preset,
+} from '@vite-pwa/assets-generator/config';
+
+export default defineConfig({
+ headLinkOptions: {
+ preset: '2023',
+ },
+ preset: {
+ ...minimal2023Preset,
+ appleSplashScreens: createAppleSplashScreens(
+ {
+ padding: 0.3,
+ resizeOptions: { fit: 'contain', background: 'white' },
+ darkResizeOptions: { fit: 'contain', background: 'black' },
+ linkMediaOptions: {
+ log: true,
+ addMediaScreen: true,
+ xhtml: true,
+ },
+ },
+ ['iPad Air 9.7"']
+ ),
+ },
+ images: 'public/favicon.svg',
+});