diff --git a/astro.config.mjs b/astro.config.mjs index 621c415998..5307dfca7b 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -8,6 +8,7 @@ import expressiveCode from "astro-expressive-code"; import icon from "astro-icon"; import { defineConfig } from "astro/config"; import rehypeAutolinkHeadings from "rehype-autolink-headings"; +import { fileURLToPath } from "url"; import rehypeComponents from "rehype-components"; /* Render the custom directive content */ import rehypeKatex from "rehype-katex"; import rehypeSlug from "rehype-slug"; @@ -29,6 +30,9 @@ export default defineConfig({ site: "https://fuwari.vercel.app/", base: "/", trailingSlash: "always", + build: { + inlineStylesheets: 'auto', + }, integrations: [ tailwind({ nesting: true, @@ -49,10 +53,37 @@ export default defineConfig({ }), icon({ include: { - "preprocess: vitePreprocess(),": ["*"], - "fa6-brands": ["*"], - "fa6-regular": ["*"], - "fa6-solid": ["*"], + "material-symbols": [ + "keyboard-arrow-up-rounded", + "home-outline-rounded", + "palette-outline", + "menu-rounded", + "calendar-today-outline-rounded", + "edit-calendar-outline-rounded", + "book-2-outline-rounded", + "tag-rounded", + "chevron-right-rounded", + "chevron-left-rounded", + "more-horiz", + "copyright-outline-rounded", + "notes-rounded", + "schedule-outline-rounded", + "search", + "wb-sunny-outline-rounded", + "dark-mode-outline-rounded", + "radio-button-partial-outline" + ], + "fa6-brands": [ + "creative-commons" + ], + "fa6-regular": [ + "address-card" + ], + "fa6-solid": [ + "arrow-up-right-from-square", + "arrow-rotate-left", + "chevron-right" + ], }, }), expressiveCode({ @@ -154,7 +185,36 @@ export default defineConfig({ ], }, vite: { + plugins: [ + { + name: 'block-iconify-json-imports', + enforce: 'pre', // Run before vite:json plugin + load(id) { + // Block ALL @iconify-json imports since manual addIcon() is used in preload-icons.ts + // This prevents bundling large JSON files and forces dynamic icons to use CDN + if (id.includes('@iconify-json')) { + if (id.endsWith('/icons.json')) { + return JSON.stringify({ + prefix: "", + icons: {}, + width: 24, + height: 24 + }); + } + if (id.endsWith('/info.json')) { + return JSON.stringify({ + name: "", + total: 0, + version: "1.0.0" + }); + } + } + } + } + ], build: { + minify: 'esbuild', + cssCodeSplit: true, rollupOptions: { onwarn(warning, warn) { // temporarily suppress this warning @@ -166,7 +226,53 @@ export default defineConfig({ } warn(warning); }, + output: { + manualChunks: (id) => { + // Vendor chunking for better caching and code splitting + if (id.includes('node_modules')) { + // Exclude icon JSON data from bundles - loaded from API instead + if (id.includes('@iconify-json') || id.includes('@iconify/json')) { + return undefined; + } + // Split heavy libraries into separate chunks + if (id.includes('photoswipe')) { + return 'vendor-photoswipe'; + } + if (id.includes('swup') || id.includes('@swup')) { + return 'vendor-swup'; + } + if (id.includes('overlayscrollbars')) { + return 'vendor-scrollbar'; + } + if (id.includes('@iconify/svelte')) { + return 'vendor-iconify'; + } + if (id.includes('astro-icon')) { + return 'vendor-icons'; + } + // Split Tailwind/CSS frameworks + if (id.includes('tailwindcss')) { + return 'vendor-tailwind'; + } + // Other vendor dependencies + return 'vendor'; + } + }, + // Optimize output with smaller chunks + chunkFileNames: '_astro/[name].[hash].js', + assetFileNames: '_astro/[name].[hash][extname]', + }, }, + // Enable aggressive tree-shaking + target: 'esnext', + }, + optimizeDeps: { + exclude: [ + '@iconify-json/material-symbols', + '@iconify-json/fa6-brands', + '@iconify-json/fa6-regular', + '@iconify-json/fa6-solid' + ] }, }, -}); +}); \ No newline at end of file diff --git a/scripts/get-icon-data.js b/scripts/get-icon-data.js new file mode 100644 index 0000000000..097a152b87 --- /dev/null +++ b/scripts/get-icon-data.js @@ -0,0 +1,49 @@ +#!/usr/bin/env node + +/** + * Helper script to get icon data from Iconify API + * Usage: node scripts/get-icon-data.js + * Example: node scripts/get-icon-data.js material-symbols:search + */ + +const iconName = process.argv[2]; + +if (!iconName) { + console.error('Usage: node scripts/get-icon-data.js '); + console.error('Example: node scripts/get-icon-data.js material-symbols:search'); + process.exit(1); +} + +const [prefix, name] = iconName.split(':'); + +if (!prefix || !name) { + console.error('Icon name must be in format: :'); + console.error('Example: material-symbols:search'); + process.exit(1); +} + +const url = `https://api.iconify.design/${prefix}.json?icons=${name}`; + +fetch(url) + .then(res => res.json()) + .then(data => { + const icon = data.icons[name]; + if (!icon) { + console.error(`Icon "${name}" not found in set "${prefix}"`); + process.exit(1); + } + + const width = icon.width || data.width || 24; + const height = icon.height || data.height || 24; + + console.log('\n// Add this to src/utils/preload-icons.ts:\n'); + console.log(`addIcon('${iconName}', {`); + console.log(`\tbody: '${icon.body}',`); + console.log(`\twidth: ${width},`); + console.log(`\theight: ${height},`); + console.log(`});\n`); + }) + .catch(error => { + console.error('Error fetching icon data:', error.message); + process.exit(1); + }); diff --git a/src/components/misc/BrandIcon.svelte b/src/components/misc/BrandIcon.svelte new file mode 100644 index 0000000000..51011b3ff4 --- /dev/null +++ b/src/components/misc/BrandIcon.svelte @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/components/widget/Profile.astro b/src/components/widget/Profile.astro index 22eddcacbd..169b35023d 100644 --- a/src/components/widget/Profile.astro +++ b/src/components/widget/Profile.astro @@ -1,5 +1,6 @@ --- import { Icon } from "astro-icon/components"; +import BrandIcon from "../misc/BrandIcon.svelte"; import { profileConfig } from "../../config"; import { url } from "../../utils/url-utils"; import ImageWrapper from "../misc/ImageWrapper.astro"; @@ -25,12 +26,12 @@ const config = profileConfig;
{config.links.length > 1 && config.links.map(item => - + )} {config.links.length == 1 && - + {config.links[0].name} }
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index c18052209c..6949eb7911 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -84,6 +84,10 @@ const bannerOffset = + + + + @@ -130,11 +134,12 @@ const bannerOffset = // Load the hue from local storage const hue = localStorage.getItem('hue') || configHue; - document.documentElement.style.setProperty('--hue', hue); // calculate the --banner-height-extend, which needs to be a multiple of 4 to avoid blurry text let offset = Math.floor(window.innerHeight * (BANNER_HEIGHT_EXTEND / 100)); offset = offset - offset % 4; + + document.documentElement.style.setProperty('--hue', hue); document.documentElement.style.setProperty('--banner-height-extend', `${offset}px`);