QwikDev / qwik

Instant-loading web apps, without effort
https://qwik.dev
MIT License
20.64k stars 1.28k forks source link

[🐞] Problems with typescript decorators (Unexpected token `@`.) #2951

Closed r1n0x closed 1 year ago

r1n0x commented 1 year ago

Which component is affected?

Qwik Rollup / Vite plugin

Describe the bug

So I wanted to build classic website like in PHP/NextJS, no edge functions etc. and I wanted to use TypeORM and I was meet with error which said: [plugin:vite-plugin-qwik] Unexpected token `@`. Expected this, import, async, function, [ for array literal, { for object literal, @ for decorator, function, class, null, true, false, number, bigint, string, regexp, ` for template literal, (, or an identifier which I guess is because of TypeORM uses decorators,

At first after some googling internet said it may be because Vite compiles to esbuild and it supposedly doesn't support decorators, but after trying it in normal Vite it works smoothly so I think problem is in the plugin.

Error message while trying to execute class method. (reproducing code has this) image

Error message while having a class decorator (straight from TypeORM). The funny thing is that is clearly says @ symbol should be accepted XD image image

Reproduction

https://github.com/r1n0x/qwik-issue

Steps to reproduce

Working example in qwik (installed using npm create qwik@latest today):

I've attached a normal vite as comparison too, which works normally with or without the decorator (installed using npm create vite@latest today):

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (4) x64 Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
    Memory: 4.03 GB / 15.98 GB
  Binaries:
    Node: 19.3.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.2.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (110.0.1587.41)
    Internet Explorer: 11.0.19041.1566

Additional Information

Tried googling but Qwik is pretty new and so I didn't find anything and normal vite works sooo... I'm out of ideas! Hope you guys can help!

nickbreaton commented 1 year ago

Started looking into this a little and noticed adding decorators: true to the parser options allows the build to complete without error.

https://github.com/BuilderIO/qwik/blob/4b72570ce87fec58516b94ac1ecbfde103505705/packages/qwik/src/optimizer/core/src/parse.rs#L520-L523

However, it seems the decorator never gets transpiled, resulting in a runtime error. It's not clear to me if Qwik's core is doing the actual transpiring here or if this is left up to Vite.

Hopefully someone smarter than me could point me in the right direction. I'd be happy to continue looking into this.

nickbreaton commented 1 year ago

Yeah I think anything other than the parser option above may be out of Qwik's responsibilities. (Happy to get a PR going to enable this if it seems reasonable to the maintainers)

After digging a litter deeper, I was able to configure the babel vite plugin to just parse the decorators with the following setup:

import { defineConfig } from "vite";
import { qwikVite } from "@builder.io/qwik/optimizer";
import { qwikCity } from "@builder.io/qwik-city/vite";
import babel from "vite-plugin-babel";

export default defineConfig(() => {
  return {
    plugins: [
      qwikCity(),
      qwikVite(),
      babel({
        babelConfig: {
          presets: [["@babel/preset-typescript"]],
          plugins: [["@babel/plugin-proposal-decorators", { version: "2023-01" }]],
        },
        filter: /\.ts?$/,
      }),
    ],
  };
});
saeedhbi commented 1 year ago

Yeah I think anything other than the parser option above may be out of Qwik's responsibilities. (Happy to get a PR going to enable this if it seems reasonable to the maintainers)

After digging a litter deeper, I was able to configure the babel vite plugin to just parse the decorators with the following setup:

import { defineConfig } from "vite";
import { qwikVite } from "@builder.io/qwik/optimizer";
import { qwikCity } from "@builder.io/qwik-city/vite";
import babel from "vite-plugin-babel";

export default defineConfig(() => {
  return {
    plugins: [
      qwikCity(),
      qwikVite(),
      babel({
        babelConfig: {
          presets: [["@babel/preset-typescript"]],
          plugins: [["@babel/plugin-proposal-decorators", { version: "2023-01" }]],
        },
        filter: /\.ts?$/,
      }),
    ],
  };
});

I do have this problem too, and even this approach doesn't work. My error message is different:

Error: Unexpected token @. Expected identifier, string literal, numeric literal or [ for the computed key

nickbreaton commented 1 year ago

@saeedhbi This approach is what is needed by the end user in addition to the Qwik parser understanding decorators.

I don't currently know of a way to get decorators loading in Qwik until this issue is resolved.

saeedhbi commented 1 year ago

@saeedhbi This approach is what is needed by the end user in addition to the Qwik parser understanding decorators.

I don't currently know of a way to get decorators loading in Qwik until this issue is resolved.

I could handle the decorators by changing the order of babel configurations. But also, I'm not sure why but it didn't work with vite-plugin-babel plugin and it will work only with @vitejs/plugin-react.

The @vitejs/plugin-react plugin should be ordered before qwik plugins. Like:

{
  plugins: [
    tsconfigpath(), 
    react({
      babel: {
        babelrc: false,
        configFile: false,
        plugins: [
          ["@babel/plugin-transform-class-static-block"],
          ["@babel/plugin-proposal-decorators", { version: "legacy" }],
          ["@babel/plugin-proposal-class-properties"],
        ],
      },
    }),
    qwikVite(),
    qwikCity()
  ]
}`
kattsushi commented 1 year ago

@saeedhbi This approach is what is needed by the end user in addition to the Qwik parser understanding decorators. I don't currently know of a way to get decorators loading in Qwik until this issue is resolved.

I could handle the decorators by changing the order of babel configurations. But also, I'm not sure why but it didn't work with vite-plugin-babel plugin and it will work only with @vitejs/plugin-react.

The @vitejs/plugin-react plugin should be ordered before qwik plugins. Like:

{
  plugins: [
    tsconfigpath(), 
    react({
      babel: {
        babelrc: false,
        configFile: false,
        plugins: [
          ["@babel/plugin-transform-class-static-block"],
          ["@babel/plugin-proposal-decorators", { version: "legacy" }],
          ["@babel/plugin-proposal-class-properties"],
        ],
      },
    }),
    qwikVite(),
    qwikCity()
  ]
}`

i just tried this way but i got the same error

image

gioboa commented 1 year ago

Hi @r1n0x , thanks for opening this issue, did you solve this specific problem with the @ ?

mhevery commented 1 year ago

I think there are two parts:

  1. Add decorators: true as describe https://github.com/BuilderIO/qwik/issues/2951#issuecomment-1585794394
  2. Instructions to add the babel plugin
Roman-Simik commented 5 months ago

Hi,

For me, modifying vite.config.ts like this was enough:

import { defineConfig } from "vite";
import { qwikVite } from "@builder.io/qwik/optimizer";
import { qwikCity } from "@builder.io/qwik-city/vite";
import babel from "vite-plugin-babel";

export default defineConfig(() => {
  return {
    plugins: [
      qwikCity(),
      qwikVite(),
      babel({
        babelConfig: {
          plugins: [["@babel/plugin-proposal-decorators", { version: "2023-01" }]],
        },
        filter: /\.(ts|tsx)$/,
      }),
    ],
  };
});
wmertens commented 5 months ago

FYI I'm updating the optimizer and it will include decorator support but it's not done yet.