vitejs/vite-plugin-react

[plugin:vite:esbuild] Transform failed - Importing JSON files with { type: "json" };

Closed this issue · 5 comments

Describe the bug

Reproduction here: https://stackblitz.com/edit/vitejs-vite-no1xpg?file=src%2FApp.tsx

I am trying to import json files, with code like so:

import enUs from "../locales/en-US.json" with { type: "json" };
import it from "../locales/it.json" with { type: "json" };

But running it with vite causes it to crash with this error:

[plugin:vite:esbuild] Transform failed with 1 error:
/Users/skeithtan/WebstormProjects/deno-reporting/report-templates/src/components/IntlContextProvider.tsx:3:46: ERROR: Expected "{" but found "type"

/Users/skeithtan/WebstormProjects/deno-reporting/report-templates/src/components/IntlContextProvider.tsx:3:48

Expected "{" but found "type"
1  |  import RefreshRuntime from "/@react-refresh";const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;let prevRefreshReg;let prevRefreshSig;if (import.meta.hot && !inWebWorker) {  if (!window.__vite_plugin_react_preamble_installed__) {    throw new Error(      "@vitejs/plugin-react can't detect preamble. Something is wrong. " +      "See https://github.com/vitejs/vite-plugin-react/pull/11#discussion_r430879201"    );  }  prevRefreshReg = window.$RefreshReg$;  prevRefreshSig = window.$RefreshSig$;  window.$RefreshReg$ = (type, id) => {    RefreshRuntime.register(type, "/Users/skeithtan/WebstormProjects/deno-reporting/report-templates/src/components/IntlContextProvider.tsx" + " " + id)  };  window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;}var _s = $RefreshSig$();import { createContext, PropsWithChildren, useState } from "react";
2  |  import { IntlProvider } from "react-intl";
3  |  import enUs from "../locales/en-US.json" with type: "json";
   |                                                ^
4  |  import it from "../locales/it.json" with type: "json";
5  |  import { DEFAULT_LOCALE, Locale } from "../../../pdf-server/types/locale.ts";

Strange enough, in the stacktrace, it shows line 3 and 4 with missing braces like so: import enUs from "../locales/en-US.json" with type: "json"; even though the actual code has braces like so: { with type: "json" }.

Using npm:vite@^5.4.11 npm:react@^18.3.1 npm:@vitejs/plugin-react@^4.3.3 npm:@deno/vite-plugin@^1.0.0

Reproduction

https://stackblitz.com/edit/vitejs-vite-no1xpg?file=src%2FApp.tsx

Steps to reproduce

No response

System Info

"vite": "npm:vite@^5.4.11",
"vitest": "npm:vitest@^2.1.5"
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.0",
"react": "npm:react@^18.3.1",

Used Package Manager

npm

Logs

image
  vite:transform 14.68ms /src/templates/MedeaResting/components/Viewer/LeadContainer.tsx +5ms
  vite:transform 14.71ms /src/templates/MedeaResting/components/PatientInfoBox.tsx +0ms
  vite:load 13.19ms [fs] /src/components/IntlContextProvider.tsx +22ms
  vite:load 17.13ms [fs] /src/hooks/useFormatAge.ts +4ms
  vite:esbuild esbuild error with options used:  {
  sourcemap: true,
  sourcefile: '/Users/skeithtan/WebstormProjects/deno-reporting/report-templates/src/components/IntlContextProvider.tsx',
  target: 'esnext',
  charset: 'utf8',
  jsxDev: true,
  jsx: 'automatic',
  jsxImportSource: undefined,
  minify: false,
  minifyIdentifiers: false,
  minifySyntax: false,
  minifyWhitespace: false,
  treeShaking: false,
  keepNames: false,
  supported: { 'dynamic-import': true, 'import-meta': true },
  loader: 'tsx',
  tsconfigRaw: {
    compilerOptions: { useDefineForClassFields: false, jsx: undefined }
  }
} +49ms
3:12:01 PM [vite] Pre-transform error: Transform failed with 1 error:
/Users/skeithtan/WebstormProjects/deno-reporting/report-templates/src/components/IntlContextProvider.tsx:3:46: ERROR: Expected "{" but found "type" (x4)

Validations

It looks like babel transform breaks import attributes. I added @babel/plugin-syntax-import-attributes manually and it's working https://stackblitz.com/edit/vitejs-vite-dhfgvm?file=vite.config.ts

I'm not sure if silently stripping {} is their intended behavior though (maybe should be hard error?).

UPDATE: reported upstream babel/babel#16975

I missed the warning on first look, but it's there indicating that with type ... is one of babel's output:

  VITE v5.4.11  ready in 1421 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
You are using import attributes, without specifying the desired output syntax.
Please specify the "importAttributesKeyword" generator option, whose value can be one of:
 - "with"        : `import { a } from "b" with { type: "json" };`
 - "assert"      : `import { a } from "b" assert { type: "json" };`
 - "with-legacy" : `import { a } from "b" with type: "json";`

9:55:48 AM [vite] Internal server error: Transform failed with 1 error:
/home/projects/vitejs-vite-no1xpg/src/App.tsx:5:36: ERROR: Expected "{" but found "type"

To preserve with { type: ... }, you can use generator options of react plugin https://stackblitz.com/edit/vitejs-vite-vxpfbt?file=vite.config.ts

export default defineConfig({
  plugins: [
    react({
      babel: {
        generatorOpts: {
          importAttributesKeyword: 'with',
        },
      },
    }),
  ],
});

This might not be totally intuitive, but it looks clear enough for users to take actions, so I think we can close this.

We could add the default in the plugin, this current behavior is not great and they should have break people that were using unspec features instead

Oh right, default generator option would be a one liner without dependency, so that makes sense. I think we can simply add it here?

generatorOpts: {
...babelOptions.generatorOpts,
decoratorsBeforeExport: true,
},

Yep!