Reputation: 157
I want to convert my create react app typescript to ssr for serving dynamic meta tags so social medial crawlers can show preview. Has anyone done this, can share a sample code with all the config
this is my index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.hydrate(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
my server.ts
import express from "express";
import React from "react";
import {renderToString} from "react-dom/server";
import App from '../src/App'
import * as path from 'path';
import * as fs from 'fs'
import { getArticle } from "../src/api";
const app = express();
app.use(express.static("public"));
const PORT = process.env.PORT || 3006;
const indexPath = path.resolve(__dirname,'..','public','index.html')
const readIndexHtml = () => {
let response
fs.readFile(indexPath,'utf8',(err,html) => {
if(err) {
console.error('Error during file reading', err);
// return res.status(404).end()
throw err
}
response = html
})
return response
}
app.get('/',(req,res) => {
try {
let htmlData = readIndexHtml()
htmlData = (htmlData as string)
.replace('__META_OG_TITLE__', "title")
.replace('__META_OG_DESCRIPTION__', "description")
.replace('__META_DESCRIPTION__', "desc")
return res.send(htmlData);
} catch (error) {
console.log('erro while reading ' , error)
return res.status(404).end()
}
})
app.get('/article/:id', async(req,res) => {
let id = req.params.id
try {
let response = await getArticle(parseInt(id))
try {
let htmlData = readIndexHtml()
htmlData = (htmlData as string)
.replace('__META_OG_TITLE__', response.data['heading'])
.replace('__META_OG_DESCRIPTION__', response.data['shortDescription'])
.replace('__META_DESCRIPTION__', response.data['shortDescription'])
return res.send(htmlData);
} catch (error) {
console.log('erro while reading ' , error)
return res.status(404).end()
}
} catch (error) {
console.log('erro while fetching article ' , error)
return res.status(404).end()
}
})
app.listen(PORT, () => {
return console.log(`server is listening on ${PORT}`);
});
My Package.json
{
"name": "react-anoop-study",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"@types/jest": "^26.0.24",
"@types/node": "^12.20.15",
"@types/react": "^17.0.13",
"@types/react-dom": "^17.0.8",
"axios": "^0.21.1",
"jsx-runtime": "^1.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-toggle": "^4.1.2",
"typescript": "^4.3.5",
"web-vitals": "^1.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@types/node": "^12.20.26",
"@types/react": "^17.0.22",
"@types/react-helmet": "^6.1.2",
"@types/react-router-dom": "^5.1.8",
"@types/react-toggle": "^4.0.3"
}
}
What are the packages and configurations I need to add to make the dynamic changes possible
My project structure
├───public
├───server
└───src
├───api
├───components
│ ├───carousel
│ ├───flexboxtitle
│ └───paper
├───pages
│ ├───about
│ ├───article
│ └───carouseldemo
└───style
├───component
└───pages
Upvotes: 2
Views: 1052
Reputation: 120
Easiest way of doing this is by migrating to next.js https://nextjs.org/docs/migrating/from-create-react-app
Upvotes: 2