Closed macrozone closed 5 years ago
It's probably related to different versions of Babel used by uniforms and Meteor. While I'm not sure, I'd ask for a reproduction too (we can track it in the Meteor issue if you want).
@radekmie does your example project work under meteor 1.7? did not have time to setup a reproduction yet
Haven't tried it yet. I'll give it a shot later this week.
Unluckily, I've made two attempts and failed twice. Any progress on your site?
EDIT: Yep, I've tried updating Babel too (7.0.0-beta.49
).
@radekmie i tried to update to 1.25.0-rc.3, but i still get the same error. Do i need to bump something else as well?
Edit: i also bumped all babel stuff to beta 51 without success
I got it working in the demo app. If you could provide a reproduction, please do - I’ll reopen it then.
I had no success yet.
In your .babelrc you have
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
],
i am not sure if this messes with meteor 1.7's legacy and modern browser support?
maybe @benjamn can shed some light on that
@radekmie I have
import AutoFormBase from 'uniforms/AutoForm';
const Auto = parent =>
class extends AutoFormBase.Auto(parent) {
static Auto = Auto;
};
const AutoForm = Auto(ValidatedQuickForm);
in my meteor app, because I have a custom AutoForm
component
Maybe that's the problem? in the demo-app this is not the case
Edit: Also @benjamn 's comment here https://github.com/meteor/meteor/issues/9934#issuecomment-394356011 indicates, that its because AutoFormBase.Auto(parent)
is compiled down to a constructor function by babel. The error happens in node_modules/uniforms/AutoForm, which is already compiled. So It seems, I can't fix it in my codebase
Edit2: The error already happens in
import ValidatedForm from 'uniforms/ValidatedForm';
import BaseForm from './BaseForm';
const Validated = parent => class extends ValidatedForm.Validated(parent) {
static Validated = Validated;
};
where
class extends ValidatedForm.Validated(parent) {
static Validated = Validated;
};
gives a "broken" class, that cannot be instantiate
I’ll reopen it then.
@radekmie any idea what we can do? I can try to setup a reproduction on the weekend, but it seems i am not into babel enough to be able to fix this issue myself.
Have you tried to launch the demo app? It's working somehow. I'll try to do some research again, but I can't promise anything.
@radekmie
not yet, but i will try
the demo app also uses preset-env, which should not be used according to this comment: https://forums.meteor.com/t/meteor-1-7-and-babel-issues/44479/4?u=macrozone
If you have a better idea on how to make it work, I'd really appreciate that and surely update the demo project. As for now, it's working pretty well.
I tried the demo app. It works, unless i remove ["@babel/preset-env", {"useBuiltIns": "usage"}],
as you should not use "@babel/preset-env"
in a meteor app, i think you basically will break meteor 1.7's modern/legacy optimisation.
maybe @benjamn has an idea, what to do in this situation.
Edit: If i add ["@babel/preset-env", {"useBuiltIns": "usage"}],
to my app, I will get an error " Missing class properties transform." while bundling. If i then further add "transform-class-properties", I will get other Class constructor XXX cannot be invoked without 'new'
on other npm imports.
So I strongly believe it has to work without ["@babel/preset-env", {"useBuiltIns": "usage"}],
or we will break a lot of apps
ok, the problem seems to be much harder:
for inheritence to work, the whole class chain has to be either es5 polyfilled or all es6 classes.
A transpiled es5 pseudo-class can't extend a es6 class otherwise you get the error TypeError: Class constructor _class cannot be invoked without 'new'
.
But this might happen with uniforms e.g. in connectField
:
return class extends baseField {
where baseField can be passed from your app's code (from your "app-space")
In case of meteor 1.7. this baseField will be a native es6 class for modern browsers, but uniforms will use it as a base class for a es5 transpiled class (in "module-space").
I think the only proper solution is to enable meteor to transpile the raw code to either es6 or es5 depending on the target. So uniform should additionaly ship es6 code.
Edit: some more thoughts: https://github.com/meteor/meteor/issues/9934#issuecomment-406888390
possible solution:
node_modules/uniforms/src
somwhere in your app, e.g. ln -s ./node_modules/uniforms/src imports/uniforms
All uniforms packages are also shipping the ES6 version. You can check it in your node_modules
directory or on unpkg.com/uniforms/, directory src/
.
@radekmie, yes simlinking src into the app seems to work!
I think we can close it as we already have a workaround.
Would it be possible to solve the issue without workaround, please? @radekmie you claim that uniforms are shipped in ES6 and I believe that up-to-date meteor and babel produce also ES6 so what is causing the error?
I would like to use uniforms as standard package, with all the updates and convinience. So I don't like the workaround very much :)
Thanks.
Hi @mariusrak. Yes, both transpiled and non-transpiled versions are published - you can see it on unpkg.com. I don't know what is causing the error - I'd surely fix it if I knew.
@mariusrak @radekmie
I explained above what causes the issue (see https://github.com/vazco/uniforms/issues/433#issuecomment-406887427)
The only workaround possible at the moment is the symlinking described above https://github.com/vazco/uniforms/issues/433#issuecomment-406889261
@macrozone, I've read that, but I somehow don't understand. If both uniforms and output of meteor project are in ES6, then where is the problem?
@mariusrak if you do a import XXX from "uniforms"
, XXX is ES5 code, because that is what is shipped to npm. It addionally has ES6 code in "uniforms/src", but that is not automatically used.
So is it possible to ship ES6 code to npm? Or why not?
@mariusrak yes, you can do that. But then it only works in environments that support es6 or transpile it down.
Even meteor does not automatically transpile code from npm/node_modules unless you do the symlink-trick.
I think @benjamn is working on that problem, but its not easy. Here is a good read: https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages
ok, the same problem happens if you use other bundlers. E.g. it happend to me on a jest / storyshots test now.
@radekmie what maybe would help is to transpile also to es201x and use a module
entry point. Modern bundlers would then take the untranspiled code. This also improves tree-shaking usually
Tree shaking is not really an interesting case for us, as one can import uniforms/X
anyway (and we encourage to do so in the docs). Yes, we can do it, but we are not planning to do so. We've migrated to TypeScript recently (it's still unreleased) - maybe that will help.
@radekmie i could somewhat work around the issue.
its really easy to support es-module, e.g. see the first three changes here: https://github.com/react-page/react-page/pull/699/files
many bundlers (e.g. webpack) will then pickup module
entrypoint and use the uncompiled es20xx code there. You can even use dynamic imports for code-splitting then.
Would it be possible to just skip ~objects~ classes altogether? what is extension but saying an object gets it's parent functions and properties; Es6 return { newProp, newFn, ...oldObj }
can do all that without the hubabaloo of classes and interoperability between es5 and esNext, stuff just works.
damn, run again into that problem. Is there another way to extend the base forms?
@refactorized yeah, i try to avoid classes like the plague...
@radekmie i could somewhat work around the issue.
its really easy to support es-module, e.g. see the first three changes here: https://github.com/react-page/react-page/pull/699/files
many bundlers (e.g. webpack) will then pickup
module
entrypoint and use the uncompiled es20xx code there. You can even use dynamic imports for code-splitting then.
@radekmie maybe we can try that? Problem is you can't test that with meteor as it does not support the module entry point. but at least most other bundlers should work
possible workaround:
when using next.js, you might need to configure:
[
"next/babel",
{
"preset-env": {
include: ["@babel/plugin-transform-classes"],
modules: "commonjs",
},
},
]
this will compile classes always down to oldschool es5 even if they are supported. This will unfortunatly increase the bundle size a bit and decrease probably the performance.
It took some time, but we are back, finally with some ideas. We are far too deep in classes to "go back" now (maybe in the future; never say never, huh?), so let's cope with it somehow. We've done some research on how to ship all needed code (both es5 and es6) and not to break everything. A PR will be opened in a second and I'm kindly asking both of you to check it.
@radekmie cool! thx! looks similar to what i did in another project https://github.com/react-page/react-page/pull/699/files
Just ran into this again, since it doesn't seem like a reproduction was ever extracted, here is one: https://github.com/Floriferous/meteor-cypress-debug/tree/bug/class-constructor
EDIT: Workaround for me at the moment is to change this:
// Failing
import AutoForm from "uniforms-material/AutoForm";
import AutoField from "uniforms-material/AutoField";
// Working
import { AutoForm, AutoField } from "uniforms-material";
I just came across this too - ended up using the destructuring import style, the babel plugin "babel-plugin-transform-imports" and meteor 1.8.2's recompile flag to make it work:
{
"babel": {
"plugins": [
[
"transform-imports",
{
"@material-ui/core": {
"transform": "@material-ui/core/${member}",
"preventFullImport": true
},
"@material-ui/icons": {
"transform": "@material-ui/icons/${member}",
"preventFullImport": true
},
"@material-ui/styles": {
"transform": "@material-ui/styles/${member}",
"preventFullImport": true
},
"uniforms": {
"transform": "uniforms/src/${member}",
"preventFullImport": true
},
"uniforms-material": {
"transform": "uniforms-material/src/${member}",
"preventFullImport": true
}
}
],
"lodash",
"npdev-react-loadable-babel"
]
},
"meteor": {
"mainModule": {
"client": "client/main.js",
"server": "server/main.js"
},
"nodeModules": {
"recompile": {
"uniforms": true,
"uniforms-material": true
}
}
}
}
For future reference there is more discussion and some solutions in #612 .
I could not get the tests in my modified copy of uniforms-unstyled to work in a Create react app project due to Jest ignoring the es6 modules and only limited ways to configure jest properly. The production code worked fine though
My solution was to remove all the form (Autoform, Quickfom etc) files from my copy and just import them from the official uniforms-unstyled. Their direct interaction with the field files is not existent and I did not need to modify them.. It where those tests that were failing..
this line fails in meteor 1.7.0.1:
any idea?
full error: