feat(v2): allow users to specify a custom ssr HTML template (#3387)

* feat(v2): allow users to specify a custom ssr HTML template

* docs(v2): add ssrTemplate property to docusaurus.config.js page
This commit is contained in:
Méril 2020-09-02 19:29:04 +02:00 committed by GitHub
parent 9857f7b2b5
commit 3ace60043b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 8 deletions

View file

@ -41,6 +41,7 @@ export interface DocusaurusConfig {
[key: string]: unknown;
}
)[];
ssrTemplate?: string;
stylesheets?: (
| string
| {
@ -110,6 +111,7 @@ export interface LoadContext {
siteConfig: DocusaurusConfig;
outDir: string;
baseUrl: string;
ssrTemplate?: string;
}
export interface InjectedHtmlTags {

View file

@ -26,19 +26,18 @@ import {
createStatefulLinksCollector,
ProvideLinksCollector,
} from './LinksCollector';
import ssrTemplate from './templates/ssr.html.template';
// eslint-disable-next-line no-restricted-imports
import {memoize} from 'lodash';
const getCompiledSSRTemplate = memoize(() => {
return eta.compile(ssrTemplate.trim(), {
const getCompiledSSRTemplate = memoize((template) => {
return eta.compile(template.trim(), {
rmWhitespace: true,
});
});
function renderSSRTemplate(data) {
const compiled = getCompiledSSRTemplate();
function renderSSRTemplate(ssrTemplate, data) {
const compiled = getCompiledSSRTemplate(ssrTemplate);
return compiled(data, eta.defaultConfig);
}
@ -51,6 +50,7 @@ export default async function render(locals) {
postBodyTags,
onLinksCollected,
baseUrl,
ssrTemplate,
} = locals;
const location = routesLocation[locals.path];
await preload(routes, location);
@ -90,7 +90,7 @@ export default async function render(locals) {
const stylesheets = (bundles.css || []).map((b) => b.file);
const scripts = (bundles.js || []).map((b) => b.file);
const renderedHtml = renderSSRTemplate({
const renderedHtml = renderSSRTemplate(ssrTemplate, {
appHtml,
baseUrl,
htmlAttributes: htmlAttributes || '',

View file

@ -81,6 +81,7 @@ const ConfigSchema = Joi.object({
// See https://github.com/facebook/docusaurus/issues/3378
.unknown(),
),
ssrTemplate: Joi.string(),
stylesheets: Joi.array().items(
Joi.string(),
Joi.object({

View file

@ -7,6 +7,7 @@
import {generate} from '@docusaurus/utils';
import path, {join} from 'path';
import ssrDefaultTemplate from '../client/templates/ssr.html.template';
import {
BUILD_DIR_NAME,
CONFIG_FILE_NAME,
@ -43,7 +44,7 @@ export function loadContext(
const outDir = customOutDir
? path.resolve(customOutDir)
: path.resolve(siteDir, BUILD_DIR_NAME);
const {baseUrl} = siteConfig;
const {baseUrl, ssrTemplate} = siteConfig;
return {
siteDir,
@ -51,6 +52,7 @@ export function loadContext(
siteConfig,
outDir,
baseUrl,
ssrTemplate,
};
}
@ -72,7 +74,7 @@ export async function load(
): Promise<Props> {
// Context.
const context: LoadContext = loadContext(siteDir, customOutDir);
const {generatedFilesDir, siteConfig, outDir, baseUrl} = context;
const {generatedFilesDir, siteConfig, outDir, baseUrl, ssrTemplate} = context;
// Plugins.
const pluginConfigs: PluginConfig[] = loadPluginConfigs(context);
@ -237,6 +239,7 @@ ${Object.keys(registry)
headTags,
preBodyTags,
postBodyTags,
ssrTemplate: ssrTemplate || ssrDefaultTemplate,
};
return props;

View file

@ -31,6 +31,7 @@ export default function createServerConfig({
headTags,
preBodyTags,
postBodyTags,
ssrTemplate,
} = props;
const config = createBaseConfig(props, true, minify);
@ -70,6 +71,7 @@ export default function createServerConfig({
preBodyTags,
postBodyTags,
onLinksCollected,
ssrTemplate,
},
paths: ssgPaths,
}),

View file

@ -306,6 +306,50 @@ module.exports = {
};
```
### `ssrTemplate`
An HTML template that will be used to render your application. This can be used to set custom attributes on the `body` tags, additional `meta` tags, customize the `viewport`, etc. Please note that Docusaurus will rely on the template to be correctly structured in order to function properly, once you do customize it, you will have to make sure that your template is compliant with the requirements from `upstream`.
- Type: `string`
Example:
```js title="docusaurus.config.js"
module.exports = {
ssrTemplate: `<!DOCTYPE html>
<html <%~ it.htmlAttributes %>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=0.86, maximum-scale=3.0, minimum-scale=0.86">
<meta name="generator" content="Docusaurus v<%= it.version %>">
<%~ it.headTags %>
<% it.metaAttributes.forEach((metaAttribute) => { %>
<%~ metaAttribute %>
<% }); %>
<% it.stylesheets.forEach((stylesheet) => { %>
<link rel="stylesheet" type="text/css" href="<%= it.baseUrl %><%= stylesheet %>" />
<% }); %>
<% it.scripts.forEach((script) => { %>
<link rel="preload" href="<%= it.baseUrl %><%= script %>" as="script">
<% }); %>
</head>
<body <%~ it.bodyAttributes %> itemscope="" itemtype="http://schema.org/Organization">
<%~ it.preBodyTags %>
<div id="__docusaurus">
<%~ it.appHtml %>
</div>
<div id="outside-docusaurus">
<span>Custom markup</span>
</div>
<% it.scripts.forEach((script) => { %>
<script type="text/javascript" src="<%= it.baseUrl %><%= script %>"></script>
<% }); %>
<%~ it.postBodyTags %>
</body>
</html>
};
```
### `stylesheets`
An array of CSS sources to load. The values can be either strings or plain objects of attribute-value maps. The `<link>` tags will be inserted in the HTML `<head>`.