Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-async-ssr

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-async-ssr - npm Package Compare versions

Comparing version 0.4.4 to 0.4.5

10

changelog.md
# Changelog
## 0.4.5
Features:
* Call `[ON_MOUNT]` on promises
Other:
* Tests: Refactor with expect extensions
## 0.4.4

@@ -4,0 +14,0 @@

1

lib/constants.js

@@ -12,3 +12,4 @@ /* --------------------

TYPE_PROMISE: 'promise',
TYPE_FALLBACK: 'fallback',
TYPE_TEXT: 'text'
};

@@ -90,3 +90,12 @@ /* --------------------

if (suspenseNode.suspended) {
// Abort promise
followAndAbort(promise);
// Create tree node
if (!this.fallbackFast) {
const node = this.createNode(TYPE_PROMISE);
node.resolved = true;
node.promise = promise;
}
return;

@@ -126,2 +135,3 @@ }

node.resolved = true;
node.promise = promise;

@@ -140,5 +150,5 @@ node.frame = frame;

node = this.createNodeWithStackState(TYPE_PROMISE, frame);
node.resolved = false;
node.promise = promise;
node.element = element;
node.promise = promise;
node.resolved = false;

@@ -176,5 +186,12 @@ this.numAwaiting++;

handleNoSsrPromise(promise) {
// Abort this promise
// Abort promise
followAndAbort(promise);
// Create tree node
if (!this.fallbackFast) {
const node = this.createNode(TYPE_PROMISE);
node.resolved = true;
node.promise = promise;
}
// Suspend suspense

@@ -181,0 +198,0 @@ const {suspenseNode} = this;

9

lib/renderer.js

@@ -12,3 +12,3 @@ /* --------------------

// Imports
const {TYPE_SUSPENSE, TYPE_PROMISE, TYPE_TEXT} = require('./constants'),
const {TYPE_SUSPENSE, TYPE_PROMISE, TYPE_FALLBACK, TYPE_TEXT} = require('./constants'),
{ReactDOMServerRenderer, isDev} = require('./rendererSuper'),

@@ -156,5 +156,6 @@ shimMethods = require('./shim'),

convertNodeToFallback(node) {
node.type = null;
node.type = TYPE_FALLBACK;
node.fallback = null;
node.children.length = 0;
node.suspendedChildren = node.children;
node.children = [];
}

@@ -229,3 +230,3 @@

// NB Do not leak `this` to callback
const out = treeToHtml(this.tree, this.makeStaticMarkup);
const out = treeToHtml(this.tree, this.makeStaticMarkup, this.fallbackFast);
const {callback} = this;

@@ -232,0 +233,0 @@ callback(null, out);

@@ -11,3 +11,4 @@ /* --------------------

NO_SSR: '__reactAsyncSsrNoSsr',
ABORT: '__reactAsyncSsrAbort'
ABORT: '__reactAsyncSsrAbort',
ON_MOUNT: '__reactAsyncSsrOnMount'
};

@@ -9,30 +9,73 @@ /* --------------------

// Imports
const {TYPE_TEXT} = require('./constants'),
walkTree = require('./walkTree');
const {TYPE_TEXT, TYPE_PROMISE, TYPE_FALLBACK} = require('./constants'),
{ON_MOUNT} = require('./symbols');
// Exports
class Walker {
constructor(tree, makeStaticMarkup, fallbackFast) {
this.tree = tree;
this.makeStaticMarkup = makeStaticMarkup;
this.fallbackFast = fallbackFast;
this.out = '';
this.lastText = false;
}
walk() {
this.process(this.tree, false);
return this.out;
}
process(node, suspended) {
const {type} = node;
if (type === TYPE_TEXT) {
// Flush output.
// If is within suspended Suspense boundary, do not output as will not render.
if (!suspended) {
const {out} = node;
if (this.lastText && out.slice(0, 1) !== '<') this.out += '<!-- -->';
this.out += out;
if (!this.makeStaticMarkup) this.lastText = out.slice(-1) !== '>';
}
return;
}
if (type === TYPE_PROMISE) {
const {promise} = node;
// Call `[ON_MOUNT]()` on promise with `true` if being rendered,
// or `false` if not (inside suspensed Suspense boundary)
if (typeof promise[ON_MOUNT] === 'function') promise[ON_MOUNT](!suspended);
// If inside suspended boundary, exit - promise is not resolved,
// so children will not render
if (suspended) return;
} else if (type === TYPE_FALLBACK && !this.fallbackFast) {
// Is a suspended suspense node.
// Iterate over suspended children to call `[ON_MOUNT]()` callbacks on promises.
for (let child of node.suspendedChildren) {
this.process(child, true);
}
}
for (let child of node.children) {
this.process(child, suspended);
}
}
}
/**
* Render node tree to HTML.
* `[ON_MOUNT]()` is called on all promises that have this method.
* All promise nodes must be resolved before calling this.
* @param {Object} tree - Node tree
* @param {boolean} makeStaticMarkup - `true` for `renderToStaticMarkup()`-style rendering
* @param {boolean} fallbackFast - `fallbackFast` option
* @returns {string} - HTML output
*/
function treeToHtml(tree, makeStaticMarkup) {
let out = '',
lastText = false;
walkTree(tree, node => {
if (node.type !== TYPE_TEXT) return;
const thisOut = node.out;
if (lastText && thisOut.slice(0, 1) !== '<') out += '<!-- -->';
out += thisOut;
if (!makeStaticMarkup) lastText = thisOut.slice(-1) !== '>';
});
return out;
function treeToHtml(tree, makeStaticMarkup, fallbackFast) {
const walker = new Walker(tree, makeStaticMarkup, fallbackFast);
return walker.walk();
}
module.exports = treeToHtml;
{
"name": "react-async-ssr",
"version": "0.4.4",
"version": "0.4.5",
"description": "Render React Suspense on server",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -186,2 +186,16 @@ [![NPM version](https://img.shields.io/npm/v/react-async-ssr.svg)](https://www.npmjs.com/package/react-async-ssr)

### Tracking components being used
If promises thrown have an `[ON_MOUNT]()` method, they are called.
`[ON_MOUNT]` is a symbol which can be imported from `react-async-ssr/symbols`.
`[ON_MOUNT]()` is called in the order components will be rendered on the client during hydration. This may not be the same order as the components are rendered on the server, if lazy components are nested within each other. In some cases, a component may render on the server, but not at all on the client during hydration, due to a Suspense fallback being triggered (see below).
`[ON_MOUNT]()` is called with `true` if the element will be rendered on client, or `false` if it will not. `false` happens if the promise was thrown by a component which ends up being inside a Suspense boundary whose fallback is triggered, so the component is not rendered.
Only components whose promise's `[ON_MOUNT]()` method has been called with `true` should have their imported file/data provided on client side so they can be rehydrated synchronously. Those called with `false` should be allowed to load file/data asynchronously.
This is to prevent unnecessary files/data being loaded on the client prior to hydration, when they won't actually be used in hydration. Doing that would increase the time user has to wait before hydration.
### Preventing components rendering on server side

@@ -188,0 +202,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc