mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Render callbacks can now inject HTML content into multiple different
elements, and may also append content to the <head> or <body> elements, on
both the client and the server.
This new API was inspired by trying to use the styled-components npm
package on the server, which involves not only rendering and injecting
static HTML somewhere in the <body>, but also appending the resulting
<style> tag(s) into the <head>:
import { onPageLoad } from "meteor/server-render";
import { renderToString } from "react-dom/server";
import { ServerStyleSheet } from "styled-components";
onPageLoad(sink => {
const sheet = new ServerStyleSheet();
const html = renderToString(sheet.collectStyles(
<App location={sink.request.url} />
));
sink.renderIntoElementById("app", html);
sink.appendToHead(sheet.getStyleTags());
});
Note that the server-render package now exports an onPageLoad function,
rather than the old renderIntoElementById function. The functionality of
renderIntoElementById is now exposed by the {Client,Server}Sink API.
I say the client-side version of this API is 'isomorphish' to the
server-side version, because ClientSink methods can accept DOM nodes in
addition to raw HTML strings, whereas DOM nodes don't really make sense on
the server.
51 lines
1.1 KiB
JavaScript
51 lines
1.1 KiB
JavaScript
export class ServerSink {
|
|
constructor(request, arch) {
|
|
this.request = request;
|
|
this.arch = arch;
|
|
this.head = "";
|
|
this.body = "";
|
|
this.htmlById = Object.create(null);
|
|
this.maybeMadeChanges = false;
|
|
}
|
|
|
|
appendToHead(html) {
|
|
if (appendContent(this, "head", html)) {
|
|
this.maybeMadeChanges = true;
|
|
}
|
|
}
|
|
|
|
appendToBody(html) {
|
|
if (appendContent(this, "body", html)) {
|
|
this.maybeMadeChanges = true;
|
|
}
|
|
}
|
|
|
|
appendToElementById(id, html) {
|
|
if (appendContent(this.htmlById, id, html)) {
|
|
this.maybeMadeChanges = true;
|
|
}
|
|
}
|
|
|
|
renderIntoElementById(id, html) {
|
|
this.htmlById[id] = "";
|
|
this.appendToElementById(id, html);
|
|
}
|
|
}
|
|
|
|
function appendContent(object, property, content) {
|
|
let madeChanges = false;
|
|
|
|
if (Array.isArray(content)) {
|
|
content.forEach(elem => {
|
|
if (appendContent(object, property, elem)) {
|
|
madeChanges = true;
|
|
}
|
|
});
|
|
} else if ((content = content && content.toString("utf8"))) {
|
|
object[property] = (object[property] || "") + content;
|
|
madeChanges = true;
|
|
}
|
|
|
|
return madeChanges;
|
|
}
|