From 40d411e516efee5531404725b45ab89d97172ce8 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 28 Oct 2022 00:14:01 +0300 Subject: Initial SSR --- vnext/server/bootstrap.js | 11 +++++++++ vnext/server/index.js | 32 +++++++++++++++++++++++++ vnext/server/middleware/renderer.js | 48 +++++++++++++++++++++++++++++++++++++ vnext/server/sape.js | 38 +++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 vnext/server/bootstrap.js create mode 100644 vnext/server/index.js create mode 100644 vnext/server/middleware/renderer.js create mode 100644 vnext/server/sape.js (limited to 'vnext/server') diff --git a/vnext/server/bootstrap.js b/vnext/server/bootstrap.js new file mode 100644 index 00000000..0f920886 --- /dev/null +++ b/vnext/server/bootstrap.js @@ -0,0 +1,11 @@ +require('ignore-styles'); +require('url-loader'); +require('file-loader'); +require('@babel/register')({ + ignore: [/(node_modules)/], + presets: [ + '@babel/preset-env', + ['@babel/preset-react', { 'runtime': 'automatic' }] + ] +}); +require('./index'); diff --git a/vnext/server/index.js b/vnext/server/index.js new file mode 100644 index 00000000..2b696977 --- /dev/null +++ b/vnext/server/index.js @@ -0,0 +1,32 @@ +import express from 'express'; + +// we'll talk about this in a minute: +import serverRenderer from './middleware/renderer'; + +const PORT = 3000; +const path = require('path'); + +// initialize the application and create the routes +const app = express(); +const router = express.Router(); + +router.use('^/$', serverRenderer); + +// other static resources should just be served as they are +router.use(express.static( + path.resolve(__dirname, '..', 'dist'), + { maxAge: '30d' }, +)); + +router.use('*', serverRenderer); + +app.use(router); + +// start the app +app.listen(PORT, (error) => { + if (error) { + return console.log('something bad happened', error); + } + + console.log('listening on ' + PORT + '...'); +}); diff --git a/vnext/server/middleware/renderer.js b/vnext/server/middleware/renderer.js new file mode 100644 index 00000000..8edb5f57 --- /dev/null +++ b/vnext/server/middleware/renderer.js @@ -0,0 +1,48 @@ +import ReactDOMServer from 'react-dom/server'; +import cookie from 'cookie'; + +// import our main App component +import App from '../../src/App'; + +import { getLinks } from '../sape'; +import { StaticRouter } from 'react-router-dom'; + +const path = require('path'); +const fs = require('fs'); + +const serverRenderer = async (req, res, next) => { + + // point to the html file created by CRA's build tool + const filePath = path.resolve(__dirname, '..', '..', 'dist', 'index.html'); + + // links + const cookies = cookie.parse(req.headers.cookie || ''); + + const links = await getLinks(req.originalUrl, cookies['sape_cookie']); + console.log(`URL: ${req.originalUrl} LINKS: ${links.join(' ')}`); + fs.readFile(filePath, 'utf8', (err, htmlData) => { + if (err) { + console.error('err', err); + return res.status(404).end(); + } + + const routerContext = {}; + + // render the app as a string + const html = ReactDOMServer.renderToString( + + + + ); + + // inject the rendered app into our html and send it + return res.send( + htmlData.replace( + '
', + `
${html}
` + ) + ); + }); +}; + +export default serverRenderer; diff --git a/vnext/server/sape.js b/vnext/server/sape.js new file mode 100644 index 00000000..d8c9e2ed --- /dev/null +++ b/vnext/server/sape.js @@ -0,0 +1,38 @@ +import { parseStringPromise } from 'xml2js'; +import axios from 'axios'; +import { setupCache } from 'axios-cache-interceptor'; + +const token = process.env.SAPE_TOKEN; + +/** @external Promise */ + +/** + * @param { string } uri + * @param { string } sapeCookie + * @returns { Promise} links + */ +export const getLinks = async (uri, sapeCookie) => { + if (!token) { + console.warn('Sape is not configured'); + return []; + } + const response = await sape.get(`http://dispencer-01.sape.ru/code.php?user=${token}&host=juick.com&charset=UTF-8&as_xml=true`); + const data = await parseStringPromise(response.data); + const showCode = token === sapeCookie; + const requestURI = showCode ? '*' : uri; + const page = data.sape.page.filter(page => { + const uri = page['$']['uri']; + return uri === requestURI; + }); + return page.length > 0 ? showCode ? [page[0]._] : page[0].link : []; +}; + +/** @type { import('axios-cache-interceptor').AxiosCacheInstance } */ +let sape = setupCache( + axios.create({ + headers: { + 'User-Agent': 'SAPE_Client PHP 1.0.3' + } + }), + { ttl: 3600 * 1000 } +); -- cgit v1.2.3