Socket
Socket
Sign inDemoInstall

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.6 to 0.5.0

.DS_Store

27

changelog.md
# Changelog
## 0.5.0
Breaking changes:
* Drop support for Node v6
* Symbols are actual Symbols
Refactor:
* ESLint comments
Tests:
* Major refactor and test all against sync HTML
* Client-side hydration
Dev:
* Travis CI run tests on Node v12
* Jest config coverage blacklist
* Update dev dependencies
* Add `package-lock.json`
Docs:
* Readme update
## 0.4.6

@@ -4,0 +31,0 @@

3

lib/abort.js

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

let resolved = false;
// eslint-disable-next-line no-return-assign
const resolve = () => resolved = true;
const resolve = () => { resolved = true; };
promise.then(resolve, resolve);

@@ -34,0 +33,0 @@ if (!resolved) abort(promise);

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

suspendDescendents(node) {
// eslint-disable-next-line no-shadow
walkTree(node, (node, inLazy) => {
walkTree(node, (node, inLazy) => { // eslint-disable-line no-shadow
const {type} = node;

@@ -238,0 +237,0 @@ if (type === TYPE_SUSPENSE) {

@@ -10,5 +10,5 @@ /* --------------------

module.exports = {
NO_SSR: '__reactAsyncSsrNoSsr',
ABORT: '__reactAsyncSsrAbort',
ON_MOUNT: '__reactAsyncSsrOnMount'
NO_SSR: Symbol('react-async-ssr/symbols.NO_SSR'),
ABORT: Symbol('react-async-ssr/symbols.ABORT'),
ON_MOUNT: Symbol('react-async-ssr/symbols.ON_MOUNT')
};
{
"name": "react-async-ssr",
"version": "0.4.6",
"version": "0.5.0",
"description": "Render React Suspense on server",

@@ -23,10 +23,11 @@ "main": "index.js",

"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"@overlookmotel/eslint-config": "^2.0.0",
"@overlookmotel/eslint-config-jest": "^1.0.2",
"@overlookmotel/eslint-config-react": "^2.0.0",
"@overlookmotel/eslint-config": "^3.0.2",
"@overlookmotel/eslint-config-jest": "^1.1.1",
"@overlookmotel/eslint-config-react": "^2.0.1",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^23.6.0",
"cheerio": "^1.0.0-rc.3",
"coveralls": "^3.0.3",

@@ -38,7 +39,10 @@ "cross-env": "^5.2.0",

"eslint-plugin-eslint-comments": "^3.1.1",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jest": "^22.4.1",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-jest": "^22.6.4",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.12.4",
"eslint-plugin-react": "^7.13.0",
"fs-extra": "^8.0.1",
"jest": "^23.6.0",
"jest-each-object": "^1.0.0",
"jsdom": "^15.1.1",
"prop-types": "^15.7.2",

@@ -69,3 +73,3 @@ "react": "^16.6.0"

"engines": {
"node": ">=6"
"node": ">=8"
},

@@ -72,0 +76,0 @@ "readmeFilename": "README.md",

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

}
const html = await ReactDOMServer.renderToStringAsync(<App />);
```

@@ -85,3 +83,3 @@

In it's `render()` method, the component should throw a Promise which will resolve when the data is loaded. When the promise resolves, the renderer will re-render the component and add it into the markup.
In its `render()` method, the component should throw a Promise which will resolve when the data is loaded. When the promise resolves, the renderer will re-render the component and add it into the markup.

@@ -116,2 +114,6 @@ #### Basic example

}
const html = await ReactDOMServer.renderToStringAsync(<App />);
// html === '<div>bar</div>'
```

@@ -134,3 +136,3 @@

const data = PokemonResource.read(props.id);
return <div>My name is {data.name}</div>;
return <div>My name is {data.name}.</div>;
}

@@ -151,2 +153,10 @@

const html = await ReactDOMServer.renderToStringAsync(<App />);
// html === `
// <div>
// <div>My name is bulbasaur.</div>
// <div>My name is ivysaur.</div>
// <div>My name is venusaur.</div>
// </div>
// `
```

@@ -156,9 +166,2 @@

### Complicated cases
`.renderToStringAsync()` supports:
* Async components which themselves load more async components/data
* Suspense fallbacks which load async components/data
### Hydrating the render on client side

@@ -192,2 +195,9 @@

### Complicated cases
`.renderToStringAsync()` supports:
* Async components which themselves load more async components/data
* Suspense fallbacks which load async components/data
### Tracking components being used

@@ -199,11 +209,15 @@

`[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).
```js
const {ON_MOUNT} = require('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](#preventing-server-side-rendering-of-components)).
`[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.
Only components whose promise's `[ON_MOUNT]()` method has been called with `true` should have their imported file/data provided to client 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
### Preventing server-side rendering of components

@@ -238,6 +252,14 @@ Sometimes you might want to prevent a component rendering on server side. For example, it might be a low-priority part of the page, "below the fold", or a heavy component which will take a long time to load on client side and increase the delay before hydration.

When rendered on server, this will output `<div>Loading...</div>`.
When rendered on server, this will output `<div>Loading...</div>`. The content can then be loaded client side after hydration.
On client side, to ensure no hydration mismatch errors, the component must throw a promise which then resolves to the required component/data, and not render the output synchronously.
On client side, to ensure hydration completes correctly, the component must throw a promise which then resolves to the required component/data, and not render the content synchronously.
#### Warning: Hydration errors
If you leave some content to be rendered on client, `ReactDOM.hydrate()` will log warnings to console.error "Text content did not match". The cause is that React does not officially support using `Suspense` on server side, and so does not expect to encounter `Suspense` in hydrate.
However, aside from the console output, it's not a problem. The page *will* hydrate and then load correctly. This case is covered by this module's tests, and it does work.
There is no console output in production mode, only development, so your users should not see anything. It's just annoying in development.
#### Optimization: Bail out of rendering when suspended

@@ -299,5 +321,5 @@

Many other solutions achieve something like this by "double-rendering" the app.
Many other solutions achieve some form of server-side rendering by "double-rendering" the app.
In the first render pass, all the promises for async-loaded data are collected. Once all the promises resolve, a 2nd render pass produces the actual HTML markup which is sent to the client. Obviously, this is resource-intensive. And if async components themselves make further async requests, 3rd or 4th or more render passes can be required.
In the first render pass, all the promises for async-loaded data are collected. Once all the promises resolve, a 2nd render pass produces the actual HTML markup which is sent to the client. Obviously, it's resource-intensive to render twice. And if async components themselves make further async requests, 3rd or 4th or more render passes can be required.

@@ -304,0 +326,0 @@ The `.renderToStringAsync()` method provided by this package renders in a single pass. The render is interrupted when awaiting an async resource and resumed once it has loaded.

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