title: How to use static media assets generated by CRA’s npm build in SSR mode?
body: <p>I have a standard TypeScript React app created using CRA.</p>
  
  <p>It uses Helmet for metadata and styled-components for styling.</p>
  
  <p>I am currently using Babel and express to serve the app. Most things work fine, but imported image assets do not work in SSR mode.</p>
  
  <p>For example, <code>import sun from "../images/sun.jpg"</code> is rendered as <code>[object Object]</code> instead of <code>data:image/jpeg;base64,...</code> and <code>import backgroundS from "../images/background-1280x720.jpg"</code> as <code>[object Object]</code> instead of <code>/static/media/background-1280x720.702f9ac6.jpg</code>.</p>
  
  <pre><code>import sun from "../images/sun.jpg"
  
  const ImageComponent = () =&gt; (
    &lt;img src={sun} /&gt; // In SSR mode, this is rendered as &lt;img src="[object Object]"&gt;
  )
  </code></pre>
  
  <p>I am just getting started with React SSR so I am probably missing a few key pieces of knowledge to figure this out. I spend more than two hours trying to find a solution.</p>
  
  <p>What am I missing?</p>
  
  <h1>index.js</h1>
  
  <pre class="lang-js prettyprint-override"><code>"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")
  
  </code></pre>
  
  <h1>server.js</h1>
  
  <pre class="lang-js prettyprint-override"><code>"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) =&gt; {
    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('&lt;div id="root"&gt;&lt;/div&gt;', `&lt;div id="root"&gt;${html}&lt;/div&gt;`)
          .replace("&lt;/head&gt;", `${helmet.meta.toString()}&lt;/head&gt;`)
          .replace("&lt;/head&gt;", `${helmet.title.toString()}&lt;/head&gt;`)
          .replace("&lt;/head&gt;", `${helmet.script.toString()}&lt;/head&gt;`)
          .replace("&lt;/head&gt;", `${styleTags}&lt;/head&gt;`)
      )
    }
  }
  
  // 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}`)
  })
  </code></pre>