@vitejs/plugin-react 2.0.0-alpha.2 → 2.0.0-alpha.3

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/dist/index.cjs CHANGED
@@ -173,11 +173,11 @@ async function restoreJSX(babel, code, filename) {
173
173
  return [result?.ast, isCommonJS];
174
174
  }
175
175
  function parseReactAlias(code) {
176
- let match = code.match(/\b(var|let|const) +(\w+) *= *require\(["']react["']\)/);
176
+ let match = code.match(/\b(var|let|const)\s+([^=\{\s]+)\s*=\s*require\(["']react["']\)/);
177
177
  if (match) {
178
178
  return [match[2], true];
179
179
  }
180
- match = code.match(/^import (\w+).+? from ["']react["']/m);
180
+ match = code.match(/^import\s+(?:\*\s+as\s+)?(\w+).+?\bfrom\s*["']react["']/m);
181
181
  if (match) {
182
182
  return [match[1], false];
183
183
  }
@@ -232,7 +232,7 @@ function viteReact(opts = {}) {
232
232
  };
233
233
  },
234
234
  async transform(code, id, options) {
235
- const ssr = typeof options === "boolean" ? options : options?.ssr === true;
235
+ const ssr = options?.ssr === true;
236
236
  const [filepath, querystring = ""] = id.split("?");
237
237
  const [extension = ""] = querystring.match(fileExtensionRE) || filepath.match(fileExtensionRE) || [];
238
238
  if (/\.(mjs|[tj]sx?)$/.test(extension)) {
@@ -372,15 +372,44 @@ function viteReact(opts = {}) {
372
372
  ];
373
373
  }
374
374
  };
375
+ const reactJsxRuntimeId = "react/jsx-runtime";
376
+ const reactJsxDevRuntimeId = "react/jsx-dev-runtime";
377
+ const virtualReactJsxRuntimeId = "\0" + reactJsxRuntimeId;
378
+ const virtualReactJsxDevRuntimeId = "\0" + reactJsxDevRuntimeId;
375
379
  const viteReactJsx = {
376
380
  name: "vite:react-jsx",
377
381
  enforce: "pre",
378
382
  config() {
379
383
  return {
380
384
  optimizeDeps: {
381
- include: ["react/jsx-dev-runtime"]
385
+ include: [reactJsxRuntimeId, reactJsxDevRuntimeId]
382
386
  }
383
387
  };
388
+ },
389
+ resolveId(id, importer) {
390
+ if (id === reactJsxRuntimeId && importer !== virtualReactJsxRuntimeId) {
391
+ return virtualReactJsxRuntimeId;
392
+ }
393
+ if (id === reactJsxDevRuntimeId && importer !== virtualReactJsxDevRuntimeId) {
394
+ return virtualReactJsxDevRuntimeId;
395
+ }
396
+ },
397
+ load(id) {
398
+ if (id === virtualReactJsxRuntimeId) {
399
+ return [
400
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxRuntimeId)}`,
401
+ `export const Fragment = jsxRuntime.Fragment`,
402
+ `export const jsx = jsxRuntime.jsx`,
403
+ `export const jsxs = jsxRuntime.jsxs`
404
+ ].join("\n");
405
+ }
406
+ if (id === virtualReactJsxDevRuntimeId) {
407
+ return [
408
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxDevRuntimeId)}`,
409
+ `export const Fragment = jsxRuntime.Fragment`,
410
+ `export const jsxDEV = jsxRuntime.jsxDEV`
411
+ ].join("\n");
412
+ }
384
413
  }
385
414
  };
386
415
  return [viteBabel, viteReactRefresh, useAutomaticRuntime && viteReactJsx];
package/dist/index.mjs CHANGED
@@ -153,11 +153,11 @@ async function restoreJSX(babel, code, filename) {
153
153
  return [result?.ast, isCommonJS];
154
154
  }
155
155
  function parseReactAlias(code) {
156
- let match = code.match(/\b(var|let|const) +(\w+) *= *require\(["']react["']\)/);
156
+ let match = code.match(/\b(var|let|const)\s+([^=\{\s]+)\s*=\s*require\(["']react["']\)/);
157
157
  if (match) {
158
158
  return [match[2], true];
159
159
  }
160
- match = code.match(/^import (\w+).+? from ["']react["']/m);
160
+ match = code.match(/^import\s+(?:\*\s+as\s+)?(\w+).+?\bfrom\s*["']react["']/m);
161
161
  if (match) {
162
162
  return [match[1], false];
163
163
  }
@@ -212,7 +212,7 @@ function viteReact(opts = {}) {
212
212
  };
213
213
  },
214
214
  async transform(code, id, options) {
215
- const ssr = typeof options === "boolean" ? options : options?.ssr === true;
215
+ const ssr = options?.ssr === true;
216
216
  const [filepath, querystring = ""] = id.split("?");
217
217
  const [extension = ""] = querystring.match(fileExtensionRE) || filepath.match(fileExtensionRE) || [];
218
218
  if (/\.(mjs|[tj]sx?)$/.test(extension)) {
@@ -352,15 +352,44 @@ function viteReact(opts = {}) {
352
352
  ];
353
353
  }
354
354
  };
355
+ const reactJsxRuntimeId = "react/jsx-runtime";
356
+ const reactJsxDevRuntimeId = "react/jsx-dev-runtime";
357
+ const virtualReactJsxRuntimeId = "\0" + reactJsxRuntimeId;
358
+ const virtualReactJsxDevRuntimeId = "\0" + reactJsxDevRuntimeId;
355
359
  const viteReactJsx = {
356
360
  name: "vite:react-jsx",
357
361
  enforce: "pre",
358
362
  config() {
359
363
  return {
360
364
  optimizeDeps: {
361
- include: ["react/jsx-dev-runtime"]
365
+ include: [reactJsxRuntimeId, reactJsxDevRuntimeId]
362
366
  }
363
367
  };
368
+ },
369
+ resolveId(id, importer) {
370
+ if (id === reactJsxRuntimeId && importer !== virtualReactJsxRuntimeId) {
371
+ return virtualReactJsxRuntimeId;
372
+ }
373
+ if (id === reactJsxDevRuntimeId && importer !== virtualReactJsxDevRuntimeId) {
374
+ return virtualReactJsxDevRuntimeId;
375
+ }
376
+ },
377
+ load(id) {
378
+ if (id === virtualReactJsxRuntimeId) {
379
+ return [
380
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxRuntimeId)}`,
381
+ `export const Fragment = jsxRuntime.Fragment`,
382
+ `export const jsx = jsxRuntime.jsx`,
383
+ `export const jsxs = jsxRuntime.jsxs`
384
+ ].join("\n");
385
+ }
386
+ if (id === virtualReactJsxDevRuntimeId) {
387
+ return [
388
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxDevRuntimeId)}`,
389
+ `export const Fragment = jsxRuntime.Fragment`,
390
+ `export const jsxDEV = jsxRuntime.jsxDEV`
391
+ ].join("\n");
392
+ }
364
393
  }
365
394
  };
366
395
  return [viteBabel, viteReactRefresh, useAutomaticRuntime && viteReactJsx];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.3",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "contributors": [
@@ -39,14 +39,13 @@
39
39
  },
40
40
  "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-react#readme",
41
41
  "dependencies": {
42
- "@babel/core": "^7.18.0",
42
+ "@babel/core": "^7.18.2",
43
43
  "@babel/plugin-transform-react-jsx": "^7.17.12",
44
44
  "@babel/plugin-transform-react-jsx-development": "^7.16.7",
45
45
  "@babel/plugin-transform-react-jsx-self": "^7.17.12",
46
46
  "@babel/plugin-transform-react-jsx-source": "^7.16.7",
47
47
  "@rollup/pluginutils": "^4.2.1",
48
- "react-refresh": "^0.13.0",
49
- "resolve": "^1.22.0"
48
+ "react-refresh": "^0.13.0"
50
49
  },
51
50
  "peerDependencies": {
52
51
  "vite": "^3.0.0-alpha"
package/src/index.ts CHANGED
@@ -165,7 +165,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
165
165
  }
166
166
  },
167
167
  async transform(code, id, options) {
168
- const ssr = typeof options === 'boolean' ? options : options?.ssr === true
168
+ const ssr = options?.ssr === true
169
169
  // File extension could be mocked/overridden in querystring.
170
170
  const [filepath, querystring = ''] = id.split('?')
171
171
  const [extension = ''] =
@@ -361,7 +361,10 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
361
361
  }
362
362
  }
363
363
 
364
- // const runtimeId = 'react/jsx-runtime'
364
+ const reactJsxRuntimeId = 'react/jsx-runtime'
365
+ const reactJsxDevRuntimeId = 'react/jsx-dev-runtime'
366
+ const virtualReactJsxRuntimeId = '\0' + reactJsxRuntimeId
367
+ const virtualReactJsxDevRuntimeId = '\0' + reactJsxDevRuntimeId
365
368
  // Adapted from https://github.com/alloc/vite-react-jsx
366
369
  const viteReactJsx: Plugin = {
367
370
  name: 'vite:react-jsx',
@@ -369,32 +372,42 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
369
372
  config() {
370
373
  return {
371
374
  optimizeDeps: {
372
- include: ['react/jsx-dev-runtime']
375
+ include: [reactJsxRuntimeId, reactJsxDevRuntimeId]
373
376
  }
374
377
  }
375
- }
376
- // TODO: this optimization may not be necesary and it is breacking esbuild+rollup compat,
377
- // see https://github.com/vitejs/vite/pull/7246#discussion_r861552185
378
- // We could still do the same trick and resolve to the optimized dependency here
379
- /*
380
- resolveId(id: string) {
381
- return id === runtimeId ? id : null
382
- },
383
- load(id: string) {
384
- if (id === runtimeId) {
385
- const runtimePath = resolve.sync(runtimeId, {
386
- basedir: projectRoot
387
- })
388
- const exports = ['jsx', 'jsxs', 'Fragment']
378
+ },
379
+ resolveId(id, importer) {
380
+ // Resolve runtime to a virtual path to be interoped.
381
+ // Since the interop code re-imports `id`, we need to prevent re-resolving
382
+ // to the virtual id if the importer is already the virtual id.
383
+ if (id === reactJsxRuntimeId && importer !== virtualReactJsxRuntimeId) {
384
+ return virtualReactJsxRuntimeId
385
+ }
386
+ if (
387
+ id === reactJsxDevRuntimeId &&
388
+ importer !== virtualReactJsxDevRuntimeId
389
+ ) {
390
+ return virtualReactJsxDevRuntimeId
391
+ }
392
+ },
393
+ load(id) {
394
+ // Apply manual interop
395
+ if (id === virtualReactJsxRuntimeId) {
389
396
  return [
390
- `import * as jsxRuntime from ${JSON.stringify(runtimePath)}`,
391
- // We can't use `export * from` or else any callsite that uses
392
- // this module will be compiled to `jsxRuntime.exports.jsx`
393
- // instead of the more concise `jsx` alias.
394
- ...exports.map((name) => `export const ${name} = jsxRuntime.${name}`)
397
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxRuntimeId)}`,
398
+ `export const Fragment = jsxRuntime.Fragment`,
399
+ `export const jsx = jsxRuntime.jsx`,
400
+ `export const jsxs = jsxRuntime.jsxs`
395
401
  ].join('\n')
396
402
  }
397
- } */
403
+ if (id === virtualReactJsxDevRuntimeId) {
404
+ return [
405
+ `import * as jsxRuntime from ${JSON.stringify(reactJsxDevRuntimeId)}`,
406
+ `export const Fragment = jsxRuntime.Fragment`,
407
+ `export const jsxDEV = jsxRuntime.jsxDEV`
408
+ ].join('\n')
409
+ }
410
+ }
398
411
  }
399
412
 
400
413
  return [viteBabel, viteReactRefresh, useAutomaticRuntime && viteReactJsx]
@@ -1,6 +1,67 @@
1
1
  import * as babel from '@babel/core'
2
2
  import { describe, expect, it } from 'vitest'
3
- import { restoreJSX } from './restore-jsx'
3
+ import { parseReactAlias, restoreJSX } from './restore-jsx'
4
+
5
+ describe('parseReactAlias', () => {
6
+ it('handles cjs require', () => {
7
+ expect(parseReactAlias(`const React = require("react")`))
8
+ .toMatchInlineSnapshot(`
9
+ [
10
+ "React",
11
+ true,
12
+ ]
13
+ `)
14
+ })
15
+
16
+ it('handles cjs require (minified)', () => {
17
+ expect(parseReactAlias(`var F=require('foo');var R=require('react')`))
18
+ .toMatchInlineSnapshot(`
19
+ [
20
+ "R",
21
+ true,
22
+ ]
23
+ `)
24
+ })
25
+
26
+ it('does not handle destructured cjs require', () => {
27
+ expect(parseReactAlias(`var {createElement} = require("react")`))
28
+ .toMatchInlineSnapshot(`
29
+ [
30
+ undefined,
31
+ false,
32
+ ]
33
+ `)
34
+ })
35
+
36
+ it('handles esm import', () => {
37
+ expect(parseReactAlias(`import React from 'react'`)).toMatchInlineSnapshot(`
38
+ [
39
+ "React",
40
+ false,
41
+ ]
42
+ `)
43
+ })
44
+
45
+ it('handles esm import namespace', () => {
46
+ expect(parseReactAlias(`import * as React from "react"`))
47
+ .toMatchInlineSnapshot(`
48
+ [
49
+ "React",
50
+ false,
51
+ ]
52
+ `)
53
+ })
54
+
55
+ it('does not handle destructured esm import', () => {
56
+ expect(parseReactAlias(`import {createElement} from "react"`))
57
+ .toMatchInlineSnapshot(`
58
+ [
59
+ undefined,
60
+ false,
61
+ ]
62
+ `)
63
+ })
64
+ })
4
65
 
5
66
  async function jsx(sourceCode: string) {
6
67
  const [ast] = await restoreJSX(babel, sourceCode, 'test.js')
@@ -79,16 +79,16 @@ export async function restoreJSX(
79
79
  return [result?.ast, isCommonJS]
80
80
  }
81
81
 
82
- function parseReactAlias(
82
+ export function parseReactAlias(
83
83
  code: string
84
84
  ): [alias: string | undefined, isCommonJS: boolean] {
85
85
  let match = code.match(
86
- /\b(var|let|const) +(\w+) *= *require\(["']react["']\)/
86
+ /\b(var|let|const)\s+([^=\{\s]+)\s*=\s*require\(["']react["']\)/
87
87
  )
88
88
  if (match) {
89
89
  return [match[2], true]
90
90
  }
91
- match = code.match(/^import (\w+).+? from ["']react["']/m)
91
+ match = code.match(/^import\s+(?:\*\s+as\s+)?(\w+).+?\bfrom\s*["']react["']/m)
92
92
  if (match) {
93
93
  return [match[1], false]
94
94
  }