Giter VIP home page Giter VIP logo

Comments (6)

realityforge avatar realityforge commented on May 18, 2024

We are just getting started with our use of gwt/react so it is interesting to see how it is being used elsewhere. When we started this journey we planned on riding on top of GWTReact and just adding our enhancements as needed. However we found a few things that we wanted to change.

I should note that in an ideal world there would be one java/gwt adapter for react and would be happy if we could just use it. I guess an ideal world would see it generated from the react source code so that the react team is effectively maintaining it. I also don't see a problem with multiple variants, particularly if they are experimenting with different approaches.

So the things we wanted to change. Almost all of these things required breaking backwards compatibility. The things that we wanted which GWTReact would likely get to in time that broke backwards compatibility:

  • Elemental2
  • React 16 (Fragments, componentDidCatch() and Portals being the most interesting, some of which has landed in react4j and some which is still in development in downstream apps)
  • context
  • Improve interoperability with the DevTools. (component display name, callback names etc). Although I am not sure how this could be done gracefully without an annotation processor.

Somethings that we wanted to do which may not ever be desired in GWTReact:

  • Generate all the dom props from typescript type definition file.
  • Remove of need to enable js exports
  • migration of lots of "utilities" from javascript to java. The ultimate goal being to give the closure/gwt compiler the ability to optimize them away unless used. Examples include the removal of dom factories and moving them into java, probably removing usage of React.createElement(..) and direct implementation in java.
  • Rework the way props, state and context is done. Dramatically reduce boilerplate. (This is our next mini project)
    etc.

As our library mandates the use an annotation processor we have gone down the path of code generation to solving a lot of our problems and that is how we ended up with the dual component hierarchy with native versus java components.

We also wanted to make it so it was easy for our components to be fast by default. i.e. Our annotation processor caches event handlers so we could use PureComponents for all of our dumb components. Etc etc.

As to other things like your comments on stateless components. We have them - they just have the same syntax as stateful components. The reason roughly being that in java the number of tokens between the two approach was roughly the same whether you represented them as a functional class or a normal class so no need to add multiple syntaxes for the same thing. That is one of the few things that there is a FAQ for at http://realityforge.org/react4j/faq/#where-is-the-equivalent-of-reacts-stateless-function-components

Anyhoo we have a lot of work planned on react4j and am not sure where it will end up. I am reluctant to try and merge or anything like that as I expect the changes we will be doing will result in a lot of churn. I am sure it will settle in time.

I am happy to work together if you see an area where there is something we could work together.

Thoughts?

from react4j.

ivmarkov avatar ivmarkov commented on May 18, 2024

Sounds like you have an ambitious plan and you need the freedom to experiment, unconstrained by the release cycles and point of views of another library/maintainer. Fair enough.

I will take the freedom to comment on a few technical points:

Elemental2

Are you DOM diffing with React or are you manipulating the native DOM directly? in a 10K React LOC codebase, we have, like, 30 lines of code in total where we need to deal with the native DOM directly (primarily fetching stuff from the native DOM elements on key-press, clipboard copy and a couple of others), where we currently still use the GWT DOM API. Not the end of the world, especially if this is isolated in utility methods. Also, Elemental2 is a moving target still, with the "beta1" tag attached to it (since, like 6+ months in the meantime?). Not exactly giving me a warm fuzzy feeling that we should commit to it right away. With that said, sooner or later it will come: GWTReact/gwt-react#9

React 16 (Fragments, componentDidCatch() and Portals being the most interesting, some of which has landed in react4j and some which is still in development in downstream apps)

Fair enough. But also coming, I think: GWTReact/gwt-react#15

context

I have 0% use of contexts, but my use case is not everybody's use case.
Have you actually tried contributing pull requests to GWTReact? Paul is relatively responsive on these. See here: GWTReact/gwt-react#6

Improve interoperability with the DevTools. (component display name, callback names etc). Although I am not sure how this could be done gracefully without an annotation processor.

I'm a bit lost here. What are you trying to do? Have some meaningful fields when inspecting the ReactElement object from within the Chrome debugger?

Generate all the dom props from typescript type definition file.

Quite ambitious. You need a good TypeScript parser (ideally, the Microsoft one, as TypeScript is also a moving target), that can generate an AST tree and then you can walk the AST and generate your JSInterop annotated Java sources. And if you take the burden to implement all of this, why not walk the extra mile and make it working for all of React, or in fact, for any d.ts file? And then, maybe rather contribute here (https://github.com/ltearno/typescript2java), and once it stabilizes, and you have a good argument, talk to Paul for a change of course regarding how GWTReact is generated/maintained? By the way, the d.ts bindings for React are not maintained by the React team itself.

Remove of need to enable js exports
migration of lots of "utilities" from javascript to java. The ultimate goal being to give the closure/gwt compiler the ability to optimize them away unless used. Examples include the removal of dom factories and moving them into java, probably removing usage of React.createElement(..) and direct implementation in java.

If you - already now - feel the pain of having too many un-minifed JS function calls - fine. But otherwise (a bit Mr Obvious here) with J2CL + webpack/closure minifying/removing dead code on all of the sources combined, JS exports become a non-issue.

As to other things like your comments on stateless components. We have them - they just have the same syntax as stateful components. The reason roughly being that in java the number of tokens between the two approach was roughly the same whether you represented them as a functional class or a normal class so no need to add multiple syntaxes for the same thing. That is one of the few things that there is a FAQ for at http://realityforge.org/react4j/faq/#where-is-the-equivalent-of-reacts-stateless-function-components

I still think this is a bit subjective. For us, for small components, not having the ceremony of inheriting from React.Component, the meaningless constructor, protected ReactElement<?, ?> render(Props props) does count. And also the promise that stateless functions might be lighter-weight and optimized in future React versions.

from react4j.

realityforge avatar realityforge commented on May 18, 2024

Re: Elemental2

We use Elemental2 for much the same purpose as you. However none of our new apps use any of the GWT framework at all. Actually that is a lie we have some common libraries that still use EventBus but that will likely be phased out relatively soon. We want to be able to move to j2cl as soon as it is available. IIRC were have a checkstyle rule that warns on gwt framework imports except for a few classes (ExceptionHandler, Entrypoint etc).

Re: context

We though we had no use for them but it seems a lot of the animation libraries make use of them which we want to port across.

Re: DevTools

React has some pretty nice devtools for chrome and soon to be other browser I believe. See the chrome store. Heres a screen shot from the todo app with dev tools open.

screen shot 2017-11-08 at 9 05 23 pm

The DevTools was one of the draw cards of adopting react.

Re: TypeScript Code Generator

We are not planning to have a typescript interop layer but more to read very specific file and generate a very specific output format. Reading typescript is not the hard problem as such - it is figuring out what we want the output to look like. We still haven't come up with anything we like that is significantly better than what is currently in GWTReact. The best idea we have had is really just a slight improvement ala h1().className('foo').tabIndex(3).children("Hello",span().className('red').children('World')).

If we figure it out I can certainly show you how we did it.

Re: J2CL minifying react

The react js library is a massive way off, being able to be optimized by closure in advanced mode. One of the React core developers is currently tinkering to get it working in whitespace mode with renames disabled so they can replace uglify. I hold out hope that there may be a chance that it could run in advanced mode some day but I would not hold my breath. And you can not get rid of js exports until that happens...

Also: Some of the optimisations I describe are because they are things that the react community has already decided are necessary and implemented as part of jsx compilation in production mode in most apps.

Re: Stateless components

It may not have been obvious from the link above but the code snippets include all the code that is required to implement stateless components using a class syntax. React4j does not require that you implement a constructor ... ever. In fact if you want to implement initialization code you instead override lifecycle method componentDidConstruct. You can see a basic explanation at http://realityforge.org/react4j/compared_to_react/#the-constructor-versus-componentdidconstruct
and an example in TodoEntry class.

if you compare the number of tokens between the Stateless as a Component and Stateless as a Function examples at the above link you will see that there is exactly one token difference (Namely BaseState to indicate the component has no state.) In one of our projects we actually have a StatelessComponent class that you can extend from that would make the two approaches identical in the number of tokens.

When there is a performance difference between SFCs and regular react components we will just update out annotation processor so that our components are exported as SFCs to react (if they can be).

Stylistically you may prefer a function but performance wise and level-of-boilerplate wise there is no benefit to them. And we find that having a single, consistent way to author components makes it easier for people to develop components.

I am not trying to convince you to change but just pointing out that in React4j, some of the problems you see in ES6 and GWTReact do not apply.

Anyhoo I will keep in mind GWTReact and when we figure out where we want to be, if it is compatible with where that project wants to go then I will be happy to collaborate. Right now we are focused on building out what we need for our apps ;)

from react4j.

ivmarkov avatar ivmarkov commented on May 18, 2024

Re: DevTools

React has some pretty nice devtools for chrome and soon to be other browser I believe. See the chrome store. Heres a screen shot from the todo app with dev tools open.

Cool toy. Thanks or the link.
If you are already committed to Java annotations for other reasons, sure - this can be done with annotations & code generation I guess, at least for component names and for callbacks which you implement as Java methods.

We went for a simpler approach. We just call this:

	public  static native <T> T name(T component, String name) /*-{
		if(typeof component.displayName == "undefined")
			component.displayName = name;
			
		return component;
	}-*/;

... from our code base for each custom component. For stateful components, there is probably a cleverer way to do this e.g. in a base class constructor or so, so that you don't have to have it in each custom component constructor. And you can automatically supply the Java class name, so that its simple name is extracted etc. etc.

Re: TypeScript Code Generator

We are not planning to have a typescript interop layer but more to read very specific file and generate a very specific output format. Reading typescript is not the hard problem as such - it is figuring out what we want the output to look like. We still haven't come up with anything we like that is significantly better than what is currently in GWTReact. The best idea we have had is really just a slight improvement ala h1().className('foo').tabIndex(3).children("Hello",span().className('red').children('World')).

If we figure it out I can certainly show you how we did it.

I'm still convinced that parsing TypeScript & generating jsinterop Java bindings is a nontrivial task, but I see where you are going. You just want a more beautiful DSL to fill in the gap of JSX missing in Java.

Here perhaps simple Props interfaces with custom annotations and Java annotation processor generating the DSL code from these might save the day.
In the meantime, we went with a much simpler approach - we just use the "double curly braces" trick described here: GWTReact/gwt-react#16

Pros:

  • Simplicity. No need for code generation
  • Custom props classes are created in no time. Just a bunch of public properties, that's all.

Cons:

  • Not as beautiful as a dedicated DSL. But then, beauty is in the eye of the beholder

Re: J2CL minifying react

The react js library is a massive way off, being able to be optimized by closure in advanced mode. One of the React core developers is currently tinkering to get it working in whitespace mode with renames disabled so they can replace uglify. I hold out hope that there may be a chance that it could run in advanced mode some day but I would not hold my breath. And you can not get rid of js exports until that happens...

What you are referring to? This? https://github.com/facebook/react/pull/10236/files (btw, it is not "tinkering" but merged already, and it is not "whitespace", but "simple mode", but that's a detail).

The way I understand it, this is an effort to improve the React library download code size, which will only slightly benefit people still using React via CDN / separate download or us who still compile Java code separately from JS code with GWT.

I think the above is very different form what I had in mind which is funneling your app generated code generated with J2CL + all 3rd party JS libraries' code TOGETHER via webpack/uglify/closure/whatever (which is the main use case and why j2cl is so important isn't it - it does not optimize by itself), as then -
I was thinking - the closed world assumption kicks in and uglify or closure can minify ALL methods in the app (including the React API, your exported methods from your Java code, etc. etc.; and do some real DCE, etc. etc.) - simply because in an app (unlike a library), there is no API anymore.

Perhaps I'm missing something - correct me if I'm wrong.

from react4j.

realityforge avatar realityforge commented on May 18, 2024

The Closure Compiler change for React that just landed in closure compiler repo is google/closure-compiler#2707

from react4j.

realityforge avatar realityforge commented on May 18, 2024

There does not seem to be an interest in pursuing this. Closing the issue until there is a practical way forward.

from react4j.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.