YousefED / SyncedStore

SyncedStore CRDT is an easy-to-use library for building live, collaborative applications that sync automatically.
https://syncedstore.org
MIT License
1.75k stars 54 forks source link

Vue usage without TypeScript? #8

Closed getflourish closed 3 years ago

getflourish commented 3 years ago

This project looks awesome. I was reading about y.js and tried it with Vue which worked, but you seem to have taken it a lot further and almost make the whole magic "invisible".

I’ve tried the example for Vue, but can’t seem to get it to work. How do I need to set up the data without TypeScript?

sharedData: crdt<{
  vehicles: Vehicle[];
}>(doc),

I’ve tried:

sharedData: crdt(doc)

But changing arbitrary keys on sharedData (like sharedData.vehicles) wasn’t noticed.

getflourish commented 3 years ago

Full example:

<template>
  <div>
    {{ players }}
  </div>
</template>

<script>
  import * as Vue from "vue";
  import { crdt, Y, useVueBindings } from "@reactivedata/reactive-crdt";
  import { WebsocketProvider } from "y-websocket";

  // make reactive-crdt use Vuejs internally
  useVueBindings(Vue);

  // Setup Yjs
  const doc = new Y.Doc();

  new WebsocketProvider("ws://localhost:1234", "my-roomname", doc);

  export default Vue.defineComponent({
    mounted() {
      document.addEventListener("mousemove", (event) => {
        this.players[this.id] = {
          x: event.clientX,
          y: event.clientY
        };
      });
    },
    data() {
      return {
        id: Math.random(),
        players: crdt(doc)
      };
    }
  });
</script>
YousefED commented 3 years ago

Thanks for the kind words and reporting the bug @getflourish!

I've fixed it in #9 . I'll also deploy a new version

Looking forward to hearing about your dev experience with reactive-crdt :) Really hopes it simplifies yjs development!

getflourish commented 3 years ago

@YousefED 🤯 Wow, I just updated the package and it worked right away. This is so exciting! This means that Vue data can be synced in realtime between clients: without changing the way components are authored. The implementation details are almost invisible. Fantastic work!

Sidenote: I found your reactive project a few days ago on the "Future of Coding" Slack. I looked into it, but didn’t get it at first, because I wasn’t quite sure if / why I would need it in the context of Vue. But I understood that it could be useful when used with VanillaJS or WebComponents. Now, I found this repo through digging into tiptap and y.js. It’s always fascinating how things connect.

I have my demo running and hope to experiment more with this. Are there any issue / bottlenecks / downsides / performance issues that you already know of?

YousefED commented 3 years ago

@YousefED 🤯 Wow, I just updated the package and it worked right away. This is so exciting! This means that Vue data can be synced in realtime between clients: without changing the way components are authored. The implementation details are almost invisible. Fantastic work!

Yep, thanks!

Sidenote: I found your reactive project a few days ago on the "Future of Coding" Slack. I looked into it, but didn’t get it at first, because I wasn’t quite sure if / why I would need it in the context of Vue. But I understood that it could be useful when used with VanillaJS or WebComponents. Now, I found this repo through digging into tiptap and y.js. It’s always fascinating how things connect.

Correct! Fun that you're also on FoC :) I should share reactive-crdt there as well!

I have my demo running and hope to experiment more with this. Are there any issue / bottlenecks / downsides / performance issues that you already know of?

Exciting. It's early days for the library, so you might run into edge cases every now and then. Feel free to reach out. I don't expect major performance impact until you'd have a huge number of shared objects.

Caveats are similar as for Yjs, most importantly, the way you use types have impact on whether it's truly conflict-free. Yjs works well with Map / Array primitives, and therefor reactive-crdt as well.

Example: if two people would do: store.counter++ (which is store.counter = store.counter + 1) at the same time, the resulting value might only be an increment of 1. So a "conflict free" counter would probably be better represented as

In other words, if your write value directly depends on a read value, your application might not as offline/distributed proof as you'd like. However, in most cases it would resolve to a "last-writer-wins" scenario which is fine for most applications as well.