У меня есть стандартное приложение TypeScript React, созданное с использованием CRA.
Оно использует шлем для метаданных и стилевые компоненты для стиля.
В настоящее время я использую Babel и express для обслуживания приложение. Большинство вещей работают нормально, но импортированные графические ресурсы не работают в режиме SSR.
Например, import sun from "../images/sun.jpg"
отображается как [object Object]
вместо data:image/jpeg;base64,...
и import backgroundS from "../images/background-1280x720.jpg"
как [object Object]
вместо /static/media/background-1280x720.702f9ac6.jpg
.
import sun from "../images/sun.jpg"
const ImageComponent = () => (
<img src={sun} /> // In SSR mode, this is rendered as <img src="[object Object]">
)
Я только начинаю работать с React SSR, поэтому мне, вероятно, не хватает нескольких ключевых знаний, чтобы понять это. Я потратил более двух часов, пытаясь найти решение.
Что мне не хватает?
index. js
"use strict"
require("ignore-styles")
require("@babel/register")({
ignore: [/(node_modules)/],
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
extensions: [".tsx"],
cache: false,
})
require("./server")
server. js
"use strict"
const dotenv = require("dotenv").config()
const express = require("express")
const path = require("path")
const fs = require("fs")
const renderToString = require("react-dom/server").renderToString
const React = require("react")
const Helmet = require("react-helmet").default
const ServerStyleSheet = require("styled-components").ServerStyleSheet
const StaticRouter = require("./src/routers/Static").default
const indexPath = path.join(__dirname, "build/index.html")
const server = express()
server.disable("x-powered-by")
const middleware = async (req, res, next) => {
const sheet = new ServerStyleSheet()
let context = {}
let html = renderToString(
sheet.collectStyles(
React.createElement(StaticRouter, {
location: req.url,
context: context,
})
)
)
const helmet = Helmet.renderStatic()
const styleTags = sheet.getStyleTags()
if (context.url) {
res.redirect(context.url)
} else if (!fs.existsSync(indexPath)) {
next("Site is updating... please reload page in a few minutes.")
} else {
let index = fs.readFileSync(indexPath, "utf8")
let status = 200
if (typeof context.status === "number") {
status = context.status
}
return res.status(status).send(
index
.replace('<div id="root"></div>', `<div id="root">${html}</div>`)
.replace("</head>", `${helmet.meta.toString()}</head>`)
.replace("</head>", `${helmet.title.toString()}</head>`)
.replace("</head>", `${helmet.script.toString()}</head>`)
.replace("</head>", `${styleTags}</head>`)
)
}
}
// This line is required by SSR
server.get("/", middleware)
server.use(express.static(path.join(__dirname, "build")))
server.get("*", middleware)
server.listen(process.env.PORT, function() {
console.log(`Server listening on port ${process.env.PORT}`)
})