Introduction to Nuxt Socket.IO

Richard Schloss
Oct 22, 2019 · 7 min read

TL;DR — nuxt-socket-io is a module for the Nuxt framework that allows you to configure IO easily: that is, configure your socket.IO clients once, and then just use them. It plays nicely with Vuex so you can stream incoming data directly to your application state. This article explains how to use it.

Disclaimer: I am the author of the nuxt-socket-io module.


Prerequisites: (listed in order)

  1. VueJS: The progressive JS framework. For the impatient: focus on the components and computed properties. Ignore the installation guide because installing Nuxt (next bullet) will install VueJS.
  2. Nuxt: The progressive VueJS framework that makes it easy to organize and maintain your VueJS app. For the impatient: install npx with npm i -g npx. Then create your Nuxt app with npx create-nuxt-app and follow the prompts. It may be helpful to read the Modules Guide, although not completely required.
  3. Socket.IO: The real-time IO engine for the web

Recommended reading:

  • Vuex: [Global] State management for your app. For understanding core concepts, go here. For practical purposes though, it’s better to understand how Nuxt interacts with Vuex to help make development easier. I.e., configure your stores the “Nuxt way” if using Nuxt (see next bullet).
  • Nuxt Vuex Configuration: Stores are managed in the “stores” folder. Pretty straightforward once you get the hang of it.
  • Rethinking Web IO”: Explains the motivation behind this module’s development

At a very high-level view, nuxt-socket-iois a Nuxt module that wraps around the popular socket.io-client. While it may be tempting to want to use that client directly, you may find yourself having to set up configurations in multiple locations and performing other common tasks repeatedly. When possible, developers want to strive for efficiency and maintainability: code less, repeat less, and accomplish more faster. The nuxt-socket-io module lets you configure almost everything in the nuxt.config.js file, yet still provides you with the socket.io-client instance, so all the API methods you may already be familiar with can be used. Easier for you, easier for me to maintain the plugin.

The advantages of using this module are:

  1. Configure multiple IO sockets with meaningful names directly in the nuxt.config.js file. Easily specify a default, otherwise the first socket in the list will be default. When designing components, you may be interested to see what the component looks like with data injected into it. Various options are out there, but an easy one might be to configure a “test” socket that injects dummy data into your component. This may be particularly useful when the injected data size is large.
  2. Configure Vuex options directly in nuxt.config.js.
  • When certain events are received by your application, you may want to simply trigger Vuex mutations or actions. I.e., as data comes in, it gets written to the application state. When components need that data, simply read from the Vuex stores.
  • When Vuex state changes, you may want changes of certain state properties to trigger notifications back to IO server(s). After all, who says reactivity has to be limited to the browser?
  • It works well with what you have already configured in your stores folder.

Installation: (straightforward)

npm i -S nuxt-socket-io

Registering the module:

In nuxt.config.js simply add it to the modules list:

Module Registration

Once registered, $nuxtSocket will be injected into the context so you can easily use it in your app. However, in order to use it, you must also configure the module options:

Module Options

Configuration

The following is required for each socket:

  • url: The client needs an IO server it can connect to

The following are recommended:

  • default: Specifies the default socket. If you accidentally set this Boolean for multiple sockets, the first found default will be used.
  • name: The name that will be used to look up the requested socket. If a name is not provided, the socket with default set to “true”. If neither a name or the default are set, the first socket will be used.
  • vuex: The mapping of IO events to vuex mutations / actions / emit backs.

For the above example, the following will happen:

  • mutations: When the IO client receives the event “progress”, it will trigger the Vuex “examples/SET_PROGRESS” mutation and pass the event’s data to the mutation. (If, instead, the option were just the string “examples/SET_PROGRESS”, then when that event is received, it would trigger the mutation)
  • actions: When the IO client receives the event “chatMessage” it will trigger the Vuex action “‘FORMAT_MESSAGE”. Again, if just the string “FORMAT_MESSAGE” were specified, that would be treated as both the event name and the Vuex action.
  • emitBacks: When the Vuex property “examples/sample” changes, it will emit back the “examples/sample” event with that property’s data. When the Vuex property “examples/sample2” changes, it will emit the mapped event back to the IO server with that property’s data. The nuxt-socket-io module provides a utility to help mapping this state data so your components can easily use it. See below.

Following along with this example, the store is configured the “Nuxt way” in the “stores” folder. So, stores/index.js contains the “root store”, and stores/examples.js contains “examples store”.

Root store configuration: When FORMAT_MESSAGE action is dispatched, it’s handled here
“Examples” store config. When state mutations are committed, it’s handled here.

Usage

OK, all the boring, boiler-plate work is done! But the idea with module is you should only have to do it once; maintenance should be straightforward. Now using the module in your Vue components is a breeze. Here are some examples:

  1. The index.vue page:
Index Page

The index page uses the mapState helper to bind this.chatMessages to the chatMessages stored in Vuex. In order for chatMessages to be updated in store though, we need to instantiate a socket.IO client. We do this in the mounted() lifecycle hook. Notice, I don’t specify what name to use. By omission, the default socket will be used, which has the vuex options set. I could have just as well specifed name: home in the $nuxtSocket to obtain the same instance. The $nuxtSocket function also accepts a channel as an option, and all other options will be passed as connection options to the underlying socket.io-client. So, reconnection: false will be honored.

While the convenience of Vuex may be nice, you may not always want your data to live globally; you want it only in the scope of your component. In that case, the $nuxtSocket instance is a socket.io-client, so you can use it directly as you would expect: using .emit methods and receiving the data in the callback. That’s exactly what is being done in the getMessage()method.

2. The examples.vue page:

Example of examples.vue page

Recall from the vuex options, we specified “emitBacks” in addition to mutations. Since vuex’s mapState is “getter by default”, if it’s desired to have two way binding, a setter must be provided. There are two ways to accomplish the same thing.

  1. The module provides a “mapState2Way” util that can be imported from eithernuxt-socket-io/utils/common or nuxt-socket-io/utils/esm . The former is in “CommonJS” format, the other is in “ESM” format. To setup a two way binding between the computed property “sample”, the mapState2Way method needs a mapping of the Vuex property to the mutation that will perform the updating. So here, when the Vuex “examples/sample” property changes, we want to commit the “examples/SET_SAMPLE” mutation.
  2. This is the more manual approach, but gives an idea of what the utility is doing. When we want to bind the component’s sample2 property to the Vuex sample2 property, the getter returns it directly. When we want to update the property, we commit the “examples/SET_SAMPLE2” mutation.

Learn by Doing

  1. Clone the git repo: https://github.com/richardeschloss/nuxt-socket-io
  2. Build the dev server: npm run dev:server
  3. Play with the app at: http://localhost:3000

Conclusion

As demonstrated above, the Nuxt-socket-io module allows socket.io-client to easily be integrated and configured in your Nuxt applications. It makes it easy for IO events to be mapped directly to your application state, but also exposes the socket.IO client API directly should you wish to use it. Hopefully, this article and the actual module proves to be helpful.

Credits / Acknowledgements

JavaScript in Plain English

Learn the web's most important programming language.

Richard Schloss

Written by

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade