diff --git a/.github/assets/nginx.conf b/.github/assets/nginx.conf index f9d8e412d..a163a4735 100644 --- a/.github/assets/nginx.conf +++ b/.github/assets/nginx.conf @@ -6,7 +6,8 @@ server { index index.html; location / { - try_files $uri $uri/ /index.html; + try_files $uri $uri.html $uri/ =404; + add_header X-Frame-Options "DENY"; add_header X-Content-Type-Options "nosniff"; add_header X-XSS-Protection "1; mode=block"; @@ -26,4 +27,4 @@ gzip on; gzip_types text/plain text/css application/javascript application/json image/svg+xml; gzip_min_length 1000; gzip_proxied any; -gzip_vary on; \ No newline at end of file +gzip_vary on; diff --git a/Dockerfile b/Dockerfile index 4feee9d47..0ca7b6423 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,17 @@ -FROM node:25.7-slim AS base +FROM node:25.7-alpine AS base ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN npm install -g pnpm@10.30.3 WORKDIR /app COPY package.json pnpm-lock.yaml ./ -FROM base AS prod-deps -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --config.autoInstallPeers=false - FROM base AS build RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --config.autoInstallPeers=false COPY . . RUN pnpm run docs:build -FROM base -ENV NODE_ENV=production -COPY --from=prod-deps /app/node_modules /app/node_modules -COPY --from=build /app/docs/.vitepress/dist /app/docs/.vitepress/dist - -EXPOSE 4173 -CMD ["pnpm", "docs:preview"] +FROM nginx:alpine-slim +COPY --from=build /app/docs/.vitepress/dist /usr/share/nginx/html +COPY .github/assets/nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/docs/.vitepress/hooks/meta.ts b/docs/.vitepress/hooks/meta.ts index be455b25c..92c672ca8 100644 --- a/docs/.vitepress/hooks/meta.ts +++ b/docs/.vitepress/hooks/meta.ts @@ -70,14 +70,14 @@ export function generateMeta(context: TransformContext, hostname: string) { ]) } else { const url = pageData.filePath.replace('index.md', '').replace('.md', '') - const imageUrl = `${url}/__og_image__/og.png` + const imageUrl = `${url}/__og_image__/og.webp` .replaceAll('//', '/') .replace(/^\//, '') head.push( ['meta', { property: 'og:image', content: `${hostname}/${imageUrl}` }], ['meta', { property: 'og:image:width', content: '1200' }], - ['meta', { property: 'og:image:height', content: '628' }], + ['meta', { property: 'og:image:height', content: '630' }], ['meta', { property: 'og:image:type', content: 'image/png' }], [ 'meta', @@ -85,7 +85,7 @@ export function generateMeta(context: TransformContext, hostname: string) { ], ['meta', { name: 'twitter:image', content: `${hostname}/${imageUrl}` }], ['meta', { name: 'twitter:image:width', content: '1200' }], - ['meta', { name: 'twitter:image:height', content: '628' }], + ['meta', { name: 'twitter:image:height', content: '630' }], [ 'meta', { name: 'twitter:image:alt', content: pageData.frontmatter.title } diff --git a/docs/.vitepress/hooks/opengraph.ts b/docs/.vitepress/hooks/opengraph.ts index 3bbd78417..e15330aa1 100644 --- a/docs/.vitepress/hooks/opengraph.ts +++ b/docs/.vitepress/hooks/opengraph.ts @@ -20,6 +20,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises' import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { renderAsync } from '@resvg/resvg-js' +import sharp from 'sharp' import consola from 'consola' import { createContentLoader } from 'vitepress' import { satoriVue } from 'x-satori/vue' @@ -102,8 +103,8 @@ async function generateImage({ // consola.info(url, title, description) const options: SatoriOptions = { - width: 1800, - height: 900, + width: 1200, + height: 630, fonts, props: { title, @@ -116,12 +117,16 @@ async function generateImage({ const render = await renderAsync(svg) + const compressed = await sharp(render.asPng()) + .webp({ quality: 75 }) + .toBuffer() + const outputFolder = resolve(outDir, url.slice(1), '__og_image__') - const outputFile = resolve(outputFolder, 'og.png') + const outputFile = resolve(outputFolder, 'og.webp') await mkdir(outputFolder, { recursive: true }) - await writeFile(outputFile, render.asPng()) + await writeFile(outputFile, compressed) } function getPage(page: string) { diff --git a/package.json b/package.json index 273cd9d09..0d266b88b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "nprogress": "^0.2.0", "pathe": "^2.0.3", "reka-ui": "^2.9.0", + "sharp": "^0.34.5", "unocss": "66.6.4", "vitepress": "^1.6.4", "vue": "^3.5.29", @@ -43,7 +44,7 @@ "zod": "^4.3.6" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20251202.0", + "@cloudflare/workers-types": "^4.20260305.1", "@ianvs/prettier-plugin-sort-imports": "^4.7.1", "@iconify-json/carbon": "^1.2.19", "@iconify-json/fluent": "^1.2.40", @@ -73,7 +74,7 @@ "vite-plugin-optimize-exclude": "^0.0.1", "vite-plugin-pwa": "^1.2.0", "vite-plugin-terminal": "^1.4.0", - "wrangler": "^4.52.1" + "wrangler": "^4.70.0" }, "pnpm": { "peerDependencyRules": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a3498bbc..c3bae2591 100644 Binary files a/pnpm-lock.yaml and b/pnpm-lock.yaml differ