Skip to content

Commit

Permalink
docs: using Mercure and Hotwire to stream page changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas committed Jan 4, 2021
1 parent f032121 commit e6a199e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/ecosystem/awesome.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

* [Official Mercure support for the Symfony framework](https://symfony.com/doc/current/mercure.html)
* [Official Mercure support for the API Platform framework](https://api-platform.com/docs/core/mercure/)
* [Using Mercure and Hotwire to stream page changes](hotwire.md)
* [Laravel Mercure Broadcaster](https://github.com/mvanduijker/laravel-mercure-broadcaster)
* [Yii Mercure Behavior](https://github.com/bizley/mercure-behavior)
* [GitHub Actions for Mercure](https://github.com/Ilshidur/action-mercure)
Expand Down
77 changes: 77 additions & 0 deletions docs/ecosystem/hotwire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Using Mercure and Hotwire to Stream Page Changes

> [Hotwire](https://hotwire.dev) is an alternative approach to building modern web applications without using much JavaScript by sending HTML instead of JSON over the wire.
Hotwire comes with a handy feature called [Turbo Streams](https://turbo.hotwire.dev/handbook/streams).
Turbo Streams allow servers to push page changes to connected clients in real-time.

Using Mercure to power a Turbo Stream is straightforward, and doesn't require any external dependency:

```javascript
import { connectStreamSource } from "@hotwired/turbo";

// The "topic" parameter can be any string or URI
const es = new EventSource("https://example.com/.well-known/mercure?topic=my-stream");
connectStreamSource(es);
```

The native [`EventSource` class](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) is used to connect to the [Server-Sent Events (SSE)](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) endpoint exposed by [the Mercure hub](../hub/install.md).

## Broadcasting Page Changes With Mercure

To broadcast messages through Turbo Streams, simply send a `POST` HTTP request to [the Mercure hub](../hub/install.md):

curl \
-H 'Authorization: Bearer <snip>' \
-d 'topic=my-stream' \
-d 'data=<turbo-stream action=...' \
-X POST \
https://example.com/.well-known/mercure

* `topic` must be the same topic we used in the JavaScript code ;
* `data` contains the [Turbo Streams messages](https://turbo.hotwire.dev/handbook/streams#stream-messages-and-actions) to broadcast ;
* the `Authorization` header must contain [a valid publisher JWT](../../spec/mercure.md#publication).

[Other Mercure features](../../spec/mercure.md#publication), including broadcasting private updates to authorized subscribers, are also supported.

In this example, we use `curl` but any HTTP client or [Mercure client library](awesome.md#client-libraries) will work.

## Disconnecting From a Stream

To disconnect the stream source, use the `disconnectStreamSource()` function:

```javascript
import { disconnectStreamSource } from "@hotwired/turbo";

disconnectStreamSource(es);
```

## Creating a Stimulus Controller

Mercure also plays very well with [the Stimulus framework](https://stimulus.hotwire.dev/) (another component of Hotwire).

In the following example, we create [a Stimulus controller](https://stimulus.hotwire.dev/handbook/hello-stimulus#controllers-bring-html-to-life) to connect to the SSE stream exposed by the Mercure hub when an HTML element is created, and to disconnect when it is destroyed:

```javascript
// stream_controller.js
import { Controller } from "stimulus";
import { connectStreamSource, disconnectStreamSource } from "@hotwired/turbo";

export default class extends Controller {
connect() {
this.es = new EventSource(this.element.getAttribute("data-url"));
connectStreamSource(this.es);
}

disconnect() {
this.es.close();
disconnectStreamSource(this.es);
}
}
```

```html
<div data-controller="stream" data-url="https://example.com/.well-known/mercure?topic=my-stream">
<!-- ... -->
</div>
```

0 comments on commit e6a199e

Please sign in to comment.