Skip to contentSkip to navigationSkip to topbar
On this page

Migrating to Voice JavaScript SDK 2.0


(information)

Info

This migration guide covers up to version 2.7.2. Please refer to the Voice JavaScript SDK: Changelog page for more details if you are upgrading to a newer version.


Benefits

benefits page anchor

The newest version of the SDK will always have the latest and greatest features, bug fixes, and security patches. We're always adding new capabilities - below is shortlist of notable investments we've made in versions 2.x.

New Features and Improvements

new-features-and-improvements page anchor

Modern design patterns

modern-design-patterns page anchor

The SDK has been updated to use more modern design patterns. Library APIs now use Promises where asynchronous actions occur to help keep your code concise and clean. When registering for incoming calls or making an outgoing call, you can now use the returned Promise to keep your application UI up-to-date.

Support for modern JavaScript frameworks

support-for-modern-javascript-frameworks page anchor

This feature was released with versions 2.6.0 and 2.7.0.

Twilio in-band websocket messaging. The SDK now supports the ability to send messages to and receive messages from backend services through the existing websocket connection.

This feature was released with version 2.2.0.

Older, more generic, error codes have been replaced with more descriptive error codes and objects.

The library now has support for VDI environments, such as Citrix HDX.

This feature was released with version 2.5.0.

Improved performance and security

improved-performance-and-security page anchor

Fixed memory leaks, removed MediaDevice polling, addressed security vulnerabilities, and removed deprecated dependencies.

This feature was released with version 2.6.1.


How can I import the new library into my project?

how-can-i-import-the-new-library-into-my-project page anchor

The library source is hosted in a new GitHub repository(link takes you to an external page). The recommended way to install the module is through npm.

2.x versions of the Voice JavaScript SDK are now published under @twilio/voice-sdk(link takes you to an external page).

1.x versions of the Voice JavaScript SDK are still available as twilio-client(link takes you to an external page).

In the interest of promoting best practices, 2.0 and newer releases will not be uploaded to the Twilio CDN. Existing versions (prior to 2.0) and any further 1.x release will continue to be served via the CDN. However, we still strongly recommend not to link directly to these files in production as it introduces the potential for interruption due to CDN outages.

For customers currently using the CDN, there are a couple of options for switching:

  • If your project uses npm, install the latest version of @twilio/voice-sdk. From here, the built distribution files will be available under node_modules/@twilio/voice-sdk/dist.
  • If your project does not use npm, it's possible to download the latest built artifacts and serve it from your own servers. Each release will have its own tag on GitHub(link takes you to an external page). Download the latest release (the newest tag without -rc), unzip it, and navigate to /dist for the twilio.js and twilio.min.js files.

If your application uses Content Security Policies (CSP)(link takes you to an external page), they need to be updated along with other network configurations such as firewall rules, etc. to allow connections to the new DNS names and IP addresses.

We've renamed the Connection class to Call. This shouldn't affect any public API; however, some internal method names have been updated. Therefore, any code accessing internal methods will break if not updated.

Removal of the Device singleton

removal-of-the-device-singleton page anchor

As part of adapting to modern design patterns, the singleton behavior of Device has been removed.

If your code is similar to the following on 1.x:

const device = Twilio.Device;

Your code on 2.x should create a Device like this:

const device = new Device(token, deviceOptions);

Create a new Device by invoking the constructor. The device.setup method is no longer supported.

If your code is similar to the following on 1.x:

const device = Twilio.Device.setup(...);

Your code on 2.x should create a Device like this:

const device = new Device(token, deviceOptions);

Updating Device configurations after constructing

updating-device-configurations-after-constructing page anchor

Additionally, device.setup will no longer work for updating the Device instance after it has been created. Instead, use device.updateOptions(deviceOptions) to update any of the Device instance options.

The SDK now performs setup only when necessary, decreasing time to a ready application state and only making network connections when needed.

This means that the Device constructor is synchronous and will not cause a signaling channel to be opened. The signaling websocket will be opened when either:

  • device.register is invoked, which registers the Device instance to receive incoming calls.
  • device.connect is invoked, which places an outbound call.

If your application needs to monitor the Device instance registration status, the following events are emitted by the Device instance:

In the scenario such that you are making an outbound call and have not previously registered for inbound calls, you can invoke Call.status to observe the signaling connection status.

Keep the AccessToken up to date

keep-the-accesstoken-up-to-date page anchor

The AccessToken can be updated with device.updateToken(accessToken: AccessToken).

Prior to registering for inbound calls with device.register() or making an outbound call with device.connect(), you can ensure that the AccessToken is valid by listening to the tokenWillExpireEvent.

The following is an example of how to use this feature:

1
/**
2
* This function would fetch an AccessToken from your backend services.
3
*/
4
async function getAccessToken(): string;
5
6
const token = await getAccessToken();
7
const options = { ... };
8
const device = new Device(token, options);
9
10
device.on(Device.EventName.TokenWillExpire, async () => {
11
const newToken = await getAccessToken();
12
device.updateToken(newToken);
13
});

Device status has been removed and refactored as Device state. Note that we no longer represent busy as part of the Device state. You can check if the Device is busy by using the device.isBusy getter method. The ready status has been renamed to Device.State.Registered. The offline status has been renamed to Device.State.Unregistered. An important note is that ready and offline have always indicated registration status rather than signaling connection status. This change aims to clear up confusion.

The functions to accept an incoming call and make an outgoing call now have their parameters standardized. Please see Call.AcceptOptions and Device.ConnectOptions. Note that Device.ConnectOptions extends the Call.AcceptOptions type. Also note that the option types take MediaStreamConstraints as opposed to MediaTrackConstraints. Please see this resource(link takes you to an external page) for more information.

Error reporting is now more descriptive. For backward compatibility, the existing error format is attached under the error.twilioError member of the new error objects.

Some generic error codes have been replaced with more specific and precise error codes. See the following table for changed error codes.

Former Error CodeNew Error CodeError Description
3100353405Ice connection failure
3120131402Unable to acquire user media
3120831401User denies access to user media
3190153000Websocket timeout during preflight

In a prior version, we included ringing states on Call, which were enabled behind the DeviceOptions property enableRingingState. We have removed this flag in 2.0, as it is now on by default.

For full functionality, this still requires setting answerOnBridge in your TwiML. However, even without answerOnBridge, the Call will go through the new ringing state briefly before transitioning to open. When answerOnBridge is enabled, the ringing state will begin when the recipient's phone begins ringing, and transition to open when they have answered and media is established.

This event is no longer raised in response to a local call.ignore(). Instead, it will only be raised when the remote end has canceled the call.


A plus (+) sign denotes an addition to the SDK with 2.x.

A dash (-) denotes a removal from the SDK with 2.x.

-audioConstraints?: MediaTrackConstraints | boolean;

This functionality has been moved to device.connect and call.accept.

1
-codecPreferences?: Connection.Codec[];
2
+codecPreferences?: Call.Codec[];

The functionality of this option remains the same, but the type has changed to reflect the Call class rename.

-debug?: boolean;

This functionality is now covered by the logLevel option.

-enableIceRestart?: boolean;

This functionality is now enabled by default.

-fakeLocalDTMF?: boolean;

This functionality is now enabled by default.

+enumerateDevices?: any;

This parameter enables VDI support.

+getUserMedia?: any;

This parameter enables VDI support.

1
+logLevel?: LogLevelDesc;
2
3
type LogLevelDesc =
4
| 0 | 1 | 2 | 3 | 4 | 5
5
| 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent'
6
| 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'SILENT';

This parameter allows for finer control over logged messages. This option supersedes the functionality that Device.Options.debug and Device.Options.warnings used to provide in a standardized way.

-region?: string;

Connecting by region name is deprecated. Please use edge.

-rtcConfiguration?: RTCConfiguration;

This functionality has been moved to device.connect and call.accept.

maxCallSignalingTimeoutMs

maxcallsignalingtimeoutms page anchor
+maxCallSignalingTimeoutMs?: number;

This parameter enables the new Signaling Reconnection feature.

+RTCPeerConnection?: any;

This parameter enables VDI support.

-warnings?: boolean;

This functionality is now covered by the logLevel option.

+tokenRefreshMs?: number;

This parameter adjusts the event timing of the tokenWillExpire event.


A plus (+) sign denotes an addition to the SDK with 2.x.

A dash (-) denotes a removal from the SDK with 2.x.

-cancelEvent(connection: Connection): void;

The device object will no longer emit a cancel event for canceled incoming calls. Instead, attach a listener to the Call.Event.Cancel event.

-connectEvent(connection: Connection): void;

The device object will no longer emit a connect event when an outgoing call is established. Instead, use the return value from device.connect.

+destroyedEvent(): void;

New API. Raised when the Device has been destroyed.

-disconnectEvent(connection: Connection): void;

This functionality is now provided by Call.Event.Disconnect.

1
-errorEvent(connection: Connection): void;
2
+errorEvent(error: TwilioError, call?: Call): void;

The listener signature for this event has now changed. It will only emit a call as the second parameter when the error is call related, otherwise signaling errors are surfaced as the first parameter to this event.

1
-incomingEvent(connection: Connection): void;
2
+incomingEvent(call: Call): void;

The functionality of this event has not changed, only the names of the parameters as the Connection class has been renamed to Call.

1
-offlineEvent(device: Device): void;
2
+unregisteredEvent(): void;

This event has been renamed to Device.Event.Unregistered.

1
-readyEvent(device: Device): void;
2
+registeredEvent(): void;

This event has been renamed to Device.Event.Registered.

+registeringEvent(): void;

New API. Raised when the Device has started the registration process, in effect after Device.register has been invoked.

+tokenWillExpireEvent(device: Device): void;

New API. Raised when the token passed to the Device is about to expire. The time interval of this event and when the token will actually expire is configurable, see Device.Options.tokenRefreshMs.


A plus (+) sign denotes an addition to the SDK with 2.x.

A dash (-) denotes a removal from the SDK with 2.x.

1
-connections: Connection[];
2
+calls: Call[];

Renamed to reflect the class name change.

-isInitialized: boolean;

The application code should observe the registration status of the Device, either through the registration events or Device.state.

-readonly sounds: Partial<Record<Device.SoundName, (value?: boolean) => void>> = {};

Use Device.audio to access any sound related functionality.

1
-constructor(): Device;
2
-constructor(token: string, options?: Device.Options): Device;
3
-constructor(token?: string, options?: Device.Options): Device;
4
+constructor(token: string, options: Device.Options = {}): Device;

A Device can no longer be constructed without a token.

-activeConnection(): Connection | null | undefined;

The application code should keep track of all calls made or received.

1
-cancel(handler: (connection: Connection) => any): this;
2
-connect(handler: (connection: Connection) => any): this;
3
-disconnect(handler: (connection: Connection) => any): this;
4
-error(handler: (error: Connection) => any): this;
5
-incoming(handler: (connection: Connection) => any): this;
6
-offline(handler: (device: Device) => any): this;
7
-ready(handler: (device: Device) => any): this;

Removed deprecated event handler setter methods.

1
-connect(params?: Record<string, string>, audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): Connection;
2
-connect(paramsOrHandler?: Record<string, string> | ((connection: Connection) => any), audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): Connection | null;
3
+async connect(options: Device.ConnectOptions = {}): Promise<Call>;

Consolidated all options into an options object parameter. See device.connect.

-region(): string;

Connecting by region is deprecated. See Device.edge.

-setup(token: string, options: Device.Options = {}): this;

The Device is now lazily set up when making an outgoing call or registering for incoming calls.

1
-status(): Device.Status;
2
+get state(): Device.State;

Renamed. See device.state.

+get home(): string | null;

New API.

+get identity(): string | null;

New API.

+get isBusy(): boolean;

New API.

1
-registerPresence(): this;
2
+async register(): Promise<void>;

Registration is an asynchronous action and the API now surfaces that with a Promise.

1
-unregisterPresence(): this;
2
+async unregister(): Promise<void>;

Unregistration is an asynchronous action and the API now surfaces that with a Promise.

+updateOptions(options: Device.Options = {}): void;

New API to update the options of a device after the device has been constructed.


This class has been renamed from Connection to Call.

A plus (+) sign denotes an addition to the SDK with 2.x.

A dash (-) denotes a removal from the SDK with 2.x.

1
-readonly callerInfo: Connection.CallerInfo | null;
2
+readonly callerInfo: Call.CallerInfo | null;

The type annotation of this property has been changed to reflect the class name change.

1
-get direction(): Connection.CallDirection;
2
+get direction(): Call.CallDirection;

The type annotation of the return value has been changed to reflect the class name change.

-mediaStream: IPeerConnection;

Private class member, removed from public API. Instead, use the following APIs to get the MediaStream objects associated with a call.

1
getLocalStream(): MediaStream | undefined;
2
getRemoteStream(): MediaStream | undefined;
1
-accept(handler: (connection: this) => void): void;
2
-disconnect(handler: (connection: this) => void): void;
3
-cancel(handler: () => void): void;
4
-error(handler: (error: Connection.Error) => void): void;
5
-ignore(handler: () => void): void;
6
-mute(handler: (isMuted: boolean, connection: this) => void): void;
7
-reject(handler: () => void): void;
8
-volume(handler: (inputVolume: number, outputVolume: number) => void): void;

Setting event handlers is now removed. Please use Call.on or Call.addListener.

1
-accept(audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): void;
2
+accept(options?: Call.AcceptOptions);

Call options have been consolidated into a single object parameter. See call.accept.

-cancel(): void;

Removed deprecated API. To disconnect from an outgoing call at any time, use call.disconnect.

1
-postFeedback(score?: Connection.FeedbackScore, issue?: Connection.FeedbackIssue): Promise<void>;
2
+postFeedback(score?: Call.FeedbackScore, issue?: Call.FeedbackIssue): Promise<void>;

The functionality of this API remains intact. The method parameters have been renamed to reflect the Call class name change.

1
-status(): Connection.State;
2
+status(): Call.State;

The type of the return value has been renamed to reflect the Call class name change.

-unmute(): void;

This deprecated API has been removed. Please use the following for the same effect.

1
const call = device.connect();
2
...
3
call.mute(false); // unmutes the call

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.