← Back to Tutorials Chapter 8

Advanced Communication

GraphQL

GraphQL is a query language for APIs that allows clients to request exactly the data they need. Use express-graphql and graphql packages to add GraphQL to your Express server.

// Install: npm install express-graphql graphql

const { buildSchema } = require('graphql');
const { graphqlHTTP } = require('express-graphql');

// Define schema
const schema = buildSchema(`
  type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post]
  }

  type Post {
    id: ID!
    title: String!
    content: String
  }

  type Query {
    user(id: ID!): User
    users: [User]
    posts: [Post]
  }

  type Mutation {
    createUser(name: String!, email: String!): User
    createPost(title: String!, content: String): Post
  }
`);

// Resolvers
const root = {
  users: () => [
    { id: '1', name: 'Alice', email: 'alice@example.com' }
  ],
  user: ({ id }) => ({
    id, name: 'Alice', email: 'alice@example.com'
  })
};

app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: root,
  graphiql: true  // Enable GraphQL IDE
}));

Socket.IO

Socket.IO enables real-time, bidirectional event-based communication between web clients and servers.

// Install: npm install socket.io

const http = require('http');
const { Server } = require('socket.io');

const server = http.createServer(app);
const io = new Server(server, {
  cors: { origin: '*' }
});

io.on('connection', (socket) => {
  console.log('A user connected:', socket.id);

  // Listen for events
  socket.on('chat message', (msg) => {
    console.log('Message received:', msg);
    // Broadcast to all connected clients
    io.emit('chat message', {
      user: socket.id,
      message: msg,
      timestamp: new Date()
    });
  });

  socket.on('join room', (room) => {
    socket.join(room);
    socket.to(room).emit('notification', `${socket.id} joined ${room}`);
  });

  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

server.listen(3000, () => {
  console.log('Socket.IO server running on port 3000');
});

Client-Side Socket.IO

const socket = io('http://localhost:3000');

// Send message
socket.emit('chat message', 'Hello everyone!');

// Listen for messages
socket.on('chat message', (data) => {
  console.log(`${data.user}: ${data.message}`);
});

WebSockets (Native)

Node.js also supports raw WebSockets via the ws library for lower-level control.

// Install: npm install ws

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('WebSocket client connected');

  ws.on('message', (message) => {
    console.log('Received:', message.toString());

    // Broadcast to all clients
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(`Echo: ${message}`);
      }
    });
  });

  ws.send('Welcome to the WebSocket server!');
});
When to use what? Use Socket.IO for higher-level features like rooms, namespaces, and automatic reconnection. Use raw WebSockets (ws) when you need minimal overhead and full control.

Polling vs WebSockets

FeatureHTTP PollingWebSockets
ConnectionOpens and closes each requestPersistent open connection
OverheadHigh (HTTP headers each time)Low (minimal framing)
Real-timeNear real-time (depends on interval)True real-time
Exercise: Build a real-time chat application with Socket.IO that supports multiple chat rooms. Users should be able to join a room, send messages visible only to that room, and see who is typing.