vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.46k stars 26.8k forks source link

Decorators don't work in with-typescript example. #4707

Closed Rokt33r closed 5 years ago

Rokt33r commented 6 years ago

Examples bug report

Example name

with-typescript

Describe the bug

If I start using decorators, next.js throws an error to ask to add @babel/plugin-proposal-decorators. And, it throws same error even after I add the plugin.

Syntax Error:
   6 | }
   7 |
>  8 | @myDecorator
     | ^
   9 | export default class IndexPage extends React.Component{
  10 |   render () {
  11 |     return <div>

Add @babel/plugin-proposal-decorators (https://git.io/vb4ST) to the 'plugins' section of your Babel config to enable transformation

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Set "experimentalDecorators": true to tsconfig.json
  2. Add some any decorators to any page
import React from 'react'
import Link from 'next/link'

function myDecorator (constructor: any) {

}

@myDecorator
export default class IndexPage extends React.Component{
  render () {
    return <div>
      Hello World.{' '}
      <Link href="/about">
        <a>About</a>
      </Link>
    </div>
  }
}

Expected behavior

It should work with decorators.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  "dependencies": {
    "@zeit/next-typescript": "^1.1.0",
    "next": "^6.1.1",
    "react": "^16.4.1",
    "react-dom": "^16.4.1"
  },
  "devDependencies": {
    "@babel/plugin-proposal-decorators": "^7.0.0-beta.51",
    "@types/next": "^2.4.7",
    "@types/react": "^16.0.36"
  }
Rokt33r commented 6 years ago

It seems to work if I add those two plugins below.

    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.5"
{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    "transform-decorators-legacy",
    "transform-class-properties"
  ]
}

But, I assume those two plugins will be deprecated in babel v7. Therefore, we need to use @babel/plugin-proposal-decorators eventually.

This plugin is specifically for Babel 6.x. If you're using Babel 7, this plugin is not for you. Babel 7's @babel/plugin-proposal-decorators officially supports the same logic that this plugin has, but integrates better with Babel 7's other plugins. You can enable this with https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy#babel--7x

But, It starts breaking again after I tried like the below.

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }]
  ]
}

Then throws this error:

ModuleBuildError: Module build failed: Error: [BABEL] /PROJECT_ROOT/pages/index.tsx: You gave us a visitor for the node type PrivateName but it's not a validtype (While processing: "/PROJECT_ROOT/node_modules/@babel/plugin-proposal-class-properties/lib/index.js")

Fortunately, it works again after I install thew newest version of babel(v7.0.0-beta.51).

Rokt33r commented 6 years ago

@timneutkens Is it okay to upgrade the version of @babel/core so I could update .babelrc of with-mobx example too?

I assume it is inevitable to use @babel/plugin-proposal-decorators for now.

timneutkens commented 6 years ago

Is it okay to upgrade the version of @babel/core

This is a breaking change.

Rokt33r commented 6 years ago

Okay. Then, I'll stick with my temporary solution until it is upgraded. 👍

alejomendoza commented 6 years ago

I still get an error when trying to import a typescript module with a decorator @Rokt33r, any ideas on how to make this work? thanks!

ModuleParseError: Module parse failed: Unexpected character '@' (10:2)
You may need an appropriate loader to handle this file type.
|
| export class PlaylistsStore {
>   @observable playlists: List<Playlist> = List([]);

I'm on next 7.0.0-canary.0

lkostrowski commented 6 years ago

I had similar problem as here: https://github.com/kriasoft/react-starter-kit/issues/1522

The solution was to check what babel version is used by next, and use the same version in @babel/plugin-proposal-decorators

Rokt33r commented 6 years ago

Check here @alejomendoza

https://github.com/BoostIO/Boostwiki/blob/master/package.json#L68-L69

https://github.com/BoostIO/Boostwiki/blob/master/.babelrc

Rokt33r commented 6 years ago

@lkostrowski 's solution is also valid. If you don't want to see deprecated warnings, please install specific version of @babel/core, which fits the version of @babel/plugin-proposal-decorators, again to override the one with next.js.

timneutkens commented 5 years ago

as far as I'm aware this is fixed with Next 7.x.

webberwang commented 5 years ago

@timneutkens

I cloned the latest with-typescript repo & added those 2 settings to .babelrc, but I'm still getting those errors.

next_config_js_ _next_js

https://github.com/webberwang/next.js/commit/ed1a37ff865ed101e9fefb91ee9dafa04e69c9d7

myeongjae-kim commented 5 years ago

@webberwang The problem is that neither @babel/plugin-proposal-decorators nor @babel/plugin-proposal-class-properties support the function parameter decorator.

This

@injectable()
class Ninja implements Warrior {
    @inject(TYPES.Weapon) private _katana: Weapon;
    @inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon;
    public fight() { return this._katana.hit(); }
    public sneak() { return this._shuriken.throw(); }
}

instead of

@injectable()
class Ninja implements Warrior {

    private _katana: Weapon;
    private _shuriken: ThrowableWeapon;

    public constructor(
        @inject(TYPES.Weapon) katana: Weapon,
        @inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }

    public fight() { return this._katana.hit(); }
    public sneak() { return this._shuriken.throw(); }
}

will work well.

There is a babel plugin for the parameter decorator: https://github.com/WarnerHooh/babel-plugin-parameter-decorator. I've applied it to use the parameter decorator on nextjs but failed to remove all error messages :(

RobertoPrevato commented 4 years ago

I add a comment because maybe it will save some time for others. The current condition is still as @myeongjae-kim wrote in August 2019. I am currently working on a Next.js web application, that uses "module": "esnext". Interestingly, when I run tests using mocha and chai, I need to modify on the fly the "module" mode to "commonjs" with a command like this one:

cross-env TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\" }' mocha -r ts-node/register tests/**/*.test.ts

And in this case, parameter decorators work fine. But they don't work when starting the web app using yarn next with the different module mode. Removing constructors work fine, but in my opinion it also make classes a bit harder to test and more verbose, since now I cannot simply instantiate a class to test it and need to add property setters to otherwise full private properties. Pity.

denniske commented 4 years ago

After adding @babel/plugin-proposal-decorators and @babel/plugin-proposal-class-properties, I still got the following error:

ColumnTypeUndefinedError: Column type for User#id is not defined and cannot be guessed. Make sure you have turned on an "emitDecoratorMetadata": true option in tsconfig.json. Also make sure you have imported "reflect-metadata" on top of the main entry file in your application (before any entity imported).If you are using JavaScript instead of TypeScript you must explicitly provide a column type.

Solved by installing and using babel-plugin-transform-typescript-metadata:

npm install --dev --save babel-plugin-transform-typescript-metadata

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }]
  ]
}

.tsconfig

...
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
...
YagoLopez commented 4 years ago

Thanks @denniske That worked for me like a charm

trompx commented 4 years ago

Despite having the same config as yours @denniske, I'm still having issues: I use type-graphql, when using Arg decorator, I get:

Module parse failed: Unexpected character '@' (55:17)
File was processed with these loaders:
 * ./node_modules/next/dist/build/webpack/loaders/next-babel-loader.js
You may need an additional loader to handle the result of these loaders.
|
|
>   async register(@Arg("data")
|   {
|     email,

Any ideas?

aditya063 commented 4 years ago

Despite having the same config as yours @denniske, I'm still having issues: I use type-graphql, when using Arg decorator, I get:

Module parse failed: Unexpected character '@' (55:17)
File was processed with these loaders:
 * ./node_modules/next/dist/build/webpack/loaders/next-babel-loader.js
You may need an additional loader to handle the result of these loaders.
|
|
>   async register(@Arg("data")
|   {
|     email,

Any ideas?

Having the same issue. Have you found any solution yet?

Edit: Fixed it

Had to add additional plugin for parameter decorators. 👉🏻 LINK

Here is my:

// .babelrc
{
  "presets": ["next/babel"],
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    "babel-plugin-parameter-decorator"
  ]
}
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "esnext",
    "lib": ["ES2017", "dom", "dom.iterable", "esnext"],
    "sourceMap": true,
    "outDir": "./dist",
    "moduleResolution": "node",
    "removeComments": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "exclude": ["node_modules"],
  "include": ["./**/*.tsx", "./**/*.ts"]
}
dgurns commented 3 years ago

Still getting errors here w/ Next version 10.0.4. Tried @aditya063's exact solution and I get the error message

Syntax error: Support for the experimental syntax 'decorators-legacy' isn't currently enabled:

Would really love to use TypeGraphQL/TypeORM with Apollo Server via a Next API Route, and have it all in one project.

Hoping this gets supported soon!

softmarshmallow commented 3 years ago

@dgurns Haven't found a way through it yet?

softmarshmallow commented 3 years ago

https://github.com/bridgedxyz/assistant/commit/fe8e252f3d1dd2af6259cdb55ce15b40e5a04ac5 tried it , didn't work

dgurns commented 3 years ago

@dgurns Haven't found a way through it yet?

Nope, my guess (could be wrong) is that the NextJS team may have to explicitly enable plugin-proposal-decorators as an option in the Babel config: https://github.com/vercel/next.js/tree/canary/packages/next/bundles/babel/packages

In the meantime I switched to Serverless framework. Would love to eventually run this off NextJS API routes though due to easy preview deployments and same-origin.

Bielik20 commented 3 years ago

We are having the same problem. Perhaps we should reopen this issue or move to the other one. Base on my research I found two other issues that relate that problem:

I would also like to take this opportunity to say that it isn't only a backend related issue. We are using decorators on frontend and this prevents us from using NextJS.

aditya063 commented 3 years ago

Still getting errors here w/ Next version 10.0.4. Tried @aditya063's exact solution and I get the error message

Syntax error: Support for the experimental syntax 'decorators-legacy' isn't currently enabled:

Would really love to use TypeGraphQL/TypeORM with Apollo Server via a Next API Route, and have it all in one project.

Hoping this gets supported soon!

have add following to your tsconfig.son? "emitDecoratorMetadata": true, "experimentalDecorators": true,

@dgurns

zfwf commented 3 years ago

Thanks, @aditya063 for the code, I got it working with Next v10 using the .babelrc below:

// .babelrc
{
  "presets": ["next/babel"],
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}

Repo here: https://github.com/chhschou/nextjs-graphql-serverless-starter

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.