diff --git a/.github/workflows/create_heroku_review_app.yaml b/.github/workflows/create_heroku_review_app.yaml index 61605fb65..7e3ade03a 100644 --- a/.github/workflows/create_heroku_review_app.yaml +++ b/.github/workflows/create_heroku_review_app.yaml @@ -7,7 +7,7 @@ jobs: create-review-app: runs-on: ubuntu-latest steps: - - uses: fastruby/manage-heroku-review-app@9fa49f0320460f278c3687bc348dd0cbb18555dc # v1.3 + - uses: kqito/manage-heroku-review-app@55e434ad5ac86f21cf2f7654de1566973fbc7046 with: action: create env: diff --git a/.github/workflows/destroy_heroku_review_app.yaml b/.github/workflows/destroy_heroku_review_app.yaml index b2bf67949..cbcec744a 100644 --- a/.github/workflows/destroy_heroku_review_app.yaml +++ b/.github/workflows/destroy_heroku_review_app.yaml @@ -7,7 +7,7 @@ jobs: destroy-review-app: runs-on: ubuntu-latest steps: - - uses: fastruby/manage-heroku-review-app@9fa49f0320460f278c3687bc348dd0cbb18555dc # v1.3 + - uses: kqito/manage-heroku-review-app@55e434ad5ac86f21cf2f7654de1566973fbc7046 with: action: destroy env: diff --git a/workspaces/client/src/features/recommended/components/EpisodeItem.tsx b/workspaces/client/src/features/recommended/components/EpisodeItem.tsx index 74b08745c..d79d0a16b 100644 --- a/workspaces/client/src/features/recommended/components/EpisodeItem.tsx +++ b/workspaces/client/src/features/recommended/components/EpisodeItem.tsx @@ -3,6 +3,7 @@ import { Flipped } from 'react-flip-toolkit'; import { NavLink } from 'react-router'; import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; +import { removeVersionQuery } from '@wsh-2025/client/src/utils/remove-version-query'; interface Props { episode: { @@ -25,7 +26,7 @@ export const EpisodeItem = ({ episode }: Props) => { <>
- + {episode.premium ? ( diff --git a/workspaces/client/src/features/recommended/components/SeriesItem.tsx b/workspaces/client/src/features/recommended/components/SeriesItem.tsx index 2477b7a97..9b0732c0d 100644 --- a/workspaces/client/src/features/recommended/components/SeriesItem.tsx +++ b/workspaces/client/src/features/recommended/components/SeriesItem.tsx @@ -3,6 +3,7 @@ import { Flipped } from 'react-flip-toolkit'; import { NavLink } from 'react-router'; import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; +import { removeVersionQuery } from '@wsh-2025/client/src/utils/remove-version-query'; interface Props { series: { @@ -21,7 +22,7 @@ export const SeriesItem = ({ series }: Props) => { <>
- +
diff --git a/workspaces/client/src/main.tsx b/workspaces/client/src/main.tsx index 601b7a6a5..d1a53b942 100644 --- a/workspaces/client/src/main.tsx +++ b/workspaces/client/src/main.tsx @@ -17,7 +17,9 @@ declare global { function main() { const store = createStore({}); - const router = createBrowserRouter(createRoutes(store), {}); + const router = createBrowserRouter(createRoutes(store), { + hydrationData: window.__staticRouterHydrationData, + }); hydrateRoot( document, diff --git a/workspaces/client/src/pages/home/components/HomePage.tsx b/workspaces/client/src/pages/home/components/HomePage.tsx index 86cb77e6c..dc8c891c5 100644 --- a/workspaces/client/src/pages/home/components/HomePage.tsx +++ b/workspaces/client/src/pages/home/components/HomePage.tsx @@ -1,6 +1,6 @@ import { createStore } from '@wsh-2025/client/src/app/createStore'; import { RecommendedSection } from '@wsh-2025/client/src/features/recommended/components/RecommendedSection'; -import { useRecommended } from '@wsh-2025/client/src/features/recommended/hooks/useRecommended'; +import { useLoaderData } from 'react-router'; export const prefetch = async (store: ReturnType) => { const modules = await store @@ -10,7 +10,7 @@ export const prefetch = async (store: ReturnType) => { }; export const HomePage = () => { - const modules = useRecommended({ referenceId: 'entrance' }); + const { modules } = useLoaderData>>(); return ( <> diff --git a/workspaces/client/src/utils/remove-version-query.ts b/workspaces/client/src/utils/remove-version-query.ts new file mode 100644 index 000000000..f4f678912 --- /dev/null +++ b/workspaces/client/src/utils/remove-version-query.ts @@ -0,0 +1,4 @@ +// ?version= のクエリを削除する +export const removeVersionQuery = (url: string) => { + return url.replace(/\?version=[^&]+/, ''); +}; diff --git a/workspaces/client/webpack.config.mjs b/workspaces/client/webpack.config.mjs index 9164a996e..a90d0fddc 100644 --- a/workspaces/client/webpack.config.mjs +++ b/workspaces/client/webpack.config.mjs @@ -4,7 +4,6 @@ import webpack from 'webpack'; /** @type {import('webpack').Configuration} */ const config = { - devtool: 'inline-source-map', entry: './src/main.tsx', mode: 'none', module: { diff --git a/workspaces/server/src/index.ts b/workspaces/server/src/index.ts index e02ab7613..c3401fe27 100644 --- a/workspaces/server/src/index.ts +++ b/workspaces/server/src/index.ts @@ -13,8 +13,14 @@ async function main() { const app = fastify(); + // 画像のみキャッシュする app.addHook('onSend', async (_req, reply) => { - reply.header('cache-control', 'no-store'); + const contentType = reply.getHeader('Content-Type'); + if (reply.statusCode === 200 && typeof contentType === 'string' && contentType.startsWith('image/')) { + reply.header('Cache-Control', 'public, max-age=31536000'); + } else { + reply.header('Cache-Control', 'no-store'); + } }); app.register(cors, { origin: true, diff --git a/workspaces/server/src/ssr.tsx b/workspaces/server/src/ssr.tsx index 7603aafdd..bd2cc599c 100644 --- a/workspaces/server/src/ssr.tsx +++ b/workspaces/server/src/ssr.tsx @@ -1,4 +1,3 @@ -import { readdirSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -8,23 +7,10 @@ import { createRoutes } from '@wsh-2025/client/src/app/createRoutes'; import { createStore } from '@wsh-2025/client/src/app/createStore'; import type { FastifyInstance } from 'fastify'; import { createStandardRequest } from 'fastify-standard-request-reply'; -import htmlescape from 'htmlescape'; import { StrictMode } from 'react'; import { renderToString } from 'react-dom/server'; import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router'; -function getFiles(parent: string): string[] { - const dirents = readdirSync(parent, { withFileTypes: true }); - return dirents - .filter((dirent) => dirent.isFile() && !dirent.name.startsWith('.')) - .map((dirent) => path.join(parent, dirent.name)); -} - -function getFilePaths(relativePath: string, rootDir: string): string[] { - const files = getFiles(path.resolve(rootDir, relativePath)); - return files.map((file) => path.join('/', path.relative(rootDir, file))); -} - export function registerSsr(app: FastifyInstance): void { app.register(fastifyStatic, { prefix: '/public/', @@ -51,7 +37,7 @@ export function registerSsr(app: FastifyInstance): void { } const router = createStaticRouter(handler.dataRoutes, context); - renderToString( + const html = renderToString( store}> @@ -59,30 +45,8 @@ export function registerSsr(app: FastifyInstance): void { , ); - const rootDir = path.resolve(__dirname, '../../../'); - const imagePaths = [ - getFilePaths('public/images', rootDir), - getFilePaths('public/animations', rootDir), - getFilePaths('public/logos', rootDir), - ].flat(); - reply.type('text/html').send(/* html */ ` - - - - - - - ${imagePaths.map((imagePath) => ``).join('\n')} - - - - + ${html} `); }); }