mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-22 13:37:05 +02:00
feat: code split & use react helmet
This commit is contained in:
parent
bf1e30dc52
commit
406106b67e
19 changed files with 241 additions and 146 deletions
19
lib/core/clientEntry.js
Normal file
19
lib/core/clientEntry.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import App from './App';
|
||||
import prerender from './prerender';
|
||||
import routes from '@generated/routes'; // eslint-disable-line
|
||||
|
||||
// Client side render (e.g: running in browser) to become single-page application (SPA)
|
||||
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
prerender(routes, window.location.pathname).then(() => {
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('app')
|
||||
);
|
||||
});
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('app')
|
||||
);
|
18
lib/core/prerender.js
Normal file
18
lib/core/prerender.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import {matchRoutes} from 'react-router-config';
|
||||
|
||||
/**
|
||||
* This helps us to make sure all the async component for that particular route
|
||||
* is loaded before rendering. This is to avoid loading screens on first page load
|
||||
*/
|
||||
export default function prerender(routeConfig, providedLocation) {
|
||||
const matches = matchRoutes(routeConfig, providedLocation);
|
||||
return Promise.all(
|
||||
matches.map(match => {
|
||||
const {component} = match.route;
|
||||
if (component && component.preload) {
|
||||
return component.preload();
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
);
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import React from 'react';
|
||||
import {BrowserRouter, StaticRouter} from 'react-router-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
|
||||
import App from './App';
|
||||
|
||||
// Client side render (e.g: running in browser) to become single-page application (SPA)
|
||||
if (typeof document !== 'undefined') {
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('app')
|
||||
);
|
||||
}
|
||||
|
||||
// Renderer for static-site-generator-webpack-plugin (async rendering via callbacks)
|
||||
export default function render(locals, callback) {
|
||||
const context = {};
|
||||
const body = ReactDOMServer.renderToString(
|
||||
<StaticRouter location={locals.path} context={context}>
|
||||
<App />
|
||||
</StaticRouter>
|
||||
);
|
||||
|
||||
// Build HTML template
|
||||
const assets = Object.keys(locals.webpackStats.compilation.assets);
|
||||
const css = assets.filter(value => value.match(/\.css$/));
|
||||
const js = assets.filter(value => value.match(/\.js$/));
|
||||
const {title, baseUrl, lang = 'en', template} = locals;
|
||||
const html = template({body, baseUrl, css, js, title, lang});
|
||||
|
||||
callback(null, html);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="<%- lang%>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title><%- title %></title>
|
||||
<% css.forEach(function(file){ %>
|
||||
<link href="<%-baseUrl %><%- file %>" rel="stylesheet">
|
||||
<% }); %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><%- body %></div>
|
||||
<% js.forEach(function(file){ %>
|
||||
<script src="<%-baseUrl %><%- file %>"></script>
|
||||
<% }); %>
|
||||
</body>
|
||||
</html>
|
59
lib/core/serverEntry.js
Normal file
59
lib/core/serverEntry.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
import React from 'react';
|
||||
import {StaticRouter} from 'react-router-dom';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import App from './App';
|
||||
import prerender from './prerender';
|
||||
import routes from '@generated/routes'; // eslint-disable-line
|
||||
import webpackClientStats from '@build/client.stats.json'; //eslint-disable-line
|
||||
|
||||
// Renderer for static-site-generator-webpack-plugin (async rendering via promises)
|
||||
export default function render(locals) {
|
||||
return prerender(routes, locals.path).then(() => {
|
||||
const context = {};
|
||||
const appHtml = ReactDOMServer.renderToString(
|
||||
<StaticRouter location={locals.path} context={context}>
|
||||
<App />
|
||||
</StaticRouter>
|
||||
);
|
||||
|
||||
const helmet = Helmet.renderStatic();
|
||||
const htmlAttributes = helmet.htmlAttributes.toString();
|
||||
const bodyAttributes = helmet.bodyAttributes.toString();
|
||||
const metaStrings = [
|
||||
helmet.title.toString(),
|
||||
helmet.meta.toString(),
|
||||
helmet.link.toString()
|
||||
];
|
||||
const metaHtml = metaStrings.filter(Boolean).join('\n ');
|
||||
|
||||
const assets = webpackClientStats.assetsByChunkName.main;
|
||||
const jsFiles = assets.filter(value => value.match(/\.js$/));
|
||||
const cssFiles = assets.filter(value => value.match(/\.css$/));
|
||||
const {baseUrl} = locals;
|
||||
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
<html${htmlAttributes ? ` ${htmlAttributes}` : ''}>
|
||||
<head>
|
||||
${metaHtml}
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
${cssFiles.map(
|
||||
cssFile =>
|
||||
`<link rel="stylesheet" type="text/css" href="${baseUrl}${cssFile}" />`
|
||||
)}
|
||||
</head>
|
||||
<body${bodyAttributes ? ` ${bodyAttributes}` : ''}>
|
||||
<div id="app">${appHtml}</div>
|
||||
${jsFiles.map(
|
||||
jsFile =>
|
||||
`<script type="text/javascript" src="${baseUrl}${jsFile}"></script>`
|
||||
)}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
return html;
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue