Hey, this is part 3 of a 5 part series on building a Lightning app. If you haven't read part 1, you can go here and start from the beginning.
Our app as we left it is now a fully functionaly Lightning web app, but it's far from the polished result we're aiming for. It relies on polling the server for updates, and makes the page refresh when we make a post. So we're going to speed things up by replacing some of our traditional calls with Web Sockets.
Web Sockets and Lightning make a great pair, as the ability to make small and frequent payments needs small and frequent messages to be sent back and forth between the client and the server. If you're not familiar with how sockets work, I suggest doing a little light reading before we get started. But don't worry, the concept is extremely simple once you take a look, and I'll try to explain along the way.
Yet again, we'll start with cloning a further iteration of the project. If you want to keep any changes you made to the first part, feel free to manually add the new code.
git clone blah blah
Also yet again, you'll need to install the dependencies we need. We didn't add too many this go-around, but adding web sockets to our API has necessitated a few more:
yarn
Alrighty, now we can get into the code!
We haven't added any new files here, we've just altered some of the previous ones to use sockets instead. Let's start with the server, shall we?
https://gist.github.com/e3575cd60ce7ac67680425bf02e9c0b4
We've added a new websocket endpoint here using the express-ws
module. Unlike GET, POST, PUT, or DELETE requests that return information once as a part of an HTTP request, websocket endpoints open a persistent connection to the server that allow us to pass data back and forth. In this case though, we'll only be passing information down to the client, and otherwise using HTTP requests for everything else.
The first thing we do is grab all of our existing posts, and feed them through the socket. Each post is sent as a "message" of JSON encoded data. We then setup an event listener for new posts, and when they're made, we send a message as they come in. This'll make our application update in real time!
The final bits are just websocket house-keeping. We ping the client every 10 seconds just to keep the connection going (Some servers or clients cut off connections if they don't hear from them for a while.) And once we see the connection is closed, we'll stop sending posts to it.
And that's it for our server! Onto the client:
https://gist.github.com/07b794d330673ededefee4802aa2696b
We've now made our App component the central store of post data, so that our other components can be much simpler, and just take in data as props. As soon as it mounts, it'll open our websocket connection and start listening for posts. It saves them to component state, and passes them to the Posts
and PostForm
components as props. If there are any errors in the connection, we can save that too and display an error message along with a button to call the connect method again.
While our Posts
component is now so simple that it's only a render function, our PostsForm
component has been changed a bit to handle our new socket data:
https://gist.github.com/1c38f20bfe7664f8673ef99b83fd675c
We've replaced our previous methodology of polling to server to see if our post has been accepted. Now we watch for our component updating due to new props being passed, and see if the post that's currently pending is in the list of posts that have been made. If it is, we just reset the form to its initial state so that the user can start posting again immediately.
And that's it for our code overview! There were a few other improvements here that I didn't explicitly cover, but you should check out all of the components and play around a bit yourself to see what you can do.
Up next: We'll be integrating WebLN into our app to allow for a slicker payment experience, as well as message signatures for our posts.