Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* `IlibPlugin`:
* Added `ILIB_ADDITIONAL_RESOURCES_PATH` to defined constants if provided.
* Added `publicPath` option to specify webpack public path.
* `PrerenderPlugin`: Added React18 support for `ReactDOMClient.hydrateRoot` instead of `ReactDOMClient.createRoot` for prerendered apps.

# 4.1.4 (February 18, 2022)

Expand Down
9 changes: 4 additions & 5 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"eslint-plugin-react-hooks": "^4.3.0",
"html-webpack-plugin": "^5.3.2",
"prettier": "^2.6.0",
"react": "^17.0.2",
"react": "^18.0.0",
"webpack": "5.64.4"
}
}
11 changes: 8 additions & 3 deletions plugins/PrerenderPlugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,15 @@ class PrerenderPlugin {
});

compiler.hooks.emit.tapAsync('PrerenderPlugin', (compilation, callback) => {
// Replace ReactDOM.render to ReactDOM.hydrate from main.js
// Replace ReactDOMClient.createRoot to ReactDOMClient.hydrateRoot from main.js
const data = compilation.assets[opts.chunk].source();
const regex = /render(?=(?:(?!render|getElementById).)*getElementById\(('|")root)/;
const replacedData = data.replace(regex, 'hydrate');
const createRootRegex = /createRoot\)(\(container|\(document\.getElementById\(('|")root('|")\))/;
const hydrateRootData = data.replace(
createRootRegex,
`hydrateRoot)(document.getElementById(\'root\'), appElement`
);
const renderRegex = /root.render\(appElement\);/;
const replacedData = hydrateRootData.replace(renderRegex, '');

emitAsset(compilation, opts.chunk, replacedData);

Expand Down
4 changes: 2 additions & 2 deletions plugins/PrerenderPlugin/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ const startup = (screenTypes, jsAssets) => `
if(typeof updateEnvironment === 'function') {
updateEnvironment();
}
if(typeof App === 'object' && (typeof ReactDOM === 'object')) {
ReactDOM.hydrate(App['default'] || App, document.getElementById('root'));
if(typeof App === 'object' && (typeof ReactDOMClient === 'object')) {
ReactDOMClient.hydrateRoot(App['default'] || App, document.getElementById('root'));
} else {
console.log('ERROR: Snapshot app not found');
}
Expand Down
6 changes: 3 additions & 3 deletions plugins/SnapshotPlugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class SnapshotPlugin {
apply(compiler) {
const opts = this.options;
const app = helper.appRoot();
const reactDOM = path.resolve(path.join(app, 'node_modules', 'react-dom'));
const reactDOMClient = path.resolve(path.join(app, 'node_modules', 'react-dom/client'));
opts.blob = getBlobName(opts.args);

// Ignore packages that don't exists so snapshot helper can skip them
Expand All @@ -86,10 +86,10 @@ class SnapshotPlugin {
compiler.hooks.normalModuleFactory.tap('SnapshotPlugin', factory => {
factory.hooks.beforeResolve.tap('SnapshotPlugin', result => {
if (!result) return;
if (result.request === 'react-dom') {
if (result.request === 'react-dom/client') {
// When the request originates from the injected helper, point to real 'react-dom'
if (result.contextInfo.issuer === SnapshotPlugin.helperJS) {
result.request = reactDOM;
result.request = reactDOMClient;
} else {
result.request = SnapshotPlugin.helperJS;
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/SnapshotPlugin/mock-window.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* mock-window.js
*
* A helper utility meant to simulate a basic window object for ReactDOM usage during snapshot execution.
* A helper utility meant to simulate a basic window object for ReactDOMClient usage during snapshot execution.
*/

var orig = {}, listeners = [], nop = function() {};
Expand Down
4 changes: 2 additions & 2 deletions plugins/SnapshotPlugin/snapshot-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ if (typeof window == 'undefined'
ExecutionEnvironment.canUseEventListeners = true;
ExecutionEnvironment.canUseViewport = true;
ExecutionEnvironment.isInWorker = false;
module.exports = global.ReactDOM = require('react-dom');
module.exports = global.ReactDOMClient = require('react-dom/client');
mockWindow.deactivate();
} else {
module.exports = global.ReactDOM = require('react-dom');
module.exports = global.ReactDOMClient = require('react-dom/client');
}