Skip to content

Commit f196a1e

Browse files
authored
fix(core): fix React hydration errors, change html minifier settings (#10786)
1 parent 2565601 commit f196a1e

File tree

4 files changed

+27
-34
lines changed

4 files changed

+27
-34
lines changed

argos/tests/screenshot.spec.ts

+1-11
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,11 @@ function throwOnConsole(page: Page) {
131131
const typesToCheck = ['error', 'warning'];
132132

133133
const ignoreMessages = [
134-
// This mismatch warning looks like a React 18 bug to me
135-
'Warning: Prop `%s` did not match. Server: %s Client: %s%s className "null" ""',
136-
137134
// TODO this fetch error message is unexpected and should be fixed
138135
// it's already happening in main branch
139136
'Failed to load resource: the server responded with a status of 404 (Not Found)',
140137

141-
// TODO looks like a legit hydration bug to fix
142-
// on /blog/releases/2.4
143-
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-theme=light"',
144-
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-theme=dark"',
145-
// on /blog/releases/3.0
146-
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-data-navbar=false&docusaurus-data-red-border"',
147-
// on /docs/styling-layout
148-
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-data-navbar=false&docusaurus-data-red-border"',
138+
// TODO looks like legit hydration bugs to fix
149139
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs/configuration" "/docs/configuration?docusaurus-theme=light"',
150140
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs/configuration" "/docs/configuration?docusaurus-theme=dark"',
151141

packages/docusaurus-bundler/src/minifyHtml.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,13 @@ async function getTerserMinifier(): Promise<HtmlMinifier> {
4747
minify: async function minifyHtmlWithTerser(html) {
4848
try {
4949
const code = await terserHtmlMinifier(html, {
50+
// When enabled => React hydration errors
5051
removeComments: false,
51-
removeRedundantAttributes: true,
52-
removeEmptyAttributes: true,
52+
removeRedundantAttributes: false,
53+
removeEmptyAttributes: false,
54+
sortAttributes: false,
55+
sortClassName: false,
56+
5357
removeScriptTypeAttributes: true,
5458
removeStyleLinkTypeAttributes: true,
5559
useShortDoctype: true,
@@ -84,8 +88,13 @@ async function getSwcMinifier(): Promise<HtmlMinifier> {
8488
sortSpaceSeparatedAttributeValues: false,
8589
sortAttributes: false,
8690

87-
removeRedundantAttributes: 'all',
88-
removeEmptyAttributes: true,
91+
// When enabled => hydration error for className={"yt-lite "}
92+
normalizeAttributes: false,
93+
// When enabled => hydration error for className=""
94+
removeEmptyAttributes: false,
95+
// When enabled => hydration error for <a target="_self">
96+
removeRedundantAttributes: 'none',
97+
8998
minifyJs: true,
9099
minifyJson: true,
91100
minifyCss: true,

packages/docusaurus-theme-common/src/components/Collapsible/index.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import React, {
1515
type SetStateAction,
1616
type ReactNode,
1717
} from 'react';
18-
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
18+
import useIsBrowser from '@docusaurus/useIsBrowser';
1919
import useIsomorphicLayoutEffect from '@docusaurus/useIsomorphicLayoutEffect';
2020
import {prefersReducedMotion} from '../../utils/accessibilityUtils';
2121

@@ -161,8 +161,15 @@ type CollapsibleElementType = React.ElementType<
161161
* Prevent hydration layout shift before animations are handled imperatively
162162
* with JS
163163
*/
164-
function getSSRStyle(collapsed: boolean) {
165-
if (ExecutionEnvironment.canUseDOM) {
164+
function getSSRStyle({
165+
collapsed,
166+
isBrowser,
167+
}: {
168+
collapsed: boolean;
169+
isBrowser: boolean;
170+
}) {
171+
// After hydration, styles are applied
172+
if (isBrowser) {
166173
return undefined;
167174
}
168175
return collapsed ? CollapsedStyles : ExpandedStyles;
@@ -202,6 +209,7 @@ function CollapsibleBase({
202209
className,
203210
disableSSRStyle,
204211
}: CollapsibleBaseProps) {
212+
const isBrowser = useIsBrowser();
205213
const collapsibleRef = useRef<HTMLElement>(null);
206214

207215
useCollapseAnimation({collapsibleRef, collapsed, animation});
@@ -211,7 +219,8 @@ function CollapsibleBase({
211219
// @ts-expect-error: the "too complicated type" is produced from
212220
// "CollapsibleElementType" being a huge union
213221
ref={collapsibleRef as RefObject<never>} // Refs are contravariant, which is not expressible in TS
214-
style={disableSSRStyle ? undefined : getSSRStyle(collapsed)}
222+
// Not even sure we need this SSRStyle anymore, try to remove it?
223+
style={disableSSRStyle ? undefined : getSSRStyle({collapsed, isBrowser})}
215224
onTransitionEnd={(e: React.TransitionEvent) => {
216225
if (e.propertyName !== 'height') {
217226
return;

website/_dogfooding/_pages tests/tabs-tests.mdx

-15
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,6 @@ import Tabs from '@theme/Tabs';
66
import TabItem from '@theme/TabItem';
77
```
88

9-
## Tabs with dynamic default value
10-
11-
This can cause [bugs](https://github.com/facebook/react-native-website/issues/2771) when default value is different between SSR and client:
12-
13-
```mdx-code-block
14-
export const isMacOS = typeof window !== 'undefined' && navigator.platform.startsWith('Mac');
15-
16-
<BrowserWindow>
17-
<Tabs defaultValue={isMacOS ? "ios" : "android"}>
18-
<TabItem value="android" label="Android">Android content</TabItem>
19-
<TabItem value="ios" label="iOS">iOS content</TabItem>
20-
</Tabs>
21-
</BrowserWindow>
22-
```
23-
249
## Tabs sync with different heights
2510

2611
```mdx-code-block

0 commit comments

Comments
 (0)