@anycable/turbo-stream

中文文档
0.8.1发布于 2025/02/20MITTypeScriptES Module近 30 天下载 10.6万

AnyCable Client plugin to support Turbo Streams

原始使用文档
文档目录7 节
  1. Usage
  2. Compatibility with @hotwired/turbo-rails
  3. Advanced configuration
  4. Delayed unsubscribe
  5. Attaching X-Socket-ID header to Turbo requests
  6. Custom channel classes
  7. Custom tags

npm version

AnyCable Turbo Streams

This package provides AnyCable client integration for Turbo Streams.

The default @hotwired/turbo-rails package doesn't allow you to replace the default Action Cable client with a custom consumer implementation.

🎥 You can learn more about the motivation behind the custom Turbo Streams integration from the AnyCasts episode "Using anycable-client to auto-refresh tokens"

NOTE: Make sure you're not importing @hotwired/turbo-rails or use a custom tag name: Hotwire's package registers the custom element implicitly and it's not possible to override it.

Usage

Assuming that you have a cable instance defined somewhere, to activate Turbo Streams elements you need to add the following code:

import { start } from "@anycable/turbo-stream"
// This is your cable instance
import cable from "cable"
// Explicitly activate stream source elements
start(cable)

This approach let you control when (and how) to start streaming from the <turbo-cable-stream-source> HTML elements.

No server-side changes required. We support all standard functionality: passing a custom channel class and subscription params.

Compatibility with @hotwired/turbo-rails

Our integration aims to be API compatible with the official packages, which means, HTML elements and their attributes are recognized and interpreted the same way as with @hotwired/turbo-rails.

One subtle but important difference is that @anycable/turbo-stream does not activate stream elements added to temporary Turbo cache pages. This way we avoid unnecessary subscriptions/unsubscriptions and potential race conditions.

Advanced configuration

Delayed unsubscribe

When using Turbo Drive for navigation, it's common to have a stream source element attached to the same stream to appear in both old and new HTML. In order to avoid re-subscription to the underlying stream, we can keep the subscription during navigation by postponing the unsubscribe call (or more precisely, channel.disconnect()). Thus, we can avoid unnecessary Action Cable commands and avoid losing messages arrived in-between resubscription. You must opt-in to use this features:

import { start } from "@anycable/turbo-stream"
import cable from "cable"

start(cable, { delayedUnsubscribe: true }) // default is 300ms

start(cable, { delayedUnsubscribe: 1000 }) // Custom number of milliseconds

Attaching X-Socket-ID header to Turbo requests

You can automatically add a header to all Turbo requests with the current socket session ID. This can be used to perform broadcasts to others (see Rails integration docs):

import { start } from "@anycable/turbo-stream"
import cable from "cable"

start(cable, { requestSocketIDHeader: true })

// You can also specify a custom header name
// start(cable, { requestSocketIDHeader: 'X-My-Socket-ID' })

Custom channel classes

You define a custom JS channel class for Turbo Streams subscriptions:

import { TurboChannel } from "@anycable/turbo-stream"

class CustomTurboChannel extends TurboChannel {
  // Constructor receives the current HTML element (turbo-cable-stream-source),
  // a channel name (Turbo::StreamsChannel) by default and subscription params
  constructor(element, channelName, params) {
    // You can override the server-side channel name
    super(element, 'MyTurboChannel', params)
    // Additional state configuration goes here
    this.totalActions = 0
  }

  // You can override receive function to intercept actions
  receive(message) {
    this.totalActions++

    // Ignore every second message
    if (this.totalActions % 2 === 0) return

    // Fallback to the default behaviour,
    // which sends the action to Turbo
    super.receive(message)
  }
}

Another example is a channel which logs all the actions before executing them:

class LogChannel extends TurboChannel {
  receive(message) {
    console.log("TURBO ACTION", message)
    super.receive(message)
  }
}

start(cable, {channelClass: LogChannel})

Custom tags

You can use a custom tag name for Turbo Streams source elements. One use case is to use different JS channels for different tags:

// Assuming you have some special channel class
import { TurboPresenceChannel } from './channel.js'
import { start } from "@anycable/turbo-stream"

import cable from "cable"

// Default behaviour
start(cable)

// Custom behaviour
start(cable, { tagName: 'turbo-presence-source', channelClass: TurboPresenceChannel })

NOTE: You need to create a custom Rails helper to render custom elements. For example:

def turbo_presence_stream_from(*streamables, **attributes)
  attributes[:channel] = attributes[:channel]&.to_s || "Turbo::StreamsChannel"
  attributes[:"signed-stream-name"] = Turbo::StreamsChannel.signed_stream_name(streamables)

  tag.turbo_presence_source(**attributes)
end

版本与发布记录

@anycable/turbo-stream 共发布 21 个版本,首次发布于 2022/05/01;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.8.1latest2025/02/201.7 年前
0.8.02025/02/111.7 年前
0.7.02024/06/042 年前
0.6.02024/05/222 年前
0.5.02024/03/152 年前
0.4.02023/10/143 年前

关于 @anycable/turbo-stream 的常见问题

@anycable/turbo-stream 是什么?

AnyCable Client plugin to support Turbo Streams

如何安装 @anycable/turbo-stream?

在项目目录运行 npm install @anycable/turbo-stream,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@hotwired/turbo(>= 7.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@anycable/turbo-stream 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@anycable/turbo-stream 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@anycable/turbo-stream 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=8.3.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@anycable/turbo-stream 可以商用吗?

@anycable/turbo-stream 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@anycable/turbo-stream 的下载量有多少?

根据 npm 官方下载统计,@anycable/turbo-stream 在 2026/10/06 – 2026/11/04 这 30 天内被下载 106,057 次,日均约 3,535 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@anycable/turbo-stream 还在维护吗?

最新版本 0.8.1 发布于 2025/02/20(1.7 年前);至今共发布 21 个版本,其中过去 12 个月发布了 0 个;首次发布于 2022/05/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。