@samitouri / QOS-React-2 / commits / 58af67a8f8

Only build react-html in experimental channel (#30129)

Even though the whole package is private right now. Once we publish it, it'll likely be just the experimental channel first before upgrading to stable. This means it gets excluded from the built packages.

Sebastian Markbåge committed Jun 28, 2024 at 16:19 UTC 58af67a8f8761e56b5d02486a304c96edc547760
5 files changed +313 -252
packages/react-html/src/ReactHTMLClient.stable.js new
+11
@@ -0,0 +1,11 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +// eslint-disable-next-line react-internal/prod-error-codes
11 +throw new Error('react-html should not get built in stable');
packages/react-html/src/ReactHTMLServer.stable.js new
+11
@@ -0,0 +1,11 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +// eslint-disable-next-line react-internal/prod-error-codes
11 +throw new Error('react-html should not get built in stable');
packages/react-html/src/__tests__/ReactHTMLClient-test.js
+132 -121
@@ -12,141 +12,152 @@
12 let React;
13 let ReactHTML;
14
15 -describe('ReactHTML', () => {
16 - beforeEach(() => {
17 - jest.resetModules();
18 - React = require('react');
19 - ReactHTML = require('react-html');
15 +if (!__EXPERIMENTAL__) {
16 + it('should not be built in stable', () => {
17 + try {
18 + require('react-html');
19 + } catch (x) {
20 + return;
21 + }
22 + throw new Error('Expected react-html not to exist in stable.');
23 });
24 +} else {
25 + describe('ReactHTML', () => {
26 + beforeEach(() => {
27 + jest.resetModules();
28 + React = require('react');
29 + ReactHTML = require('react-html');
30 + });
31
22 - it('should be able to render a simple component', async () => {
23 - function Component() {
24 - return <div>hello world</div>;
25 - }
32 + it('should be able to render a simple component', async () => {
33 + function Component() {
34 + return <div>hello world</div>;
35 + }
36
27 - const html = await ReactHTML.renderToMarkup(<Component />);
28 - expect(html).toBe('<div>hello world</div>');
29 - });
37 + const html = await ReactHTML.renderToMarkup(<Component />);
38 + expect(html).toBe('<div>hello world</div>');
39 + });
40
31 - it('should prefix html tags with a doctype', async () => {
32 - const html = await ReactHTML.renderToMarkup(
33 - <html>
34 - <body>hello</body>
35 - </html>,
36 - );
37 - expect(html).toBe(
38 - '<!DOCTYPE html><html><head></head><body>hello</body></html>',
39 - );
40 - });
41 + it('should prefix html tags with a doctype', async () => {
42 + const html = await ReactHTML.renderToMarkup(
43 + <html>
44 + <body>hello</body>
45 + </html>,
46 + );
47 + expect(html).toBe(
48 + '<!DOCTYPE html><html><head></head><body>hello</body></html>',
49 + );
50 + });
51
42 - it('should error on useState', async () => {
43 - function Component() {
44 - const [state] = React.useState('hello');
45 - return <div>{state}</div>;
46 - }
52 + it('should error on useState', async () => {
53 + function Component() {
54 + const [state] = React.useState('hello');
55 + return <div>{state}</div>;
56 + }
57
48 - await expect(async () => {
49 - await ReactHTML.renderToMarkup(<Component />);
50 - }).rejects.toThrow();
51 - });
58 + await expect(async () => {
59 + await ReactHTML.renderToMarkup(<Component />);
60 + }).rejects.toThrow();
61 + });
62
53 - it('should error on refs passed to host components', async () => {
54 - function Component() {
55 - const ref = React.createRef();
56 - return <div ref={ref} />;
57 - }
63 + it('should error on refs passed to host components', async () => {
64 + function Component() {
65 + const ref = React.createRef();
66 + return <div ref={ref} />;
67 + }
68
59 - await expect(async () => {
60 - await ReactHTML.renderToMarkup(<Component />);
61 - }).rejects.toThrow();
62 - });
69 + await expect(async () => {
70 + await ReactHTML.renderToMarkup(<Component />);
71 + }).rejects.toThrow();
72 + });
73
64 - it('should error on callbacks passed to event handlers', async () => {
65 - function Component() {
66 - function onClick() {
67 - // This won't be able to be called.
74 + it('should error on callbacks passed to event handlers', async () => {
75 + function Component() {
76 + function onClick() {
77 + // This won't be able to be called.
78 + }
79 + return <div onClick={onClick} />;
80 }
69 - return <div onClick={onClick} />;
70 - }
81
72 - await expect(async () => {
73 - await ReactHTML.renderToMarkup(<Component />);
74 - }).rejects.toThrow();
75 - });
82 + await expect(async () => {
83 + await ReactHTML.renderToMarkup(<Component />);
84 + }).rejects.toThrow();
85 + });
86
77 - it('supports the useId Hook', async () => {
78 - function Component() {
79 - const firstNameId = React.useId();
80 - const lastNameId = React.useId();
81 - return React.createElement(
82 - 'div',
83 - null,
84 - React.createElement(
85 - 'h2',
86 - {
87 - id: firstNameId,
88 - },
89 - 'First',
90 - ),
91 - React.createElement(
92 - 'p',
93 - {
94 - 'aria-labelledby': firstNameId,
95 - },
96 - 'Sebastian',
97 - ),
98 - React.createElement(
99 - 'h2',
100 - {
101 - id: lastNameId,
102 - },
103 - 'Last',
104 - ),
105 - React.createElement(
106 - 'p',
107 - {
108 - 'aria-labelledby': lastNameId,
109 - },
110 - 'Smith',
111 - ),
112 - );
113 - }
87 + it('supports the useId Hook', async () => {
88 + function Component() {
89 + const firstNameId = React.useId();
90 + const lastNameId = React.useId();
91 + return React.createElement(
92 + 'div',
93 + null,
94 + React.createElement(
95 + 'h2',
96 + {
97 + id: firstNameId,
98 + },
99 + 'First',
100 + ),
101 + React.createElement(
102 + 'p',
103 + {
104 + 'aria-labelledby': firstNameId,
105 + },
106 + 'Sebastian',
107 + ),
108 + React.createElement(
109 + 'h2',
110 + {
111 + id: lastNameId,
112 + },
113 + 'Last',
114 + ),
115 + React.createElement(
116 + 'p',
117 + {
118 + 'aria-labelledby': lastNameId,
119 + },
120 + 'Smith',
121 + ),
122 + );
123 + }
124
115 - const html = await ReactHTML.renderToMarkup(<Component />);
116 - const container = document.createElement('div');
117 - container.innerHTML = html;
118 -
119 - expect(container.getElementsByTagName('h2')[0].id).toBe(
120 - container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
121 - );
122 - expect(container.getElementsByTagName('h2')[1].id).toBe(
123 - container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
124 - );
125 -
126 - // It's not the same id between them.
127 - expect(container.getElementsByTagName('h2')[0].id).not.toBe(
128 - container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
129 - );
130 - });
125 + const html = await ReactHTML.renderToMarkup(<Component />);
126 + const container = document.createElement('div');
127 + container.innerHTML = html;
128
132 - // @gate disableClientCache
133 - it('does NOT support cache yet because it is a client component', async () => {
134 - let counter = 0;
135 - const getCount = React.cache(() => {
136 - return counter++;
137 - });
138 - function Component() {
139 - const a = getCount();
140 - const b = getCount();
141 - return (
142 - <div>
143 - {a}
144 - {b}
145 - </div>
129 + expect(container.getElementsByTagName('h2')[0].id).toBe(
130 + container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
131 );
147 - }
132 + expect(container.getElementsByTagName('h2')[1].id).toBe(
133 + container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
134 + );
135 +
136 + // It's not the same id between them.
137 + expect(container.getElementsByTagName('h2')[0].id).not.toBe(
138 + container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
139 + );
140 + });
141 +
142 + // @gate disableClientCache
143 + it('does NOT support cache yet because it is a client component', async () => {
144 + let counter = 0;
145 + const getCount = React.cache(() => {
146 + return counter++;
147 + });
148 + function Component() {
149 + const a = getCount();
150 + const b = getCount();
151 + return (
152 + <div>
153 + {a}
154 + {b}
155 + </div>
156 + );
157 + }
158
149 - const html = await ReactHTML.renderToMarkup(<Component />);
150 - expect(html).toBe('<div>01</div>');
159 + const html = await ReactHTML.renderToMarkup(<Component />);
160 + expect(html).toBe('<div>01</div>');
161 + });
162 });
152 -});
163 +}
packages/react-html/src/__tests__/ReactHTMLServer-test.js
+157 -129
@@ -15,150 +15,178 @@ global.TextEncoder = require('util').TextEncoder;
15 let React;
16 let ReactHTML;
17
18 -describe('ReactHTML', () => {
19 - beforeEach(() => {
20 - jest.resetModules();
21 - // We run in the react-server condition.
22 - jest.mock('react', () => require('react/react.react-server'));
23 - jest.mock('react-html', () =>
24 - require('react-html/react-html.react-server'),
25 - );
26 -
27 - React = require('react');
28 - ReactHTML = require('react-html');
18 +if (!__EXPERIMENTAL__) {
19 + it('should not be built in stable', () => {
20 + try {
21 + require('react-html');
22 + } catch (x) {
23 + return;
24 + }
25 + throw new Error('Expected react-html not to exist in stable.');
26 });
27 +} else {
28 + describe('ReactHTML', () => {
29 + beforeEach(() => {
30 + jest.resetModules();
31 + // We run in the react-server condition.
32 + jest.mock('react', () => require('react/react.react-server'));
33 + if (__EXPERIMENTAL__) {
34 + jest.mock('react-html', () =>
35 + require('react-html/react-html.react-server'),
36 + );
37 + }
38
31 - it('should be able to render a simple component', async () => {
32 - function Component() {
33 - // We can't use JSX because that's client-JSX in our tests.
34 - return React.createElement('div', null, 'hello world');
35 - }
39 + React = require('react');
40 + if (__EXPERIMENTAL__) {
41 + ReactHTML = require('react-html');
42 + } else {
43 + try {
44 + require('react-html/react-html.react-server');
45 + } catch (x) {
46 + return;
47 + }
48 + throw new Error('Expected react-html not to exist in stable.');
49 + }
50 + });
51
37 - const html = await ReactHTML.renderToMarkup(React.createElement(Component));
38 - expect(html).toBe('<div>hello world</div>');
39 - });
52 + it('should be able to render a simple component', async () => {
53 + function Component() {
54 + // We can't use JSX because that's client-JSX in our tests.
55 + return React.createElement('div', null, 'hello world');
56 + }
57
41 - it('should prefix html tags with a doctype', async () => {
42 - const html = await ReactHTML.renderToMarkup(
43 - // We can't use JSX because that's client-JSX in our tests.
44 - React.createElement(
45 - 'html',
46 - null,
47 - React.createElement('body', null, 'hello'),
48 - ),
49 - );
50 - expect(html).toBe(
51 - '<!DOCTYPE html><html><head></head><body>hello</body></html>',
52 - );
53 - });
58 + const html = await ReactHTML.renderToMarkup(
59 + React.createElement(Component),
60 + );
61 + expect(html).toBe('<div>hello world</div>');
62 + });
63
55 - it('should error on useState', async () => {
56 - function Component() {
57 - const [state] = React.useState('hello');
58 - // We can't use JSX because that's client-JSX in our tests.
59 - return React.createElement('div', null, state);
60 - }
64 + it('should prefix html tags with a doctype', async () => {
65 + const html = await ReactHTML.renderToMarkup(
66 + // We can't use JSX because that's client-JSX in our tests.
67 + React.createElement(
68 + 'html',
69 + null,
70 + React.createElement('body', null, 'hello'),
71 + ),
72 + );
73 + expect(html).toBe(
74 + '<!DOCTYPE html><html><head></head><body>hello</body></html>',
75 + );
76 + });
77
62 - await expect(async () => {
63 - await ReactHTML.renderToMarkup(React.createElement(Component));
64 - }).rejects.toThrow();
65 - });
78 + it('should error on useState', async () => {
79 + function Component() {
80 + const [state] = React.useState('hello');
81 + // We can't use JSX because that's client-JSX in our tests.
82 + return React.createElement('div', null, state);
83 + }
84
67 - it('should error on refs passed to host components', async () => {
68 - function Component() {
69 - const ref = React.createRef();
70 - // We can't use JSX because that's client-JSX in our tests.
71 - return React.createElement('div', {ref});
72 - }
85 + await expect(async () => {
86 + await ReactHTML.renderToMarkup(React.createElement(Component));
87 + }).rejects.toThrow();
88 + });
89
74 - await expect(async () => {
75 - await ReactHTML.renderToMarkup(React.createElement(Component));
76 - }).rejects.toThrow();
77 - });
90 + it('should error on refs passed to host components', async () => {
91 + function Component() {
92 + const ref = React.createRef();
93 + // We can't use JSX because that's client-JSX in our tests.
94 + return React.createElement('div', {ref});
95 + }
96 +
97 + await expect(async () => {
98 + await ReactHTML.renderToMarkup(React.createElement(Component));
99 + }).rejects.toThrow();
100 + });
101
79 - it('should error on callbacks passed to event handlers', async () => {
80 - function Component() {
81 - function onClick() {
82 - // This won't be able to be called.
102 + it('should error on callbacks passed to event handlers', async () => {
103 + function Component() {
104 + function onClick() {
105 + // This won't be able to be called.
106 + }
107 + // We can't use JSX because that's client-JSX in our tests.
108 + return React.createElement('div', {onClick});
109 }
84 - // We can't use JSX because that's client-JSX in our tests.
85 - return React.createElement('div', {onClick});
86 - }
110
88 - await expect(async () => {
89 - await ReactHTML.renderToMarkup(React.createElement(Component));
90 - }).rejects.toThrow();
91 - });
111 + await expect(async () => {
112 + await ReactHTML.renderToMarkup(React.createElement(Component));
113 + }).rejects.toThrow();
114 + });
115
93 - it('supports the useId Hook', async () => {
94 - function Component() {
95 - const firstNameId = React.useId();
96 - const lastNameId = React.useId();
97 - // We can't use JSX because that's client-JSX in our tests.
98 - return React.createElement(
99 - 'div',
100 - null,
101 - React.createElement(
102 - 'h2',
103 - {
104 - id: firstNameId,
105 - },
106 - 'First',
107 - ),
108 - React.createElement(
109 - 'p',
110 - {
111 - 'aria-labelledby': firstNameId,
112 - },
113 - 'Sebastian',
114 - ),
115 - React.createElement(
116 - 'h2',
117 - {
118 - id: lastNameId,
119 - },
120 - 'Last',
121 - ),
122 - React.createElement(
123 - 'p',
124 - {
125 - 'aria-labelledby': lastNameId,
126 - },
127 - 'Smith',
128 - ),
116 + it('supports the useId Hook', async () => {
117 + function Component() {
118 + const firstNameId = React.useId();
119 + const lastNameId = React.useId();
120 + // We can't use JSX because that's client-JSX in our tests.
121 + return React.createElement(
122 + 'div',
123 + null,
124 + React.createElement(
125 + 'h2',
126 + {
127 + id: firstNameId,
128 + },
129 + 'First',
130 + ),
131 + React.createElement(
132 + 'p',
133 + {
134 + 'aria-labelledby': firstNameId,
135 + },
136 + 'Sebastian',
137 + ),
138 + React.createElement(
139 + 'h2',
140 + {
141 + id: lastNameId,
142 + },
143 + 'Last',
144 + ),
145 + React.createElement(
146 + 'p',
147 + {
148 + 'aria-labelledby': lastNameId,
149 + },
150 + 'Smith',
151 + ),
152 + );
153 + }
154 +
155 + const html = await ReactHTML.renderToMarkup(
156 + React.createElement(Component),
157 );
130 - }
158 + const container = document.createElement('div');
159 + container.innerHTML = html;
160
132 - const html = await ReactHTML.renderToMarkup(React.createElement(Component));
133 - const container = document.createElement('div');
134 - container.innerHTML = html;
135 -
136 - expect(container.getElementsByTagName('h2')[0].id).toBe(
137 - container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
138 - );
139 - expect(container.getElementsByTagName('h2')[1].id).toBe(
140 - container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
141 - );
142 -
143 - // It's not the same id between them.
144 - expect(container.getElementsByTagName('h2')[0].id).not.toBe(
145 - container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
146 - );
147 - });
161 + expect(container.getElementsByTagName('h2')[0].id).toBe(
162 + container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
163 + );
164 + expect(container.getElementsByTagName('h2')[1].id).toBe(
165 + container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
166 + );
167
149 - // @gate enableCache
150 - it('supports cache', async () => {
151 - let counter = 0;
152 - const getCount = React.cache(() => {
153 - return counter++;
168 + // It's not the same id between them.
169 + expect(container.getElementsByTagName('h2')[0].id).not.toBe(
170 + container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
171 + );
172 });
155 - function Component() {
156 - const a = getCount();
157 - const b = getCount();
158 - return React.createElement('div', null, a, b);
159 - }
173
161 - const html = await ReactHTML.renderToMarkup(React.createElement(Component));
162 - expect(html).toBe('<div>00</div>');
174 + // @gate enableCache
175 + it('supports cache', async () => {
176 + let counter = 0;
177 + const getCount = React.cache(() => {
178 + return counter++;
179 + });
180 + function Component() {
181 + const a = getCount();
182 + const b = getCount();
183 + return React.createElement('div', null, a, b);
184 + }
185 +
186 + const html = await ReactHTML.renderToMarkup(
187 + React.createElement(Component),
188 + );
189 + expect(html).toBe('<div>00</div>');
190 + });
191 });
164 -});
192 +}
scripts/rollup/bundles.js
+2 -2
@@ -365,7 +365,7 @@ const bundles = [
365
366 /******* React HTML RSC *******/
367 {
368 - bundleTypes: [NODE_DEV, NODE_PROD],
368 + bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
369 moduleType: RENDERER,
370 entry: 'react-html/src/ReactHTMLServer.js',
371 name: 'react-html.react-server',
@@ -378,7 +378,7 @@ const bundles = [
378
379 /******* React HTML Client *******/
380 {
381 - bundleTypes: [NODE_DEV, NODE_PROD],
381 + bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
382 moduleType: RENDERER,
383 entry: 'react-html/src/ReactHTMLClient.js',
384 name: 'react-html',