Недавно мне было поручено изучить жизнеспособность использования Remix в качестве инструмента для EvidencCare, и одна из вещей, которая стала совершенно очевидной, — это отсутствие способа включения Styled Components из-за ряда факторов.
Некоторые решения требовали от вас изменения функции handleDataRequest
или файла entry.client.js
, но их не было. Даже в Документации по ремиксам упоминаются открытые проблемы Github, что приводит к еще большему количеству открытых проблем для React SSR. Другие предложенные решения включали рендеринг приложения в div и даже зашли так далеко, что создали пакеты Node, чтобы облегчить это, но лидеры сообщества React в дальнейшем отвергли их как хорошие. Некоторые даже поддерживают изменение процесса сборки. Даже документы Styled Component были слишком универсальными.
Итак, вот что у меня работало на момент написания этой статьи:
Вот server.js
, как он начинается, когда вы инициализируете новый проект:
import { createRequestHandler } from "@remix-run/architect"; import * as build from "@remix-run/dev/server-build"; export const handler = createRequestHandler({ build, mode: process.env.NODE_ENV, });
Я использовал Typescript, чтобы выяснить, как вручную добавить это значение build
, чтобы я мог получить доступ к этой функции handleDocumentRequest
, на которую ссылаются некоторые учебные пособия, и фактически реализовать часть решения:
import { createRequestHandler } from "@remix-run/architect"; import * as build from "@remix-run/dev/server-build"; import { ServerStyleSheet } from "styled-components"; import { renderToString } from "react-dom/server"; import { RemixServer } from "@remix-run/react"; function handleDocumentRequest( request, responseStatusCode, responseHeaders, remixContext ) { const sheet = new ServerStyleSheet(); let markup = renderToString( sheet.collectStyles( <RemixServer context={remixContext} url={request.url} /> ) ); const styles = sheet.getStyleTags(); markup = markup.replace("__STYLES__", styles); responseHeaders.set("Content-Type", "text/html"); return new Response("<!DOCTYPE html>" + markup, { status: responseStatusCode, headers: responseHeaders, }); } export const handler = createRequestHandler({ build: { routes: build.routes, entry: { module: { default: handleDocumentRequest, handleDataRequest: build.entry.module.handleDataRequest } }, assets: build.assets, dev: {liveReloadPort: build.dev?.liveReloadPort}, future: build.future, publicPath: build.publicPath, assetsBuildDirectory: build.assetsBuildDirectory }, mode: process.env.NODE_ENV, });
Мой файл root.tsx
также добавил эту строку-заполнитель:
import type {LinksFunction, MetaFunction} from "@remix-run/node"; import { Links, Meta, Outlet, Scripts, ScrollRestoration, } from "@remix-run/react"; import stylesheet from "~/tailwind.css"; export const links: LinksFunction = () => [ { rel: "stylesheet", href: stylesheet }, ]; export const meta: MetaFunction = () => ({ charset: "utf-8", title: "New Remix App", viewport: "width=device-width,initial-scale=1", }); export default function App() { return ( <html lang="en"> <head> <Meta /> <Links /> {typeof document === "undefined" ? "__STYLES__" : null} </head> <body> <Outlet /> <ScrollRestoration /> <Scripts /> {/*// https://github.com/remix-run/remix/issues/198*/} {/*<LiveReload />*/} </body> </html> ); }
Это «технически» работает. Однако известная проблема гидратации приводит к тому, что режим SPA включается во время разработки, что не позволяет ему работать для локальной разработки. Чтобы исправить это, я просто живу без перезагрузки в реальном времени, и почему вы видите, что это закомментировано. Браузер просто перезагрузится при изменении кода. Это не так идеально, но со временем это будет исправлено.
С помощью этих шагов Styled Components работает в Remix.