Last active
October 15, 2020 19:48
-
-
Save deckarts/9f44646704a5cbd4686ed0fa853c71ec to your computer and use it in GitHub Desktop.
Russ Jeffrey SSR & SEO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// React App.js | |
import React from 'react'; | |
import { Route, Switch, NavLink } from 'react-router-dom'; | |
import Home from './Home'; | |
import Posts from './Posts'; | |
export default props => { | |
return ( | |
<div> | |
<ul> | |
<li> | |
<NavLink to="/">Home</NavLink> | |
</li> | |
<li> | |
<NavLink to="/blog-posts">Blog Posts</NavLink> | |
</li> | |
</ul> | |
</div> | |
<Switch> | |
<Route | |
exact | |
path="/" | |
render={props => <Home name="example.com" {...props} />} | |
/> | |
<Route path="blog-posts" component={Posts} /> | |
</Switch> | |
); | |
}; | |
// React server.js | |
import React from 'react'; | |
import express from 'express'; | |
import ReactDOMServer from 'react-DOM/server'; | |
import { StaticRouter } from 'react-router-dom'; | |
// ...other imports and Express config | |
app.get('/*', (req, res) => { | |
const context = {}; | |
const app = ReactDOMServer.renderToString( | |
<StaticRouter location={req.url} context={context}> | |
<App /> | |
</StaticRouter> | |
); | |
const indexFile = path.resolve('./build/index.html'); | |
fs.readFile(indexFile, 'utf-8', (err, data) => { | |
if (err) { | |
console.error('Error reading indexFile for SSR page:', err); | |
return res.status(500).send('Error rendering page'); | |
} | |
return res.send( | |
data.replace('<div id="root"></div>', `<div id="root">${app}</div>`) | |
.replace('<title></title>', `<title>${context.title}</title>`) | |
.replace('<link rel="canonical" href="">', `<link rel="canonical" href="${req.protocol}://${req.host}/${req.path}">`) | |
... | |
); | |
}); | |
}); | |
app.listen(PORT, () => { | |
console.log(`Server is listening on port ${PORT}`); | |
}); | |
// React index.js | |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import { BrowserRouter } from 'react-router-dom'; | |
import App from './App'; | |
reactDOM.hydrate( | |
<BrowserRouter> | |
<App/> | |
</BrowserRouter>, | |
document.getElementById('root') | |
); | |
// Vue app.js | |
<html> | |
<head> | |
<title>{{ title }}</title> | |
{{{ meta }}} | |
</head> | |
<body> | |
<!--vue-ssr-outlet--> | |
</body> | |
</html> | |
// Vue server.js | |
const Vue = require('vue'); | |
const app = require('express')(); | |
const indexFile = require('fs').readFileSync('./index.template.html', 'utf-8'); | |
const renderer = require('vue-server-renderer').createRenderer({ | |
indexFile | |
}); | |
const context = { | |
title = 'Vue SSR', | |
metas = ` | |
<meta name="description" content="vue ssr demo"> | |
<meta property="og:image" content="https://example.com/image.jpg" /> | |
`, | |
}; | |
app.get('/*', (req, res) { | |
const vueApp = new Vue({ | |
data: { | |
url: req.url | |
}, | |
template: `<div>The visited URL is: {{ url }}</div>`, | |
}); | |
renderer | |
.renderToString(vueApp, context, (err, html) => { | |
if (err) { | |
res.status(500).end('Internal Server Error') | |
return | |
} | |
res.end.(html); | |
}); | |
}) | |
app.listen(PORT, () => { | |
console.log(`Server is listening on port ${PORT}`); | |
}); | |
// Vue index.js | |
import Vue from 'vue'; | |
const app = new Vue({ | |
data: { | |
... | |
}, | |
template: ".." | |
}) | |
app.$mount('#app') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment