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

PoC: React migration path #17802

Closed
wants to merge 17 commits into from
Closed

PoC: React migration path #17802

wants to merge 17 commits into from

Conversation

diosmosis
Copy link
Member

@diosmosis diosmosis commented Jul 22, 2021

Description:

This is a complete (for some definition of "complete") PoC of using React to replace AngularJS directives & components in Matomo, while still running alongside AngularJS.

Like the Angular PoC it migrates the site selector, enriched headline and content block directives, + any related directives/components.

Current State

This one is more functional than the Angular proof of concept. The site selector works without errors or (obvious) issues, as do the other components. It took much less time to code. The only part that is unfinished is the build system, which was not already prepackaged as with Angular. It works, but is not too flexible and will need to be modified (which is doable and shouldn't be too time consuming, but it is more work than w/ Angular).

Core Concepts

Same as with Angular, components are used here to encapsulate parts of the UI. The only difference is where Angular allows many different options, components, directives, pipes, in React there are only components. Everything you can do in Angular you can do in React, it just takes less thinking. For example, the 'focus-anywhere-but-here' directive in the Angular poc is just a component here. The translate pipe in the Angular poc doesn't even exist, we just use _pk_translate() directly (since it's all javascript this is fine).

The small footprint and set of responsibilities React covers means we can implement other things how we want or need, and do not need to be afraid of it breaking in a future release. Routing, for example, is completely out of scope of React. There are libraries to deal with it, but we don't have to use them. And if we keep our existing routing, and update React, nothing will break.

This also goes for having a solution to automatically initialize react components in twig templates. If we choose to keep that part of matomo, and create such a mechanism, updating react is very unlikely to break it. On the other hand, Angular has already deprecated entryComponents, so we have reason to fear future Angular releases.

Another thing to note is that services aren't a special thing here. It's all just javascript, so we create a class for the service and create a new instance to consume it or consume a singleton, as we would in php. Nothing special needed to mark something as a "service".

Finally, this isn't really a React thing, but with companion libraries like redux can allow us to separate component state (what is owned by the component) from application state (what must be kept in sync across components). None of this is truly needed though, and matomo probably doesn't need it.

Modularization

Modularization is achieved in a way similar to the Angular PoC. Each plugin can have a react subfolder that compiles to a UMD. They are loaded if the plugin is activated.

Unlike the ANgular PoC, loading order does not matter, and we do not need to bootstrap the application with any extra modules.

Again two commands are supplied:

  • generate:react: generates a blank library in a plugin
  • corereact:build: builds one or more plugins

It's not needed to use these commands as it is with Angular, but it's far more convenient. Any library that compiles with our webpack config can be used. And you can run the build script directly in any react folder if you want.

The Build System

The build system here uses webpack. It uses an ejected configuration from a create-react-app app modified for this specific use case. Unfortunately, our use case is far away from most react apps, so this may not have been the best approach.

Currently it works, but there's a lot there that we don't need, and a lot we'd need to modify to make sure we have optimal builds (for example, right now parts of core js appear in every plugin build, even though we include it in CoreReact.php).

Migration Path

The migration path is the same as in the Angular PoC. The process of rewriting is the same and we maintain backwards compatibility in the same way. We just don't need to do any sort of downgrading.

Other implementation details/challenges

  • Build system: Again, the build system is the primary challenge. We'd need to spend some time making sure it works how we want. This can be done in parallel to conversion work.

  • Transclusion: Adding angular elements to React is not straightforward. React elements are wrapped HTMLElements, created via the React.createElement function. The elements angular creates when transcluding and rendering are not wrapped this way and I can't see a way to wrap them after they are created. So we can't just add them via the normal React mechanism (this.props.children). Instead there is a TranscludeTarget component that manually appends them to a node. This approach appears to work, but I'm unsure whether it will work w/ more complicated transcludes.

  • Keeping twig templates: We can sort of do this, but not to the extent we currently do. Right now we could, for example, add a

    element and add regular markup inside that we want to be rendered a certain way. We can't do this in React. With AngularJS the inside elements are just normal markup. But in React (as in Angular), everything has to be JSX, we can't really output any HTML and have it automagically turn into react components. The best we can do is something like:

    <div init-react="HeatmapSessionRecording.ManageHeatmapsComponent" .../>
    

    then have React initialize it. Any HTML we put in side would be lost, unless we keep the same transclusion hack that's there now.

Pros & Cons

  • Pros

    • Using babel to provide modern ES... features makes development faster just like TypeScript.
    • Coding in React seems to be faster than with Angular because there's less choice, but the same amount of power.
    • We don't have to do things in a prescribed way and still be confident it won't break if we update React (unlike angular).
    • Module structures end up being a lot simpler. Just folders with JavaScript that get bundled into one file.
    • (Like angular) OOP in the frontend.
  • Cons

    • The build system will need an investment of time.
    • The twig templates will also have to be converted mostly which means more time spent.

@diosmosis diosmosis marked this pull request as draft July 22, 2021 00:33
@diosmosis diosmosis marked this pull request as ready for review July 22, 2021 05:24
@diosmosis diosmosis added the RFC Indicates the issue is a request for comments where the author is looking for feedback. label Jul 22, 2021
@diosmosis diosmosis changed the title PoC: React migration PoC: React migration path Jul 22, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Aug 6, 2021

If you don't want this PR to be closed automatically in 28 days then you need to assign the label 'Do not close'.

@github-actions github-actions bot added the Stale The label used by the Close Stale Issues action label Aug 6, 2021
@diosmosis diosmosis added Do not close PRs with this label won't be marked as stale by the Close Stale Issues action and removed Stale The label used by the Close Stale Issues action labels Aug 6, 2021
@tsteur
Copy link
Member

tsteur commented Aug 25, 2021

fyi closing these for now. We'll still have the code just in case

@tsteur tsteur closed this Aug 25, 2021
@sgiehl sgiehl deleted the react-poc branch April 5, 2023 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Do not close PRs with this label won't be marked as stale by the Close Stale Issues action RFC Indicates the issue is a request for comments where the author is looking for feedback.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants