@vitejs/plugin-react 3.0.0 → 3.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.cjs +19 -52
- package/dist/index.mjs +19 -52
- package/dist/refreshUtils.js +57 -0
- package/package.json +6 -5
package/README.md
CHANGED
@@ -105,3 +105,11 @@ Otherwise, you'll probably get this error:
|
|
105
105
|
```
|
106
106
|
Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.
|
107
107
|
```
|
108
|
+
|
109
|
+
## Consistent components exports
|
110
|
+
|
111
|
+
For React refresh to work correctly, your file should only export React components. You can find a good explanation in the [Gatsby docs](https://www.gatsbyjs.com/docs/reference/local-development/fast-refresh/#how-it-works).
|
112
|
+
|
113
|
+
If an incompatible change in exports is found, the module will be invalidated and HMR will propagate. To make it easier to export simple constants alongside your component, the module is only invalidated when their value changes.
|
114
|
+
|
115
|
+
You can catch mistakes and get more detailed warning with this [eslint rule](https://github.com/ArnaudBarre/eslint-plugin-react-refresh).
|
package/dist/index.cjs
CHANGED
@@ -32,14 +32,7 @@ const runtimeFilePath = path.join(
|
|
32
32
|
const runtimeCode = `
|
33
33
|
const exports = {}
|
34
34
|
${fs.readFileSync(runtimeFilePath, "utf-8")}
|
35
|
-
|
36
|
-
let handle
|
37
|
-
return () => {
|
38
|
-
clearTimeout(handle)
|
39
|
-
handle = setTimeout(fn, delay)
|
40
|
-
}
|
41
|
-
}
|
42
|
-
exports.performReactRefresh = debounce(exports.performReactRefresh, 16)
|
35
|
+
${fs.readFileSync(_require.resolve("./refreshUtils.js"), "utf-8")}
|
43
36
|
export default exports
|
44
37
|
`;
|
45
38
|
const preambleCode = `
|
@@ -70,59 +63,26 @@ if (import.meta.hot) {
|
|
70
63
|
};
|
71
64
|
window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
|
72
65
|
}`.replace(/\n+/g, "");
|
73
|
-
const timeout = `
|
74
|
-
if (!window.__vite_plugin_react_timeout) {
|
75
|
-
window.__vite_plugin_react_timeout = setTimeout(() => {
|
76
|
-
window.__vite_plugin_react_timeout = 0;
|
77
|
-
RefreshRuntime.performReactRefresh();
|
78
|
-
}, 30);
|
79
|
-
}
|
80
|
-
`;
|
81
|
-
const checkAndAccept = `
|
82
|
-
function isReactRefreshBoundary(mod) {
|
83
|
-
if (mod == null || typeof mod !== 'object') {
|
84
|
-
return false;
|
85
|
-
}
|
86
|
-
let hasExports = false;
|
87
|
-
let areAllExportsComponents = true;
|
88
|
-
for (const exportName in mod) {
|
89
|
-
hasExports = true;
|
90
|
-
if (exportName === '__esModule') {
|
91
|
-
continue;
|
92
|
-
}
|
93
|
-
const desc = Object.getOwnPropertyDescriptor(mod, exportName);
|
94
|
-
if (desc && desc.get) {
|
95
|
-
// Don't invoke getters as they may have side effects.
|
96
|
-
return false;
|
97
|
-
}
|
98
|
-
const exportValue = mod[exportName];
|
99
|
-
if (!RefreshRuntime.isLikelyComponentType(exportValue)) {
|
100
|
-
areAllExportsComponents = false;
|
101
|
-
}
|
102
|
-
}
|
103
|
-
return hasExports && areAllExportsComponents;
|
104
|
-
}
|
105
|
-
|
106
|
-
import.meta.hot.accept(mod => {
|
107
|
-
if (isReactRefreshBoundary(mod)) {
|
108
|
-
${timeout}
|
109
|
-
} else {
|
110
|
-
import.meta.hot.invalidate();
|
111
|
-
}
|
112
|
-
});
|
113
|
-
`;
|
114
66
|
const footer = `
|
115
67
|
if (import.meta.hot) {
|
116
68
|
window.$RefreshReg$ = prevRefreshReg;
|
117
69
|
window.$RefreshSig$ = prevRefreshSig;
|
118
70
|
|
119
|
-
|
71
|
+
import(/* @vite-ignore */ import.meta.url).then((currentExports) => {
|
72
|
+
RefreshRuntime.registerExportsForReactRefresh(__SOURCE__, currentExports);
|
73
|
+
import.meta.hot.accept((nextExports) => {
|
74
|
+
if (!nextExports) return;
|
75
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports);
|
76
|
+
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
|
77
|
+
});
|
78
|
+
});
|
120
79
|
}`;
|
121
80
|
function addRefreshWrapper(code, id) {
|
122
|
-
return header.replace("__SOURCE__", JSON.stringify(id)) + code + footer;
|
81
|
+
return header.replace("__SOURCE__", JSON.stringify(id)) + code + footer.replace("__SOURCE__", JSON.stringify(id));
|
123
82
|
}
|
124
83
|
|
125
84
|
const prependReactImportCode = "import React from 'react'; ";
|
85
|
+
const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/;
|
126
86
|
function viteReact(opts = {}) {
|
127
87
|
let devBase = "/";
|
128
88
|
let filter = vite.createFilter(opts.include, opts.exclude);
|
@@ -269,6 +229,9 @@ function viteReact(opts = {}) {
|
|
269
229
|
const parserPlugins = [
|
270
230
|
...babelOptions.parserOpts.plugins,
|
271
231
|
"importMeta",
|
232
|
+
// This plugin is applied before esbuild transforms the code,
|
233
|
+
// so we need to enable some stage 3 syntax that is supported in
|
234
|
+
// TypeScript and some environments already.
|
272
235
|
"topLevelAwait",
|
273
236
|
"classProperties",
|
274
237
|
"classPrivateProperties",
|
@@ -297,11 +260,12 @@ function viteReact(opts = {}) {
|
|
297
260
|
},
|
298
261
|
plugins,
|
299
262
|
sourceMaps: true,
|
263
|
+
// Vite handles sourcemap flattening
|
300
264
|
inputSourceMap: inputMap ?? false
|
301
265
|
});
|
302
266
|
if (result) {
|
303
267
|
let code2 = result.code;
|
304
|
-
if (useFastRefresh &&
|
268
|
+
if (useFastRefresh && refreshContentRE.test(code2)) {
|
305
269
|
code2 = addRefreshWrapper(code2, id);
|
306
270
|
}
|
307
271
|
return {
|
@@ -351,6 +315,9 @@ function viteReact(opts = {}) {
|
|
351
315
|
config() {
|
352
316
|
return {
|
353
317
|
optimizeDeps: {
|
318
|
+
// We can't add `react-dom` because the dependency is `react-dom/client`
|
319
|
+
// for React 18 while it's `react-dom` for React 17. We'd need to detect
|
320
|
+
// what React version the user has installed.
|
354
321
|
include: [reactJsxRuntimeId, reactJsxDevRuntimeId, "react"]
|
355
322
|
}
|
356
323
|
};
|
package/dist/index.mjs
CHANGED
@@ -17,14 +17,7 @@ const runtimeFilePath = path.join(
|
|
17
17
|
const runtimeCode = `
|
18
18
|
const exports = {}
|
19
19
|
${fs.readFileSync(runtimeFilePath, "utf-8")}
|
20
|
-
|
21
|
-
let handle
|
22
|
-
return () => {
|
23
|
-
clearTimeout(handle)
|
24
|
-
handle = setTimeout(fn, delay)
|
25
|
-
}
|
26
|
-
}
|
27
|
-
exports.performReactRefresh = debounce(exports.performReactRefresh, 16)
|
20
|
+
${fs.readFileSync(_require.resolve("./refreshUtils.js"), "utf-8")}
|
28
21
|
export default exports
|
29
22
|
`;
|
30
23
|
const preambleCode = `
|
@@ -55,59 +48,26 @@ if (import.meta.hot) {
|
|
55
48
|
};
|
56
49
|
window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
|
57
50
|
}`.replace(/\n+/g, "");
|
58
|
-
const timeout = `
|
59
|
-
if (!window.__vite_plugin_react_timeout) {
|
60
|
-
window.__vite_plugin_react_timeout = setTimeout(() => {
|
61
|
-
window.__vite_plugin_react_timeout = 0;
|
62
|
-
RefreshRuntime.performReactRefresh();
|
63
|
-
}, 30);
|
64
|
-
}
|
65
|
-
`;
|
66
|
-
const checkAndAccept = `
|
67
|
-
function isReactRefreshBoundary(mod) {
|
68
|
-
if (mod == null || typeof mod !== 'object') {
|
69
|
-
return false;
|
70
|
-
}
|
71
|
-
let hasExports = false;
|
72
|
-
let areAllExportsComponents = true;
|
73
|
-
for (const exportName in mod) {
|
74
|
-
hasExports = true;
|
75
|
-
if (exportName === '__esModule') {
|
76
|
-
continue;
|
77
|
-
}
|
78
|
-
const desc = Object.getOwnPropertyDescriptor(mod, exportName);
|
79
|
-
if (desc && desc.get) {
|
80
|
-
// Don't invoke getters as they may have side effects.
|
81
|
-
return false;
|
82
|
-
}
|
83
|
-
const exportValue = mod[exportName];
|
84
|
-
if (!RefreshRuntime.isLikelyComponentType(exportValue)) {
|
85
|
-
areAllExportsComponents = false;
|
86
|
-
}
|
87
|
-
}
|
88
|
-
return hasExports && areAllExportsComponents;
|
89
|
-
}
|
90
|
-
|
91
|
-
import.meta.hot.accept(mod => {
|
92
|
-
if (isReactRefreshBoundary(mod)) {
|
93
|
-
${timeout}
|
94
|
-
} else {
|
95
|
-
import.meta.hot.invalidate();
|
96
|
-
}
|
97
|
-
});
|
98
|
-
`;
|
99
51
|
const footer = `
|
100
52
|
if (import.meta.hot) {
|
101
53
|
window.$RefreshReg$ = prevRefreshReg;
|
102
54
|
window.$RefreshSig$ = prevRefreshSig;
|
103
55
|
|
104
|
-
|
56
|
+
import(/* @vite-ignore */ import.meta.url).then((currentExports) => {
|
57
|
+
RefreshRuntime.registerExportsForReactRefresh(__SOURCE__, currentExports);
|
58
|
+
import.meta.hot.accept((nextExports) => {
|
59
|
+
if (!nextExports) return;
|
60
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports);
|
61
|
+
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
|
62
|
+
});
|
63
|
+
});
|
105
64
|
}`;
|
106
65
|
function addRefreshWrapper(code, id) {
|
107
|
-
return header.replace("__SOURCE__", JSON.stringify(id)) + code + footer;
|
66
|
+
return header.replace("__SOURCE__", JSON.stringify(id)) + code + footer.replace("__SOURCE__", JSON.stringify(id));
|
108
67
|
}
|
109
68
|
|
110
69
|
const prependReactImportCode = "import React from 'react'; ";
|
70
|
+
const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/;
|
111
71
|
function viteReact(opts = {}) {
|
112
72
|
let devBase = "/";
|
113
73
|
let filter = createFilter(opts.include, opts.exclude);
|
@@ -254,6 +214,9 @@ function viteReact(opts = {}) {
|
|
254
214
|
const parserPlugins = [
|
255
215
|
...babelOptions.parserOpts.plugins,
|
256
216
|
"importMeta",
|
217
|
+
// This plugin is applied before esbuild transforms the code,
|
218
|
+
// so we need to enable some stage 3 syntax that is supported in
|
219
|
+
// TypeScript and some environments already.
|
257
220
|
"topLevelAwait",
|
258
221
|
"classProperties",
|
259
222
|
"classPrivateProperties",
|
@@ -282,11 +245,12 @@ function viteReact(opts = {}) {
|
|
282
245
|
},
|
283
246
|
plugins,
|
284
247
|
sourceMaps: true,
|
248
|
+
// Vite handles sourcemap flattening
|
285
249
|
inputSourceMap: inputMap ?? false
|
286
250
|
});
|
287
251
|
if (result) {
|
288
252
|
let code2 = result.code;
|
289
|
-
if (useFastRefresh &&
|
253
|
+
if (useFastRefresh && refreshContentRE.test(code2)) {
|
290
254
|
code2 = addRefreshWrapper(code2, id);
|
291
255
|
}
|
292
256
|
return {
|
@@ -336,6 +300,9 @@ function viteReact(opts = {}) {
|
|
336
300
|
config() {
|
337
301
|
return {
|
338
302
|
optimizeDeps: {
|
303
|
+
// We can't add `react-dom` because the dependency is `react-dom/client`
|
304
|
+
// for React 18 while it's `react-dom` for React 17. We'd need to detect
|
305
|
+
// what React version the user has installed.
|
339
306
|
include: [reactJsxRuntimeId, reactJsxDevRuntimeId, "react"]
|
340
307
|
}
|
341
308
|
};
|
@@ -0,0 +1,57 @@
|
|
1
|
+
function debounce(fn, delay) {
|
2
|
+
let handle
|
3
|
+
return () => {
|
4
|
+
clearTimeout(handle)
|
5
|
+
handle = setTimeout(fn, delay)
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
const enqueueUpdate = debounce(exports.performReactRefresh, 16)
|
10
|
+
|
11
|
+
// Taken from https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/lib/runtime/RefreshUtils.js#L141
|
12
|
+
// This allows to resister components not detected by SWC like styled component
|
13
|
+
function registerExportsForReactRefresh(filename, moduleExports) {
|
14
|
+
for (const key in moduleExports) {
|
15
|
+
if (key === '__esModule') continue
|
16
|
+
const exportValue = moduleExports[key]
|
17
|
+
if (exports.isLikelyComponentType(exportValue)) {
|
18
|
+
exports.register(exportValue, filename + ' ' + key)
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
function validateRefreshBoundaryAndEnqueueUpdate(prevExports, nextExports) {
|
24
|
+
if (!predicateOnExport(prevExports, (key) => !!nextExports[key])) {
|
25
|
+
return 'Could not Fast Refresh (export removed)'
|
26
|
+
}
|
27
|
+
|
28
|
+
let hasExports = false
|
29
|
+
const allExportsAreComponentsOrUnchanged = predicateOnExport(
|
30
|
+
nextExports,
|
31
|
+
(key, value) => {
|
32
|
+
hasExports = true
|
33
|
+
if (exports.isLikelyComponentType(value)) return true
|
34
|
+
if (!prevExports[key]) return false
|
35
|
+
return prevExports[key] === nextExports[key]
|
36
|
+
},
|
37
|
+
)
|
38
|
+
if (hasExports && allExportsAreComponentsOrUnchanged) {
|
39
|
+
enqueueUpdate()
|
40
|
+
} else {
|
41
|
+
return 'Could not Fast Refresh. Learn more at https://github.com/vitejs/vite-plugin-react#consistent-components-exports'
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
function predicateOnExport(moduleExports, predicate) {
|
46
|
+
for (const key in moduleExports) {
|
47
|
+
if (key === '__esModule') continue
|
48
|
+
const desc = Object.getOwnPropertyDescriptor(moduleExports, key)
|
49
|
+
if (desc && desc.get) return false
|
50
|
+
if (!predicate(key, moduleExports[key])) return false
|
51
|
+
}
|
52
|
+
return true
|
53
|
+
}
|
54
|
+
|
55
|
+
exports.registerExportsForReactRefresh = registerExportsForReactRefresh
|
56
|
+
exports.validateRefreshBoundaryAndEnqueueUpdate =
|
57
|
+
validateRefreshBoundaryAndEnqueueUpdate
|
package/package.json
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitejs/plugin-react",
|
3
|
-
"version": "3.0.0",
|
3
|
+
"version": "3.1.0-beta.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"author": "Evan You",
|
6
6
|
"contributors": [
|
7
|
-
"Alec Larson"
|
7
|
+
"Alec Larson",
|
8
|
+
"Arnaud Barré"
|
8
9
|
],
|
9
10
|
"files": [
|
10
11
|
"dist"
|
@@ -21,7 +22,7 @@
|
|
21
22
|
},
|
22
23
|
"scripts": {
|
23
24
|
"dev": "unbuild --stub",
|
24
|
-
"build": "unbuild && pnpm run patch-cjs",
|
25
|
+
"build": "unbuild && pnpm run patch-cjs && tsx scripts/copyRefreshUtils.ts",
|
25
26
|
"patch-cjs": "tsx ../../scripts/patchCJS.ts",
|
26
27
|
"prepublishOnly": "npm run build"
|
27
28
|
},
|
@@ -38,13 +39,13 @@
|
|
38
39
|
},
|
39
40
|
"homepage": "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme",
|
40
41
|
"dependencies": {
|
41
|
-
"@babel/core": "^7.20.
|
42
|
+
"@babel/core": "^7.20.12",
|
42
43
|
"@babel/plugin-transform-react-jsx-self": "^7.18.6",
|
43
44
|
"@babel/plugin-transform-react-jsx-source": "^7.19.6",
|
44
45
|
"magic-string": "^0.27.0",
|
45
46
|
"react-refresh": "^0.14.0"
|
46
47
|
},
|
47
48
|
"peerDependencies": {
|
48
|
-
"vite": "^4.0.0"
|
49
|
+
"vite": "^4.1.0-beta.0"
|
49
50
|
}
|
50
51
|
}
|