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: Vue.js 3 migration path #17805

Closed
wants to merge 15 commits into from
Closed

POC: Vue.js 3 migration path #17805

wants to merge 15 commits into from

Conversation

sgiehl
Copy link
Member

@sgiehl sgiehl commented Jul 22, 2021

Description:

This is a POC of using Vue.js 3 to replace AngularJS directives & components in Matomo step by step.

It migrates most parts of the SitesManager admin interface, as well as some basic components like enriched-headline, content-block or alert and various related directives and filters.

Current State:

The SitesManager admin should be quite fully migrated, at least some small functional tests were working and also the UI tests are passing (apart from slight UI changes). All main directives of the SitesManager are converted, but some directives like the piwik-fields/piwik-form-fields, are still used and compiled with Angular S, once they are shown.

Making it possible to communicate between piwik-fields in AngularJS and a outer Vue.js component wasn't possible directly, as you can't pass a Vue.js variable into a AngularJS model with a two way data binding. I used a workaround by listening to the native change event, that is triggered when the field's value changes. The value can then be received in Vue.js by directly accessing the AngularJS scope of that element. Similar workarounds might be needed if we don't migrate all directives that are used on one page at once.

I have also changed the content-block to use a Vue.js component instead of the previous AngularJS implementation. This currently breaks most of the pages, as it causes problems on pages using twig templates containing other AngularJS directives within that component. But in general this should work when a page uses only Vue.js components.

Core Concepts

In Vue.js there are actually mainly components.
Besides those components there are also directives, that are meant in another way than in AngularJS. Those can be used to register additional "attribute keywords" like v-model and could be used to implement something like the focus-anywhere-but-here directive.

Other than AngularJS directives it's not possible to let Vue.js components parse by attribute. So something like <div piwik-form-field ...> would need to be converted to <matomo-form-field> for Vue.

Vue.js does not provide any special implementation for controller, model or service. Those can be implemented with native javascript objects if they need to be used in a global way. But there are also Vue.js extensions like https://vuemc.io/ that provide some kind of model feature or https://vuex.vuejs.org/, which provides some kind of state management.

Routing is actually not provided by Vue.js core, but it can be implemented in Vue.js using the official Vue Router (https://next.router.vuejs.org/) or even a custom implementation if needed, or it can be done using some other libraries.

Note: Currently I'm using jQuery within the Vue.js components. If at any point we want to get rid of jQuery as well, we could consider using VueQuery (https://github.com/phanan/vuequery) instead.

Modularization

Modularization is achieved in a way similar to the current AngularJS implementation. New VueJs Components or Methods can be placed in a plugin and need to be loaded using the AssetManager.getJavaScriptFiles event. VueJs 3 is actually meant to build real single page apps, that only have one Vue.js app element containing everything else. As we can't do that at least until AngularJS is removed we need to register the components and functions to all Vue.js elements we want to parse. To achieve that, there is a global matomo javascript class that allows to register components and functions and serves a createVue method that automatically parses an element with Vue.js and registers all known components and methods.

Migration Path

Smaller components can be converted quite simple and we can use the angular directives to render Vue.js components, which will not require any changes in the templates.
I guess the best strategy would be to convert components page by page. Once the page is done we can add a vue-app css-class to the parent element, which will then be parsed with Vue.js after the page is loaded.

Pros & Cons

  • Pros

    • Coding with VueJS is quite fast and simple as it is plain Javascript (might be easier for contributors than TypeScript)
    • We can simply use our current structure and asset management
    • Possibility to switch & use TypeScript in the future if we want to
    • Having templates in twig files is not a problem, as long as the full page uses Vue.js components (mixing them up might cause problems)
  • Cons

    • Mixing Angular JS & Vue.js components does not work when using twig templates. Vue.js can't parse an element within an element that has been parsed as AngularJS directive before.
    • Binding data does not work between the frameworks. This is only possible using native javascript events

@sgiehl sgiehl added the RFC Indicates the issue is a request for comments where the author is looking for feedback. label 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
@sgiehl
Copy link
Member Author

sgiehl commented Feb 14, 2022

closing this one, as the migration is already in progress and the changes here are meanwhile outdated.

@sgiehl sgiehl closed this Feb 14, 2022
@sgiehl sgiehl deleted the vuejspoc branch May 3, 2022 13:15
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