I'm using SSR to render a react component which should import an image. I've added:
declare module '*.ico' {
const value: any
export default value
}
Which works. Then when I try to do:
import Favicon from '/path/to/favicon.ico'
I get an error "SyntaxError: Invalid or unexpected token". I get this error even if I don't even attempt to use it, it breaks on the import itself:
SyntaxError: Invalid or unexpected token
at wrapSafe (internal/modules/cjs/loader.js:979:16)
at Module._compile (internal/modules/cjs/loader.js:1027:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
I'd ask how I can use it after that, but I'm stuck on how to even import it before I can try to utilise it.
Note that when rendering a single component server side, I don't want to rerun webpack or anything like that, thus how can I utilise an image with an import without using webpack?
I'm starting to believe the only way to accomplish this is to use fs.writeFile and manually set the static URL to the image source, but I was hoping there was a better approach; I suppose webpack handles everything behind the scenes.
EDIT: I thought I'd found a solution to this but still no luck.
You can have something like this, which can render a page:
export const component = async (
request: Request,
response: Response,
): Promise<void> => {
console.log(request.url)
const stream = renderToNodeStream(<Component />)
stream.pipe(response)
stream.on('end', () => {
response.end()
})
}
Just about every blog post and example on the internet stops there and says "ay okay, job done", but it's not, that's not even nearly half the story.
When you use the above along with:
import Favicon from '/path/to/favicon.ico'
It will break inside that component since typescript can't read any pictures, which makes reasonable. It will also break on any CSS or other non-reacting elements. That implies you can't reuse any client-side components and re-render them on the server if they contain any pictures, CSS, or other non-typescript/react elements.
You can use:
import webpack from 'webpack'
import config.js from './config'
...
const compiler = webpack(config('production'))
compiler.run((error, stats) => {
compiler.close()
})
It will break inside that component since typescript can't read any pictures, which makes reasonable. It will also break on any CSS or other non-reacting elements. That implies you can't reuse any client-side components and re-render them on the server if they contain any pictures, CSS, or other non-typescript/react elements.
You can't just use manually because your server and client code will be different, causing hydrate to complain, because webpack renders the images differently than you are manually doing. You also won't be able to reuse the same components with something like import Component from './component' because you'll have to duplicate your entire code base, once for webpack client and once for manually writing image paths.
So, how can you simply render an image using renderToString? I'm not sure how nobody has any information on this, no blog post, no discussion thread, no nothing?! Furthermore, why does everyone simply say, "Oh, just use renderToString and voila," when renderToString obviously does not work for images, CSS, or anything else?
Is there a puzzle piece I'm missing, or am I overlooking something obvious?