Client use

So far, we have seen that Feathers with its services, events and hooks can also be used in the browser, which is a very unique feature. By implementing custom services that talk to an API in the browser, Feathers allows us to structure any client-side application with any framework.

This is exactly what Feathers client-side services do. In order to connect to a Feathers server, a client creates Services that use a REST or websocket connection to relay method calls and allow listening to events from the server. This means that we can use a client-side Feathers application to transparently talk to a Feathers server the same way we’d use it locally (as we’ve done in previous examples)!

Note: The following examples demonstrate using the Feathers client through a <script> tag. For more information on using a module loader like Webpack or Browserify and loading individual modules see the client API documentation.

Real-time client

In the real-time chapter we saw an example of how to directly use a websocket connection to make service calls and listen to events. We can also use a browser Feathers application and client services that use this connection. Let’s update public/client.js to:

  1. // Create a websocket connecting to our Feathers server
  2. const socket = io('http://localhost:3030');
  3. // Create a Feathers application
  4. const app = feathers();
  5. // Configure Socket.io client services to use that socket
  6. app.configure(feathers.socketio(socket));
  7. app.service('messages').on('created', message => {
  8. console.log('Someone created a message', message);
  9. });
  10. async function createAndList() {
  11. await app.service('messages').create({
  12. text: 'Hello from Feathers browser client'
  13. });
  14. const messages = await app.service('messages').find();
  15. console.log('Messages', messages);
  16. }
  17. createAndList();

REST client

We can also create services that communicate via REST using many different Ajax libraries like jQuery or Axios. For this example, we will use fetch since it’s built-in modern browsers.

Important: REST services can only emit real-time events locally, to themselves. REST does not support real-time updates from the server.

Since we are making a cross-domain request, we first have to enable Cross-Origin Resource sharing (CORS) on the server. Update app.js to:

  1. const feathers = require('@feathersjs/feathers');
  2. const express = require('@feathersjs/express');
  3. const socketio = require('@feathersjs/socketio');
  4. const memory = require('feathers-memory');
  5. // This creates an app that's both an Express and Feathers app
  6. const app = express(feathers());
  7. // Enable CORS
  8. app.use(function(req, res, next) {
  9. res.header('Access-Control-Allow-Origin', '*');
  10. res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  11. next();
  12. });
  13. // Turn on JSON body parsing for REST services
  14. app.use(express.json())
  15. // Turn on URL-encoded body parsing for REST services
  16. app.use(express.urlencoded({ extended: true }));
  17. // Set up REST transport using Express
  18. app.configure(express.rest());
  19. // Configure the Socket.io transport
  20. app.configure(socketio());
  21. // On any real-time connection, add it to the 'everybody' channel
  22. app.on('connection', connection => app.channel('everybody').join(connection));
  23. // Publish all events to the 'everybody' channel
  24. app.publish(() => app.channel('everybody'));
  25. // Initialize the messages service
  26. app.use('messages', memory({
  27. paginate: {
  28. default: 10,
  29. max: 25
  30. }
  31. }));
  32. // Set up an error handler that gives us nicer errors
  33. app.use(express.errorHandler());
  34. // Start the server on port 3030
  35. const server = app.listen(3030);
  36. server.on('listening', () => console.log('Feathers API started at localhost:3030'));

Note: This is just a basic middleware setting the headers. In production (and applications created by the Feathers generator) we will use the cors module.

Then we can update public/client.js to:

  1. // Create a Feathers application
  2. const app = feathers();
  3. // Initialize a REST connection
  4. const rest = feathers.rest('http://localhost:3030');
  5. // Configure the REST client to use 'window.fetch'
  6. app.configure(rest.fetch(window.fetch));
  7. app.service('messages').on('created', message => {
  8. console.log('Created a new message locally', message);
  9. });
  10. async function createAndList() {
  11. await app.service('messages').create({
  12. text: 'Hello from Feathers browser client'
  13. });
  14. const messages = await app.service('messages').find();
  15. console.log('Messages', messages);
  16. }
  17. createAndList();

What’s next?

In this chapter we learned how to transparently connect to another Feathers server and use its services as we previously did when accessing them server-side. In the last Basics chapter we’ll briefly look at the Feathers generator (CLI) and the patterns it uses to structure an application before jumping into building a full chat application.