stop using React for server-side-rendering
This commit is contained in:
parent
abeeccda88
commit
2575e54ba0
|
@ -25,7 +25,7 @@ import change_mail from './change_mail';
|
|||
// eslint-disable-next-line camelcase
|
||||
import restore_password from './restore_password';
|
||||
|
||||
import getHtml from '../../../ssr-components/RedirectionPage';
|
||||
import getHtml from '../../../ssr/RedirectionPage';
|
||||
|
||||
import getMe from '../../../core/me';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import socketEvents from '../../../socket/SocketEvents';
|
||||
import getHtml from '../../../ssr-components/RedirectionPage';
|
||||
import getHtml from '../../../ssr/RedirectionPage';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
import mailProvider from '../../../core/mail';
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import api from './api';
|
|||
|
||||
import assets from './assets.json'; // eslint-disable-line import/no-unresolved
|
||||
import { expressTTag } from '../core/ttag';
|
||||
import generateGlobePage from '../ssr-components/Globe';
|
||||
import generateMainPage from '../ssr-components/Main';
|
||||
import generateGlobePage from '../ssr/Globe';
|
||||
import generateMainPage from '../ssr/Main';
|
||||
|
||||
import { MONTH } from '../core/constants';
|
||||
import { GUILDED_INVITE } from '../core/config';
|
||||
|
|
|
@ -9,7 +9,7 @@ import express from 'express';
|
|||
import type { Request, Response } from 'express';
|
||||
|
||||
import logger from '../core/logger';
|
||||
import getPasswordResetHtml from '../ssr-components/PasswordReset';
|
||||
import getPasswordResetHtml from '../ssr/PasswordReset';
|
||||
|
||||
import mailProvider from '../core/mail';
|
||||
import { RegUser } from '../data/sql';
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* react html for 3D globe page
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
import Html from './Html';
|
||||
/* this will be set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
import { ASSET_SERVER } from '../core/config';
|
||||
|
||||
import globeCss from '../styles/globe.css';
|
||||
|
||||
const styles = [{
|
||||
id: 'globe',
|
||||
cssText: globeCss,
|
||||
}];
|
||||
|
||||
const defaultScripts = assets.globe.js.map(
|
||||
(s) => ASSET_SERVER + s,
|
||||
);
|
||||
|
||||
/*
|
||||
* generates string with html of globe page
|
||||
* @param lang language code
|
||||
* @return html of mainpage
|
||||
*/
|
||||
function generateGlobePage(lang: string): string {
|
||||
const scripts = (assets[`globe-${lang}`])
|
||||
? assets[`globe-${lang}`].js.map((s) => ASSET_SERVER + s)
|
||||
: defaultScripts;
|
||||
|
||||
const { t } = getTTag(lang);
|
||||
const Globe = () => (
|
||||
<div>
|
||||
<div id="webgl" />
|
||||
<div id="coorbox">(0, 0)</div>
|
||||
<div id="info">{t`Double click on globe to go back.`}</div>
|
||||
<div id="loading">{t`Loading...`}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const html = ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
title={t`PixelPlanet.Fun 3DGlobe`}
|
||||
description={t`A 3D globe of our whole map`}
|
||||
scripts={scripts}
|
||||
body={<Globe />}
|
||||
styles={styles}
|
||||
/>,
|
||||
);
|
||||
|
||||
return `<!doctype html>${html}`;
|
||||
}
|
||||
|
||||
export default generateGlobePage;
|
|
@ -1,70 +0,0 @@
|
|||
/* @flow */
|
||||
/**
|
||||
* React Starter Kit (https://www.reactstarterkit.com/)
|
||||
*
|
||||
* Copyright © 2014-present Kriasoft, LLC. All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const Html = ({
|
||||
title,
|
||||
description,
|
||||
body,
|
||||
// array of css stylesheet urls
|
||||
css,
|
||||
// array of script urls
|
||||
scripts,
|
||||
// style as string
|
||||
styles,
|
||||
// code as string
|
||||
code,
|
||||
}) => (
|
||||
<html className="no-js" lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
{styles && styles.map((style) => (
|
||||
<style
|
||||
key={style.id}
|
||||
id={style.id}
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: style.cssText }}
|
||||
/>
|
||||
))}
|
||||
{code && (
|
||||
<script
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: code }}
|
||||
/>
|
||||
)}
|
||||
{css && css.map((stylesheet) => (
|
||||
<link rel="stylesheet" type="text/css" id={stylesheet.id} href={stylesheet.uri} />
|
||||
))}
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
{body}
|
||||
</div>
|
||||
{scripts && scripts.map((script) => <script key={script} src={script} />)}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
|
||||
export default Html;
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Html for mainpage
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
|
||||
import { langCodeToCC } from '../utils/location';
|
||||
import ttags, { getTTag } from '../core/ttag';
|
||||
import Html from './Html';
|
||||
/* this one is set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import styleassets from './styleassets.json';
|
||||
|
||||
import { ASSET_SERVER, BACKUP_URL } from '../core/config';
|
||||
|
||||
/*
|
||||
* generate language list
|
||||
*/
|
||||
const langs = Object.keys(ttags)
|
||||
.map((l) => (l === 'default' ? 'en' : l))
|
||||
.map((l) => [l, langCodeToCC(l)]);
|
||||
|
||||
/*
|
||||
* values that we pass to client scripts
|
||||
*/
|
||||
const ssv = {
|
||||
assetserver: ASSET_SERVER,
|
||||
availableStyles: styleassets,
|
||||
langs,
|
||||
};
|
||||
if (BACKUP_URL) {
|
||||
ssv.backupurl = BACKUP_URL;
|
||||
}
|
||||
|
||||
const defaultScripts = assets.client.js.map(
|
||||
(s) => ASSET_SERVER + s,
|
||||
);
|
||||
const css = [
|
||||
{
|
||||
id: 'globcss',
|
||||
uri: styleassets.default,
|
||||
},
|
||||
];
|
||||
|
||||
/*
|
||||
* Generates string with html of main page
|
||||
* @param countryCoords Cell with coordinates of client country
|
||||
* @param lang language code
|
||||
* @return html of mainpage
|
||||
*/
|
||||
function generateMainPage(lang: string): string {
|
||||
const ssvR = {
|
||||
...ssv,
|
||||
lang: lang === 'default' ? 'en' : lang,
|
||||
};
|
||||
const scripts = (assets[`client-${lang}`])
|
||||
? assets[`client-${lang}`].js.map((s) => ASSET_SERVER + s)
|
||||
: defaultScripts;
|
||||
const { t } = getTTag(lang);
|
||||
// eslint-disable-next-line
|
||||
const html = ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
title={t`PixelPlanet.fun`}
|
||||
// eslint-disable-next-line max-len
|
||||
description={t`Place color pixels on an map styled canvas with other players online`}
|
||||
scripts={scripts}
|
||||
css={css}
|
||||
// eslint-disable-next-line max-len
|
||||
code={`window.ssv=JSON.parse('${JSON.stringify(ssvR)}');`}
|
||||
/>,
|
||||
);
|
||||
|
||||
return `<!doctype html>${html}`;
|
||||
}
|
||||
|
||||
export default generateMainPage;
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Make basic reset_password forms
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
import Html from './Html';
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
export default function getPasswordResetHtml(name, code, lang, message = null) {
|
||||
const { t } = getTTag(lang);
|
||||
|
||||
let body = '';
|
||||
|
||||
if (message) {
|
||||
body = (
|
||||
<div>
|
||||
<h3>{t`Reset Password`}</h3>
|
||||
<p>{message}</p>
|
||||
<p><a href="./">{t`Click here`}</a>
|
||||
{t`to go back to pixelplanet`}</p>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
body = (
|
||||
<form method="post" action="reset_password">
|
||||
<h3>{t`Reset Password`}</h3>
|
||||
<p>{t`Hello ${name}, you can set your new password here:`}</p>
|
||||
<input
|
||||
type="password"
|
||||
name="pass"
|
||||
placeholder={t`New Password`}
|
||||
style={{
|
||||
maxWidth: '35em',
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="passconf"
|
||||
placeholder={t`Confirm New Password`}
|
||||
style={{
|
||||
maxWidth: '35em',
|
||||
}}
|
||||
/>
|
||||
<input type="hidden" name="code" value={code} />
|
||||
<button type="submit" name="submit">{t`Submit`}</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
const title = t`PixelPlanet.fun Password Reset`;
|
||||
const description = t`Reset your password here`;
|
||||
|
||||
const index = `<!doctype html>${
|
||||
ReactDOM.renderToStaticMarkup(<Html
|
||||
title={title}
|
||||
description={description}
|
||||
body={body}
|
||||
/>)}`;
|
||||
return index;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Make basic redirection page
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
import Html from './Html';
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
function getHtml(description, text, host, lang) {
|
||||
const { jt, t } = getTTag(lang);
|
||||
|
||||
const clickHere = <a href={host}>{t`Click here`}</a>;
|
||||
|
||||
const body = (
|
||||
<div>
|
||||
<h3>{text}</h3>
|
||||
<p>{t`You will be automatically redirected after 15s`}</p>
|
||||
<p>{jt`Or ${clickHere} to go back to pixelplanet`}</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const title = t`PixelPlanet.fun Accounts`;
|
||||
// eslint-disable-next-line max-len
|
||||
const code = `window.setTimeout(function(){window.location.href="${host}";},15000)`;
|
||||
|
||||
const index = `<!doctype html>${
|
||||
ReactDOM.renderToStaticMarkup(
|
||||
<Html title={title} description={description} body={body} code={code} />,
|
||||
)
|
||||
}`;
|
||||
return index;
|
||||
}
|
||||
|
||||
export default getHtml;
|
58
src/ssr/Globe.jsx
Normal file
58
src/ssr/Globe.jsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* react html for 3D globe page
|
||||
*
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
/* this will be set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
import { ASSET_SERVER } from '../core/config';
|
||||
|
||||
import globeCss from '../styles/globe.css';
|
||||
|
||||
/*
|
||||
* generates string with html of globe page
|
||||
* @param lang language code
|
||||
* @return html of mainpage
|
||||
*/
|
||||
function generateGlobePage(lang) {
|
||||
const scripts = (assets[`globe-${lang}`])
|
||||
? assets[`globe-${lang}`].js
|
||||
: assets.globe.js;
|
||||
|
||||
const { t } = getTTag(lang);
|
||||
|
||||
const html = `
|
||||
<!doctype html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>${t`PixelPlanet.Fun 3DGlobe`}</title>
|
||||
<meta name="description" content="${t`A 3D globe of our whole map`}" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<meta name="viewport"
|
||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
<style key="globe" id="globe">${globeCss}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="webgl" />
|
||||
<div id="coorbox">(0, 0)</div>
|
||||
<div id="info">${t`Double click on globe to go back.`}</div>
|
||||
<div id="loading">${t`Loading...`}</div>
|
||||
${scripts.map((script) => `<script src="${ASSET_SERVER + script}"></script>`).join('')}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
export default generateGlobePage;
|
80
src/ssr/Main.jsx
Normal file
80
src/ssr/Main.jsx
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Html for mainpage
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
|
||||
import { langCodeToCC } from '../utils/location';
|
||||
import ttags, { getTTag } from '../core/ttag';
|
||||
/* this one is set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import styleassets from './styleassets.json';
|
||||
|
||||
import { ASSET_SERVER, BACKUP_URL } from '../core/config';
|
||||
|
||||
/*
|
||||
* generate language list
|
||||
*/
|
||||
const langs = Object.keys(ttags)
|
||||
.map((l) => (l === 'default' ? 'en' : l))
|
||||
.map((l) => [l, langCodeToCC(l)]);
|
||||
|
||||
/*
|
||||
* values that we pass to client scripts
|
||||
*/
|
||||
const ssv = {
|
||||
assetserver: ASSET_SERVER,
|
||||
availableStyles: styleassets,
|
||||
langs,
|
||||
};
|
||||
if (BACKUP_URL) {
|
||||
ssv.backupurl = BACKUP_URL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates string with html of main page
|
||||
* @param countryCoords Cell with coordinates of client country
|
||||
* @param lang language code
|
||||
* @return html of mainpage
|
||||
*/
|
||||
function generateMainPage(lang) {
|
||||
const ssvR = {
|
||||
...ssv,
|
||||
lang: lang === 'default' ? 'en' : lang,
|
||||
};
|
||||
const scripts = (assets[`client-${lang}`])
|
||||
? assets[`client-${lang}`].js
|
||||
: assets.client.js;
|
||||
const { t } = getTTag(lang);
|
||||
|
||||
const html = `
|
||||
<!doctype html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>${t`PixelPlanet.Fun`}</title>
|
||||
<meta name="description" content="${t`Place color pixels on an map styled canvas with other players online`}" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<meta name="viewport"
|
||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
<script>window.ssv=JSON.parse('${JSON.stringify(ssvR)}')</script>
|
||||
<link rel="stylesheet" type="text/css" id="globcss" href="${styleassets.default}" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
</div>
|
||||
${scripts.map((script) => `<script src="${ASSET_SERVER + script}"></script>`).join('')}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
|
||||
export default generateMainPage;
|
72
src/ssr/PasswordReset.jsx
Normal file
72
src/ssr/PasswordReset.jsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Make basic reset_password forms
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
export default function getPasswordResetHtml(name, code, lang, message = null) {
|
||||
const { t } = getTTag(lang);
|
||||
|
||||
let html = '';
|
||||
|
||||
if (message) {
|
||||
html = `
|
||||
<!doctype html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>${t`PixelPlanet.fun Password Reset`}</title>
|
||||
<meta name="description" content="${t`Reset your password here`}" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
</head>
|
||||
<body>
|
||||
<h3>${t`Reset Password`}</h3>
|
||||
<p>${message}</p>
|
||||
<p><a href="./">${t`Click here`}</a> ${t`to go back to pixelplanet`}</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
} else {
|
||||
html = `
|
||||
<!doctype html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>${t`PixelPlanet.fun Password Reset`}</title>
|
||||
<meta name="description" content="${t`Reset your password here`}" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action="reset_password">
|
||||
<h3>${t`Reset Password`}</h3>
|
||||
<p>${t`Hello ${name}, you can set your new password here:`}</p>
|
||||
<input
|
||||
type="password"
|
||||
name="pass"
|
||||
placeholder="${t`New Password`}"
|
||||
style="max-width:35em"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="passconf"
|
||||
placeholder="${t`Confirm New Password`}"
|
||||
style="max-width:35em"
|
||||
/>
|
||||
<input type="hidden" name="code" value=${code} />
|
||||
<button type="submit" name="submit">${t`Submit`}</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
38
src/ssr/RedirectionPage.jsx
Normal file
38
src/ssr/RedirectionPage.jsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Make basic redirection page
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
import { getTTag } from '../core/ttag';
|
||||
|
||||
function getHtml(description, text, host, lang) {
|
||||
const { jt, t } = getTTag(lang);
|
||||
|
||||
const clickHere = `<a href="${host}">${t`Click here`}</a>`;
|
||||
|
||||
const html = `
|
||||
<!doctype html>
|
||||
<html lang="${lang}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>${t`PixelPlanet.fun Accounts`}</title>
|
||||
<meta name="description" content="${description}" />
|
||||
<meta name="google" content="nopagereadaloud" />
|
||||
<meta name="theme-color" content="#cae3ff" />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
<script>window.setTimeout(function(){window.location.href="${host}";},15000)</script>
|
||||
</head>
|
||||
<body>
|
||||
<h3>${text}</h3>
|
||||
<p>${t`You will be automatically redirected after 15s`}</p>
|
||||
<p>${jt`Or ${clickHere} to go back to pixelplanet`}</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
export default getHtml;
|
Loading…
Reference in New Issue
Block a user