Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the new Babel 7 decorator implementation #1352

Closed
mweststrate opened this issue Feb 16, 2018 · 37 comments
Closed

Support the new Babel 7 decorator implementation #1352

mweststrate opened this issue Feb 16, 2018 · 37 comments

Comments

@mweststrate
Copy link
Member

mweststrate commented Feb 16, 2018

Example config for babel 7, in decorators legacy mode:

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

Please note that plugin ordering is important, and plugin-proposal-decorators should be the first plugin in your plugin list

"devDependencies": {
    "@babel/core": "^7.1.0",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/plugin-proposal-decorators": "^7.1.0",
    "@babel/preset-env": "^7.1.0"
}

Non-legacy mode decorators (stage 2) is work in progress, see #1732

Edit: updated config to show the non-beta configuration for babel 7

@brandonhall
Copy link

Just wanted to share my requirements for setting up mobx with babel 7.0.0-beta.40. Mainly, I wanted to highlight the necessary inclusion of babel-plugin-transform-decorators-legacy:

// package.json
  "devDependencies": {
    "@babel/core": "^7.0.0-beta.40",
    "@babel/preset-env": "^7.0.0-beta.40",
    "@babel/preset-react": "^7.0.0-beta.40",
    "@babel/preset-stage-1": "^7.0.0-beta.40",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
     ....
  }

// using webpack.config.js instead of babel.rc
presets: [
  '@babel/preset-react',
  '@babel/preset-env',
  '@babel/preset-stage-1',
],
plugins: [
  'react-hot-loader/babel',
  'transform-decorators-legacy',
  [
    'transform-class-properties', { loose: true, },
  ],
],

@Kielan
Copy link

Kielan commented Mar 16, 2018

I really like decorators, any way to keep it?

@und3fined
Copy link

und3fined commented Mar 22, 2018

My config. It work well

// package.json
"@babel/core": "^7.0.0-beta.42",
    "@babel/plugin-proposal-class-properties": "^7.0.0-beta.42",
    "@babel/plugin-proposal-decorators": "^7.0.0-beta.42",
    "@babel/plugin-transform-runtime": "^7.0.0-beta.42",
    "@babel/preset-env": "^7.0.0-beta.42",
    "@babel/preset-react": "^7.0.0-beta.42",
    "@babel/preset-stage-2": "^7.0.0-beta.42",
// .babelrc
{
    "presets": [
        ["@babel/preset-env", { "modules": false }],
        "@babel/preset-react",
        "@babel/preset-stage-2"
    ],
    "plugins": [
        "@babel/plugin-transform-runtime",
        "@babel/plugin-proposal-decorators",
        ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ],
    "env": {
        "development": {
            "plugins": ["react-hot-loader/babel"]
        }
    }
}

@emgyrz
Copy link

emgyrz commented Apr 20, 2018

@und3fined, thanks, it's works!

@Tsury
Copy link

Tsury commented Apr 30, 2018

When using the new Babel 7.00-beta.46 it no longer works, as described here

@dgcoffman
Copy link

dgcoffman commented May 3, 2018

UPDATE
Issue I was having below was caused by having "@babel/plugin-transform-flow-strip-types", as my first plugin. It needs to come after decorators and class-properties.


Builds work fine for me but I'm getting runtime errors like:

Error: [mobx] no observable property 'someObservableClassProperty' found on the observable object 'MyStoreObject'
    at invariant (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:2704)
    at fail$1 (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:2699)
    at getAtom (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:1990)
    at getAdministration (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:2010)
    at observeObservableProperty (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:3651)
    at observe (webpack-internal:///./node_modules/mobx/lib/mobx.module.js:3643)
    at new MyStoreObject (webpack-internal:///./src/stores/MyStoreObject.js:198)

for things like

class MyStoreObject {
  @observable someObservableClassProperty;
}

It appears that at the time that getAtom is called, thing.$mobx.values does not include property.
screen shot 2018-05-03 at 1 54 36 am

thing.__mobxDecorators contains only computed properties -- no observable properties.

My package.json has

    "@babel/cli": "7.0.0-beta.46",
    "@babel/core": "7.0.0-beta.46",
    "@babel/plugin-proposal-class-properties": "7.0.0-beta.46",
    "@babel/plugin-proposal-decorators": "7.0.0-beta.46",
    "@babel/polyfill": "7.0.0-beta.46",
    "@babel/preset-env": "7.0.0-beta.46",
    "@babel/preset-react": "7.0.0-beta.46",
    "@babel/preset-stage-3": "7.0.0-beta.46",
    "babel-loader": "8.0.0-beta.2",
    "mobx": "4.2.0",

.babelrc

{
  "presets": [
    "@babel/react",
    "@babel/stage-3",
    "@babel/preset-env",
  ],
  "plugins": [
    // NOTE: flow-strip-types MUST come after decorators and class-properties
    "@babel/plugin-transform-flow-strip-types",
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ],
  ]
}

@und3fined
Copy link

und3fined commented May 5, 2018

@Tsury please try.

update for babel@7.0.0.-beta.46
My config work well.

// package.json
"@babel/core": "^7.0.0-beta.46",
"@babel/plugin-transform-runtime": "^7.0.0-beta.46",
"@babel/preset-env": "^7.0.0-beta.46",
"@babel/preset-react": "^7.0.0-beta.46",
"@babel/preset-stage-2": "^7.0.0-beta.46",
"@babel/runtime": "^7.0.0-beta.46",

Diff with 7.0.0-beta42

// .babelrc
{
    "presets": [
        ["@babel/preset-env", { "modules": false }],
        "@babel/preset-react",
        ["@babel/preset-stage-2", { "loose": true, "decoratorsLegacy": true }]
    ],
    "plugins": [
        "@babel/plugin-transform-runtime"
    ],
    "env": {
        "development": {
            "plugins": ["react-hot-loader/babel"]
        }
    }
}

@jeffvandyke
Copy link

New Babel PR: babel/babel#7976

@vjpr
Copy link

vjpr commented Aug 5, 2018

This stopped working for me when I was using beta-56 of the proposal-decorators. beta-49 works fine for me. Also, I was using beta-49 of core while using beta-56 of the proposal-decorators, so that could have done it too.

@hyochan
Copy link

hyochan commented Aug 16, 2018

I am sharing the best solution for so far from my sight of view.

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react",
    "@babel/preset-flow"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    "@babel/plugin-proposal-function-sent",
    "@babel/plugin-proposal-export-namespace-from",
    "@babel/plugin-proposal-numeric-separator",
    "@babel/plugin-proposal-throw-expressions",
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    [
      "@babel/plugin-transform-runtime",
      {
        "helpers": true,
        "regenerator": false
      }
    ]
  ]
}

and package.json

    "@babel/cli": "7.0.0-rc.1",
    "@babel/core": "7.0.0-rc.1",
    "@babel/plugin-proposal-class-properties": "^7.0.0-rc.1",
    "@babel/plugin-proposal-decorators": "7.0.0-rc.1",
    "@babel/plugin-proposal-export-namespace-from": "^7.0.0-rc.1",
    "@babel/plugin-proposal-function-sent": "^7.0.0-rc.1",
    "@babel/plugin-proposal-numeric-separator": "^7.0.0-rc.1",
    "@babel/plugin-proposal-throw-expressions": "^7.0.0-rc.1",
    "@babel/plugin-transform-runtime": "7.0.0-rc.1",
    "@babel/preset-env": "7.0.0-rc.1",
    "@babel/preset-flow": "^7.0.0-rc.1",
    "@babel/preset-react": "7.0.0-rc.1",
    "@babel/runtime": "7.0.0-rc.1",
    "babel-loader": "^8.0.0-beta.4",

@mgambati
Copy link

Now that babel 7 stable released, its possible to work on new decorator API?

@mweststrate
Copy link
Member Author

mweststrate commented Aug 30, 2018 via email

@Lenic
Copy link

Lenic commented Aug 31, 2018

The order is important.

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

Follow the order.

@mweststrate
Copy link
Member Author

mweststrate commented Sep 25, 2018

Updated the original comment to show the latest status, the non-beta Babel 7 version

@JamesTheHacker
Copy link

JamesTheHacker commented Oct 4, 2018

Posting this error message here because when it took me all day to find the solution to this based on the error. The error I was getting was:

Uncaught TypeError: An element descriptor's .kind property must be either "method" or "field", but a decorator created an element descriptor with .kind "undefined"
    at _toElementDescriptor (app.js:46281)
    at _toElementFinisherExtras (app.js:46283)
    at _decorateElement (app.js:46273)
    at app.js:46269
    at Array.forEach (<anonymous>)
    at _decorateClass (app.js:46269)
    at _decorate (app.js:46251)
    at Module../src/App/stores/UserStore.js (app.js:46301)
    at __webpack_require__ (bootstrap:19)
    at Module../src/App/stores/index.js (index.js:1)

I was getting the error when using @computed but @actions worked fine.

The solution posted by OP works fine with Babel 7.

Babel 7 has caused me nothing but headaches so far.

@mtermoul
Copy link

I had the same issue with "@babel/core": "7.1.0" and I was able to solve the problem in two steps:

  • npm install --save-dev @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators"

  • Then add the following to babel config section on package.json as following:

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

@2Pacalypse-
Copy link

Also, make sure to put decorators plugin before the class-properties plugin in your babel config. Apparently, the ordering of plugins matter in babel. Who knew?

Agree with @JamesTheHacker, Babel 7 brought me nothing but headaches.

@andriimiroshnychenko
Copy link

andriimiroshnychenko commented Nov 2, 2018

Update:

This isn't MobX specific issue, it's related to general Babel compilation error.

Original comment

Hi! Another interesting bug here ;)
Despite of suggested plugins ordering solution decorators will conflict with static property which is called another static property of the same class e.g.

export class TestClass {
  static person = {
    name: 'Bazz',
    familyName: 'Lighter'
  };
  static secondPerson = {
    name: TestClass.person.name,
    familyName: 'Fuzz'
  };

  @computed
  get someGetter() {
    return true;
  }
}

In runtime this will throw

  name: TestClass.person.name,
                  ^

TypeError: Cannot read property 'person' of undefined

I made little repo to demonstrate it https://github.com/andriimiroshnychenko/small-repro.
@mweststrate can you please take a look?

@und3fined
Copy link

@mweststrate decorators is pretty in code, but not work well with mobx

@jjinux
Copy link
Contributor

jjinux commented Nov 6, 2018

@und3fined, are you trolling? Lots of us are using decorators with MobX in production.

@und3fined
Copy link

und3fined commented Nov 6, 2018

@jjinux hi there,
I was really use it for production, it is good but after each babel and mobx update
I need more than 2 working days to fix the compilation(transpiler implementations) error

@mweststrate
Copy link
Member Author

@JamesTheHacker please use decorators in legacy mode as shown in the post at the beginnign of this thread.

@2Pacalypse- I added the notice about ordering also to the post on top of this thread, but yes, order was always important already.

@andriimiroshnychenko not sure how your issue is related to mobx?

@und3fined following the instructions on should generally keep you out of harms way :). https://mobx.js.org/best/decorators.html

Pro tip in general: If babel causes too many headaches, try TypeScript for a while, configuration is trivial and has worked reliably for years :). The amount of Babel versus TS issues in this repo is probably 100:1

@andriimiroshnychenko
Copy link

@mweststrate you're totally right, this is not MobX-generated error, other decorators usage will cause same error. Sorry for not stating it in my message. I wrote it just for people, who will run in the same problem.

@und3fined
Copy link

@mweststrate currently, i'm use Using the decorate utility, this is best choose for production

@jjinux
Copy link
Contributor

jjinux commented Nov 7, 2018

@und3fined

I was really use it for production, it is good but after each babel and mobx update
I need more than 2 working days to fix the compilation(transpiler implementations) error

Perhaps it was because they switched the order of decorators and export. There's a legacy option that you can use to put it back to what was there before. I did that without updating my code. I'm waiting for that issue to settle down before I actually dig in to change my code since it is a very contentious issue.

@mweststrate
Copy link
Member Author

mweststrate commented Nov 8, 2018 via email

@yk1062008412
Copy link

I almost add all babel in this contexty. but it still report error....

// .babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-flow"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
],
[
"@babel/plugin-transform-runtime",
{
"helpers": true,
"regenerator": false
}
]
]
}

// package.json
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.2.1",
"@babel/plugin-proposal-decorators": "^7.2.2",
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
"@babel/plugin-proposal-function-sent": "^7.2.0",
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.2.0",
"@babel/preset-env": "^7.2.0",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-stage-1": "^7.0.0",
"@babel/preset-stage-2": "^7.0.0",
"@babel/runtime": "^7.2.0",
"babel-loader": "^8.0.4",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5"

// error log
Support for the experimental syntax 'decorators-legacy' isn't currently enabled.

@mweststrate
Copy link
Member Author

@yk1062008412 looks like your config isn't picked at all up by the build tool you are using. Doesn't sound really related to mobx itself, so best provide a project repository so that people can actually look at your setup. Or google for the error in combination with the stack you are using.

@yk1062008412
Copy link

@yk1062008412 looks like your config isn't picked at all up by the build tool you are using. Doesn't sound really related to mobx itself, so best provide a project repository so that people can actually look at your setup. Or google for the error in combination with the stack you are using.

Thank you for your reply.
my app repertory link is https://github.com/yk1062008412/mytestapp .
Thanks very much.
@mweststrate

joho added a commit to hecateapp/heartbeat-extension that referenced this issue Jan 2, 2019
@katis
Copy link

katis commented Jan 10, 2019

I'm writing a TypeScript+Webpack project, but I need a couple of Babel plugins (styled-components, react-hot-loader, etc). These plugins have to run before TypeScript or they don't work well.

I've found that the best way to get everything to work nicely is to use Babel syntax plugins instead of transformation plugins wherever you can. That way Babel does a minimum amount of transformations, leaving TS the bulk of the work.

This is a simplified version of my webpack module rule:

{
  test: /\.ts$/,
  exclude: /node_modules/,
  use: [
    {
      loader: 'awesome-typescript-loader',
    },
    {
      loader: 'babel-loader',
      options: {
        plugins: [
          ['@babel/plugin-syntax-decorators', { decoratorsBeforeExport: true }],
          '@babel/plugin-syntax-class-properties',
          'babel-plugin-styled-components',
          '@babel/plugin-syntax-typescript',
          '@babel/plugin-syntax-dynamic-import',
          '@babel/plugin-syntax-json-strings',
          'react-hot-loader/babel',
        ],
      },
    },
  ],
}

I was able to make a decorator version of flow work with class methods since I could use the newer Babel decorator plugin, the legacy decorator plugin didn't understand the syntax:

import { flow as mobxFlow } from 'mobx'

export function flow(
  _: any,
  _1: string,
  descriptor: TypedPropertyDescriptor<(...args: any[]) => IterableIterator<any>>
) {
  if (descriptor.value) {
    descriptor.value = mobxFlow(descriptor.value) as any
  }
}

class Store {
  @flow
  *getData() {
    ...
   }
}

@mostrecent
Copy link

mostrecent commented Jan 29, 2019

Pro tip in general: If babel causes too many headaches, try TypeScript for a while, configuration is trivial and has worked reliably for years :). The amount of Babel versus TS issues in this repo is probably 100:1

@mweststrate, how do you pair ts-loader with babel-loader in the Webpack pipeline then? I require Babel because of two transformation plugins and I'd be even ok to have two transpilation steps but I couldn't get ts-loader and babel-loader to work together. I couldn't get this work just with Babel either using its own TS plugin (what MS recommends). Would you mind to show your Webpack config in case you use ts-loader and babel-loader together?

@danrot
Copy link

danrot commented Feb 18, 2019

I was trying to upgrade due to a security vulnerability today, but I couldn't get babel 7 to work. It was strangely failing with an observer component with a constructor like this:

constructor(props) {
    super(props);
    this.doSomething(this.props.something);
}

The problem was that this.props seemed to be undefined, and for that reason the code erred. Is it possible that a behavior like this is somehow related to this issue? I also used the plugins as mentioned in the first post (first the decorator one with the legacy option and then the class properties with the loose option), but it still didn't work...

@mweststrate
Copy link
Member Author

mweststrate commented Feb 19, 2019 via email

@mweststrate
Copy link
Member Author

mweststrate commented Feb 19, 2019 via email

@mweststrate
Copy link
Member Author

Closing for now, will be reopened once #1928 happens.

@danrot
Copy link

danrot commented Mar 28, 2019

Sorry, it took me quite some time to get the setup running, and I am quite busy at the moment 🙈 I think I'll try again once the decorators stuff landed, and create an issue if the problem then still persists.

@lock
Copy link

lock bot commented Jul 21, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.

@lock lock bot locked as resolved and limited conversation to collaborators Jul 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests