@vitejs/plugin-react-swc 3.0.1 → 3.1.0-beta.2

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 CHANGED
@@ -24,7 +24,7 @@ export default defineConfig({
24
24
 
25
25
  ## Caveats
26
26
 
27
- This plugin is only used in development and aims to be kept simple to enable good performances and be transpiler agnostic. Here is the list of non-configurable options that impact runtime behaviour:
27
+ This plugin has limited options to enable good performances and be transpiler agnostic. Here is the list of non-configurable options that impact runtime behaviour:
28
28
 
29
29
  - [useDefineForClassFields](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) is always activated, as this matches the current ECMAScript spec
30
30
  - `jsx runtime` is always `automatic`
@@ -34,17 +34,30 @@ This plugin is only used in development and aims to be kept simple to enable goo
34
34
  - JS files are not transformed
35
35
  - tsconfig is not resolved, so properties other than the ones listed above behaves like TS defaults
36
36
 
37
- ## Changing the JSX import source
37
+ ## Options
38
38
 
39
- You can use the jsxImportSource option like this:
39
+ ### jsxImportSource
40
+
41
+ Control where the JSX factory is imported from.
40
42
 
41
43
  ```ts
42
- import { defineConfig } from "vite";
43
- import react from "@vitejs/plugin-react-swc";
44
+ react({ jsxImportSource: "@emotion/react" });
45
+ ```
44
46
 
45
- export default defineConfig({
46
- plugins: [react({ jsxImportSource: "@emotion/react" })],
47
- });
47
+ ### tsDecorators
48
+
49
+ Enable TypeScript decorators. Requires `experimentalDecorators` in tsconfig.
50
+
51
+ ```ts
52
+ react({ tsDecorators: true });
53
+ ```
54
+
55
+ ## plugins
56
+
57
+ Use SWC plugins. Enable SWC at build time.
58
+
59
+ ```ts
60
+ react({ plugins: [["@swc/plugin-styled-components", {}]] });
48
61
  ```
49
62
 
50
63
  ## Consistent components exports
package/index.cjs CHANGED
@@ -3,6 +3,7 @@ var import_fs = require("fs");
3
3
  var import_path = require("path");
4
4
  var import_url = require("url");
5
5
  var import_core = require("@swc/core");
6
+ var import_module = require("module");
6
7
  var import_meta = {};
7
8
  var runtimePublicPath = "/@react-refresh";
8
9
  var preambleCode = `import { injectIntoGlobalHook } from "__PATH__";
@@ -10,72 +11,51 @@ injectIntoGlobalHook(window);
10
11
  window.$RefreshReg$ = () => {};
11
12
  window.$RefreshSig$ = () => (type) => type;`;
12
13
  var _dirname = typeof __dirname !== "undefined" ? __dirname : (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
14
+ var resolve = (0, import_module.createRequire)(
15
+ typeof __filename !== "undefined" ? __filename : import_meta.url
16
+ ).resolve;
13
17
  var refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/;
14
- var react = (options) => [
15
- {
16
- name: "vite:react-swc",
17
- apply: "serve",
18
- config: () => ({
19
- esbuild: false,
20
- optimizeDeps: { include: ["react/jsx-dev-runtime"] }
21
- }),
22
- resolveId: (id) => id === runtimePublicPath ? id : void 0,
23
- load: (id) => id === runtimePublicPath ? (0, import_fs.readFileSync)((0, import_path.join)(_dirname, "refresh-runtime.js"), "utf-8") : void 0,
24
- transformIndexHtml: (_, config) => [
25
- {
26
- tag: "script",
27
- attrs: { type: "module" },
28
- children: preambleCode.replace(
29
- "__PATH__",
30
- config.server.config.base + runtimePublicPath.slice(1)
31
- )
32
- }
33
- ],
34
- async transform(code, _id, transformOptions) {
35
- const id = _id.split("?")[0];
36
- if (id.includes("node_modules"))
37
- return;
38
- const parser = id.endsWith(".tsx") ? { syntax: "typescript", tsx: true } : id.endsWith(".ts") ? { syntax: "typescript", tsx: false } : id.endsWith(".jsx") ? { syntax: "ecmascript", jsx: true } : void 0;
39
- if (!parser)
40
- return;
41
- let result;
42
- try {
43
- result = await (0, import_core.transform)(code, {
44
- filename: id,
45
- swcrc: false,
46
- configFile: false,
47
- sourceMaps: true,
48
- jsc: {
49
- target: "es2020",
50
- parser,
51
- transform: {
52
- useDefineForClassFields: true,
53
- react: {
54
- refresh: !(transformOptions == null ? void 0 : transformOptions.ssr),
55
- development: true,
56
- useBuiltins: true,
57
- runtime: "automatic",
58
- importSource: options == null ? void 0 : options.jsxImportSource
59
- }
60
- }
61
- }
18
+ var react = (_options) => {
19
+ const options = {
20
+ jsxImportSource: _options == null ? void 0 : _options.jsxImportSource,
21
+ tsDecorators: _options == null ? void 0 : _options.tsDecorators,
22
+ plugins: (_options == null ? void 0 : _options.plugins) ? _options == null ? void 0 : _options.plugins.map((el) => [resolve(el[0]), el[1]]) : void 0
23
+ };
24
+ return [
25
+ {
26
+ name: "vite:react-swc",
27
+ apply: "serve",
28
+ config: () => ({
29
+ esbuild: false,
30
+ optimizeDeps: { include: ["react/jsx-dev-runtime"] }
31
+ }),
32
+ resolveId: (id) => id === runtimePublicPath ? id : void 0,
33
+ load: (id) => id === runtimePublicPath ? (0, import_fs.readFileSync)((0, import_path.join)(_dirname, "refresh-runtime.js"), "utf-8") : void 0,
34
+ transformIndexHtml: (_, config) => [
35
+ {
36
+ tag: "script",
37
+ attrs: { type: "module" },
38
+ children: preambleCode.replace(
39
+ "__PATH__",
40
+ config.server.config.base + runtimePublicPath.slice(1)
41
+ )
42
+ }
43
+ ],
44
+ async transform(code, _id, transformOptions) {
45
+ const id = _id.split("?")[0];
46
+ const result = await transformWithOptions(id, code, options, {
47
+ refresh: !(transformOptions == null ? void 0 : transformOptions.ssr),
48
+ development: true,
49
+ useBuiltins: true,
50
+ runtime: "automatic",
51
+ importSource: options == null ? void 0 : options.jsxImportSource
62
52
  });
63
- } catch (e) {
64
- const message = e.message;
65
- const fileStartIndex = message.indexOf("\u256D\u2500[");
66
- if (fileStartIndex !== -1) {
67
- const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/);
68
- if (match) {
69
- e.line = match[1];
70
- e.column = match[2];
71
- }
53
+ if (!result)
54
+ return;
55
+ if ((transformOptions == null ? void 0 : transformOptions.ssr) || !refreshContentRE.test(result.code)) {
56
+ return result;
72
57
  }
73
- throw e;
74
- }
75
- if ((transformOptions == null ? void 0 : transformOptions.ssr) || !refreshContentRE.test(result.code)) {
76
- return result;
77
- }
78
- result.code = `import * as RefreshRuntime from "${runtimePublicPath}";
58
+ result.code = `import * as RefreshRuntime from "${runtimePublicPath}";
79
59
 
80
60
  if (!window.$RefreshReg$) throw new Error("React refresh preamble was not loaded. Something is wrong.");
81
61
  const prevRefreshReg = window.$RefreshReg$;
@@ -87,31 +67,81 @@ var react = (options) => [
87
67
 
88
68
  window.$RefreshReg$ = prevRefreshReg;
89
69
  window.$RefreshSig$ = prevRefreshSig;
90
- import.meta.hot.accept((nextExports) => {
91
- if (!nextExports) return;
92
- import(/* @vite-ignore */ import.meta.url).then((current) => {
93
- const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(current, nextExports);
94
- if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
70
+ import(/* @vite-ignore */ import.meta.url).then((currentExports) => {
71
+ RefreshRuntime.registerExportsForReactRefresh("${id}", currentExports);
72
+ import.meta.hot.accept((nextExports) => {
73
+ if (!nextExports) return;
74
+ const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports);
75
+ if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
76
+ });
95
77
  });
96
- });
97
78
  `;
98
- const sourceMap = JSON.parse(result.map);
99
- sourceMap.mappings = ";;;;;;;;" + sourceMap.mappings;
100
- return { code: result.code, map: sourceMap };
79
+ const sourceMap = JSON.parse(result.map);
80
+ sourceMap.mappings = ";;;;;;;;" + sourceMap.mappings;
81
+ return { code: result.code, map: sourceMap };
82
+ }
83
+ },
84
+ options.plugins ? {
85
+ name: "vite:react-swc",
86
+ apply: "build",
87
+ transform: (code, _id) => transformWithOptions(_id.split("?")[0], code, options, {
88
+ useBuiltins: true,
89
+ runtime: "automatic",
90
+ importSource: options == null ? void 0 : options.jsxImportSource
91
+ })
92
+ } : {
93
+ name: "vite:react-swc",
94
+ apply: "build",
95
+ config: () => ({
96
+ esbuild: {
97
+ jsx: "automatic",
98
+ jsxImportSource: options == null ? void 0 : options.jsxImportSource,
99
+ tsconfigRaw: {
100
+ compilerOptions: { useDefineForClassFields: true }
101
+ }
102
+ }
103
+ })
101
104
  }
102
- },
103
- {
104
- name: "vite:react-swc",
105
- apply: "build",
106
- config: () => ({
107
- esbuild: {
108
- jsx: "automatic",
109
- jsxImportSource: options == null ? void 0 : options.jsxImportSource,
110
- tsconfigRaw: { compilerOptions: { useDefineForClassFields: true } }
105
+ ];
106
+ };
107
+ var transformWithOptions = async (id, code, options, reactConfig) => {
108
+ if (id.includes("node_modules"))
109
+ return;
110
+ const decorators = (options == null ? void 0 : options.tsDecorators) ?? false;
111
+ const parser = id.endsWith(".tsx") ? { syntax: "typescript", tsx: true, decorators } : id.endsWith(".ts") ? { syntax: "typescript", tsx: false, decorators } : id.endsWith(".jsx") ? { syntax: "ecmascript", jsx: true } : void 0;
112
+ if (!parser)
113
+ return;
114
+ let result;
115
+ try {
116
+ result = await (0, import_core.transform)(code, {
117
+ filename: id,
118
+ swcrc: false,
119
+ configFile: false,
120
+ sourceMaps: true,
121
+ jsc: {
122
+ target: "es2020",
123
+ parser,
124
+ experimental: { plugins: options.plugins },
125
+ transform: {
126
+ useDefineForClassFields: true,
127
+ react: reactConfig
128
+ }
129
+ }
130
+ });
131
+ } catch (e) {
132
+ const message = e.message;
133
+ const fileStartIndex = message.indexOf("\u256D\u2500[");
134
+ if (fileStartIndex !== -1) {
135
+ const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/);
136
+ if (match) {
137
+ e.line = match[1];
138
+ e.column = match[2];
111
139
  }
112
- })
140
+ }
141
+ throw e;
113
142
  }
114
- ];
143
+ return result;
144
+ };
115
145
  var src_default = react;
116
146
 
117
147
  // <stdin>
package/index.d.ts CHANGED
@@ -5,6 +5,16 @@ type Options = {
5
5
  * @default "react"
6
6
  */
7
7
  jsxImportSource?: string;
8
+ /**
9
+ * Enable TypeScript decorators. Requires experimentalDecorators in tsconfig.
10
+ * @default false
11
+ */
12
+ tsDecorators?: boolean;
13
+ /**
14
+ * Use SWC plugins. Enable SWC at build time.
15
+ * @default undefined
16
+ */
17
+ plugins?: [string, Record<string, any>][];
8
18
  };
9
- declare const react: (options?: Options) => PluginOption[];
19
+ declare const react: (_options?: Options) => PluginOption[];
10
20
  export default react;
package/index.mjs CHANGED
@@ -3,78 +3,58 @@ import { readFileSync } from "fs";
3
3
  import { dirname, join } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import { transform } from "@swc/core";
6
+ import { createRequire } from "module";
6
7
  var runtimePublicPath = "/@react-refresh";
7
8
  var preambleCode = `import { injectIntoGlobalHook } from "__PATH__";
8
9
  injectIntoGlobalHook(window);
9
10
  window.$RefreshReg$ = () => {};
10
11
  window.$RefreshSig$ = () => (type) => type;`;
11
12
  var _dirname = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
13
+ var resolve = createRequire(
14
+ typeof __filename !== "undefined" ? __filename : import.meta.url
15
+ ).resolve;
12
16
  var refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/;
13
- var react = (options) => [
14
- {
15
- name: "vite:react-swc",
16
- apply: "serve",
17
- config: () => ({
18
- esbuild: false,
19
- optimizeDeps: { include: ["react/jsx-dev-runtime"] }
20
- }),
21
- resolveId: (id) => id === runtimePublicPath ? id : void 0,
22
- load: (id) => id === runtimePublicPath ? readFileSync(join(_dirname, "refresh-runtime.js"), "utf-8") : void 0,
23
- transformIndexHtml: (_, config) => [
24
- {
25
- tag: "script",
26
- attrs: { type: "module" },
27
- children: preambleCode.replace(
28
- "__PATH__",
29
- config.server.config.base + runtimePublicPath.slice(1)
30
- )
31
- }
32
- ],
33
- async transform(code, _id, transformOptions) {
34
- const id = _id.split("?")[0];
35
- if (id.includes("node_modules"))
36
- return;
37
- const parser = id.endsWith(".tsx") ? { syntax: "typescript", tsx: true } : id.endsWith(".ts") ? { syntax: "typescript", tsx: false } : id.endsWith(".jsx") ? { syntax: "ecmascript", jsx: true } : void 0;
38
- if (!parser)
39
- return;
40
- let result;
41
- try {
42
- result = await transform(code, {
43
- filename: id,
44
- swcrc: false,
45
- configFile: false,
46
- sourceMaps: true,
47
- jsc: {
48
- target: "es2020",
49
- parser,
50
- transform: {
51
- useDefineForClassFields: true,
52
- react: {
53
- refresh: !(transformOptions == null ? void 0 : transformOptions.ssr),
54
- development: true,
55
- useBuiltins: true,
56
- runtime: "automatic",
57
- importSource: options == null ? void 0 : options.jsxImportSource
58
- }
59
- }
60
- }
17
+ var react = (_options) => {
18
+ const options = {
19
+ jsxImportSource: _options == null ? void 0 : _options.jsxImportSource,
20
+ tsDecorators: _options == null ? void 0 : _options.tsDecorators,
21
+ plugins: (_options == null ? void 0 : _options.plugins) ? _options == null ? void 0 : _options.plugins.map((el) => [resolve(el[0]), el[1]]) : void 0
22
+ };
23
+ return [
24
+ {
25
+ name: "vite:react-swc",
26
+ apply: "serve",
27
+ config: () => ({
28
+ esbuild: false,
29
+ optimizeDeps: { include: ["react/jsx-dev-runtime"] }
30
+ }),
31
+ resolveId: (id) => id === runtimePublicPath ? id : void 0,
32
+ load: (id) => id === runtimePublicPath ? readFileSync(join(_dirname, "refresh-runtime.js"), "utf-8") : void 0,
33
+ transformIndexHtml: (_, config) => [
34
+ {
35
+ tag: "script",
36
+ attrs: { type: "module" },
37
+ children: preambleCode.replace(
38
+ "__PATH__",
39
+ config.server.config.base + runtimePublicPath.slice(1)
40
+ )
41
+ }
42
+ ],
43
+ async transform(code, _id, transformOptions) {
44
+ const id = _id.split("?")[0];
45
+ const result = await transformWithOptions(id, code, options, {
46
+ refresh: !(transformOptions == null ? void 0 : transformOptions.ssr),
47
+ development: true,
48
+ useBuiltins: true,
49
+ runtime: "automatic",
50
+ importSource: options == null ? void 0 : options.jsxImportSource
61
51
  });
62
- } catch (e) {
63
- const message = e.message;
64
- const fileStartIndex = message.indexOf("\u256D\u2500[");
65
- if (fileStartIndex !== -1) {
66
- const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/);
67
- if (match) {
68
- e.line = match[1];
69
- e.column = match[2];
70
- }
52
+ if (!result)
53
+ return;
54
+ if ((transformOptions == null ? void 0 : transformOptions.ssr) || !refreshContentRE.test(result.code)) {
55
+ return result;
71
56
  }
72
- throw e;
73
- }
74
- if ((transformOptions == null ? void 0 : transformOptions.ssr) || !refreshContentRE.test(result.code)) {
75
- return result;
76
- }
77
- result.code = `import * as RefreshRuntime from "${runtimePublicPath}";
57
+ result.code = `import * as RefreshRuntime from "${runtimePublicPath}";
78
58
 
79
59
  if (!window.$RefreshReg$) throw new Error("React refresh preamble was not loaded. Something is wrong.");
80
60
  const prevRefreshReg = window.$RefreshReg$;
@@ -86,31 +66,81 @@ var react = (options) => [
86
66
 
87
67
  window.$RefreshReg$ = prevRefreshReg;
88
68
  window.$RefreshSig$ = prevRefreshSig;
89
- import.meta.hot.accept((nextExports) => {
90
- if (!nextExports) return;
91
- import(/* @vite-ignore */ import.meta.url).then((current) => {
92
- const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(current, nextExports);
93
- if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
69
+ import(/* @vite-ignore */ import.meta.url).then((currentExports) => {
70
+ RefreshRuntime.registerExportsForReactRefresh("${id}", currentExports);
71
+ import.meta.hot.accept((nextExports) => {
72
+ if (!nextExports) return;
73
+ const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports);
74
+ if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
75
+ });
94
76
  });
95
- });
96
77
  `;
97
- const sourceMap = JSON.parse(result.map);
98
- sourceMap.mappings = ";;;;;;;;" + sourceMap.mappings;
99
- return { code: result.code, map: sourceMap };
78
+ const sourceMap = JSON.parse(result.map);
79
+ sourceMap.mappings = ";;;;;;;;" + sourceMap.mappings;
80
+ return { code: result.code, map: sourceMap };
81
+ }
82
+ },
83
+ options.plugins ? {
84
+ name: "vite:react-swc",
85
+ apply: "build",
86
+ transform: (code, _id) => transformWithOptions(_id.split("?")[0], code, options, {
87
+ useBuiltins: true,
88
+ runtime: "automatic",
89
+ importSource: options == null ? void 0 : options.jsxImportSource
90
+ })
91
+ } : {
92
+ name: "vite:react-swc",
93
+ apply: "build",
94
+ config: () => ({
95
+ esbuild: {
96
+ jsx: "automatic",
97
+ jsxImportSource: options == null ? void 0 : options.jsxImportSource,
98
+ tsconfigRaw: {
99
+ compilerOptions: { useDefineForClassFields: true }
100
+ }
101
+ }
102
+ })
100
103
  }
101
- },
102
- {
103
- name: "vite:react-swc",
104
- apply: "build",
105
- config: () => ({
106
- esbuild: {
107
- jsx: "automatic",
108
- jsxImportSource: options == null ? void 0 : options.jsxImportSource,
109
- tsconfigRaw: { compilerOptions: { useDefineForClassFields: true } }
104
+ ];
105
+ };
106
+ var transformWithOptions = async (id, code, options, reactConfig) => {
107
+ if (id.includes("node_modules"))
108
+ return;
109
+ const decorators = (options == null ? void 0 : options.tsDecorators) ?? false;
110
+ const parser = id.endsWith(".tsx") ? { syntax: "typescript", tsx: true, decorators } : id.endsWith(".ts") ? { syntax: "typescript", tsx: false, decorators } : id.endsWith(".jsx") ? { syntax: "ecmascript", jsx: true } : void 0;
111
+ if (!parser)
112
+ return;
113
+ let result;
114
+ try {
115
+ result = await transform(code, {
116
+ filename: id,
117
+ swcrc: false,
118
+ configFile: false,
119
+ sourceMaps: true,
120
+ jsc: {
121
+ target: "es2020",
122
+ parser,
123
+ experimental: { plugins: options.plugins },
124
+ transform: {
125
+ useDefineForClassFields: true,
126
+ react: reactConfig
127
+ }
110
128
  }
111
- })
129
+ });
130
+ } catch (e) {
131
+ const message = e.message;
132
+ const fileStartIndex = message.indexOf("\u256D\u2500[");
133
+ if (fileStartIndex !== -1) {
134
+ const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/);
135
+ if (match) {
136
+ e.line = match[1];
137
+ e.column = match[2];
138
+ }
139
+ }
140
+ throw e;
112
141
  }
113
- ];
142
+ return result;
143
+ };
114
144
  var src_default = react;
115
145
  export {
116
146
  src_default as default
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react-swc",
3
3
  "description": "Speed up your Vite dev server with SWC",
4
- "version": "3.0.1",
4
+ "version": "3.1.0-beta.2",
5
5
  "author": "Arnaud Barré (https://github.com/ArnaudBarre)",
6
6
  "license": "MIT",
7
7
  "repository": "github:vitejs/vite-plugin-react-swc",
@@ -27,6 +27,6 @@
27
27
  "vite": "^4"
28
28
  },
29
29
  "dependencies": {
30
- "@swc/core": "^1.3.22"
30
+ "@swc/core": "^1.3.26"
31
31
  }
32
32
  }
@@ -111,7 +111,9 @@ function performReactRefresh() {
111
111
  });
112
112
  let update = {
113
113
  updatedFamilies,
114
+ // Families that will re-render preserving state
114
115
  staleFamilies
116
+ // Families that will be remounted
115
117
  };
116
118
  helpersByRendererID.forEach(function(helpers) {
117
119
  helpers.setRefreshHandler(resolveFamily);
@@ -375,6 +377,16 @@ function isLikelyComponentType(type) {
375
377
  }
376
378
  }
377
379
  }
380
+ function registerExportsForReactRefresh(filename, moduleExports) {
381
+ for (const key in moduleExports) {
382
+ if (key === "__esModule")
383
+ continue;
384
+ const exportValue = moduleExports[key];
385
+ if (isLikelyComponentType(exportValue)) {
386
+ register(exportValue, filename + " " + key);
387
+ }
388
+ }
389
+ }
378
390
  function validateRefreshBoundaryAndEnqueueUpdate(prevExports, nextExports) {
379
391
  if (!predicateOnExport(prevExports, (key) => !!nextExports[key])) {
380
392
  return "Could not Fast Refresh (export removed)";
@@ -409,16 +421,12 @@ function predicateOnExport(moduleExports, predicate) {
409
421
  }
410
422
  return true;
411
423
  }
412
- var refresh_runtime_default = {
413
- getRefreshReg,
414
- injectIntoGlobalHook,
415
- createSignatureFunctionForTransform,
416
- validateRefreshBoundaryAndEnqueueUpdate
417
- };
424
+ var refresh_runtime_default = { injectIntoGlobalHook };
418
425
  export {
419
426
  createSignatureFunctionForTransform,
420
427
  refresh_runtime_default as default,
421
428
  getRefreshReg,
422
429
  injectIntoGlobalHook,
430
+ registerExportsForReactRefresh,
423
431
  validateRefreshBoundaryAndEnqueueUpdate
424
432
  };