Skip to main content

Momento Web SDK for JavaScript in browsers

Momento provides two JavaScript SDKs; one for Node.js and one for browsers other web applications (this page). The two SDKs have identical APIs, so your code will look the same except for import statements, but under the hood they are built for optimal performance and compatibility in different JavaScript runtime environments.

The Node.js SDK is best suited for server-side use cases. The Momento web SDK, however, allows developers to write JavaScript code that runs in a browser and communicates directly with Momento services. This allows you to avoid the typical overhead of building and operating your own web service to mediate cache or pub/sub calls between the browser and Momento. It also means one less hop for your web traffic, so you can get even better performance out of your browser application. The best of both worlds!

You can also use the web SDK in other non-Node.js JavaScript environments.

The Momento web SDK is available via the npm package @gomomento/sdk-web.

The source code can be found on GitHub: momentohq/client-sdk-javascript.

Requirements

Resources

Momento web SDK and Momento Topics

Momento Topics significantly simplifies publisher-subscriber communication in a browser. Traditionally, developers example of this is a chat application embedded in a website; you are not only building the client code for the browser, but the server-side code for routing all the communications.

This server-side complexity is eliminated by incorporating Momento Topics with the Momento web SDK. Developers can subscribe to Momento Topics directly from the browser. Momento then takes care of all communication when messages are published to the topic, eliminating the need for custom server-side infrastructure for WebSockets!

Using the web SDK for browsers

While the API calls are identical to the Momento Node.js SDK, the import/require statement will consume the @gomomento/sdk-web package from npm, instead of @gomomento/sdk (which is the Node.js SDK).

Here's an example import statement for the web SDK:

import {CacheClient} from ‘@gomomento/sdk-web’;

Credentials for Browsers

In order for your browser application to communicate with Momento services, you will need to provide the browser with a Momento auth token. The recommended practice is to generate a Momento disposable token that has expiring credentials for each browser session. This enables the app to distribute tokens without worrying about your data being compromised.

To create a Momento disposable token for use in the browser, you will generally need a "token vending machine" component. The token vending machine can be a standalone application with an HTTP endpoint that a static website can access, or it can be a component embedded into the server side of your web application, as in our Next.js chat app example.

In either case, you will likely use the Node.js SDK to instantiate a Momento AuthClient and provide it an API key with Super User scope generated via the Momento Console:

new AuthClient({
credentialProvider: CredentialProvider.fromEnvironmentVariable({
environmentVariableName: 'MOMENTO_API_KEY',
}),
});

Then you will use the generateDisposableToken API to create a disposable token that you can vend to the browser. These tokens are short-lived by default and they must expire within one hour.

// Generate a disposable token with read-write access to a specific key in one cache
const oneKeyOneCacheToken = await authClient.generateDisposableToken(
DisposableTokenScopes.cacheKeyReadWrite('squirrels', 'mo'),
ExpiresIn.minutes(30)
);
if (oneKeyOneCacheToken instanceof GenerateDisposableToken.Success) {
console.log('Generated a disposable API key with access to the "mo" key in the "squirrels" cache!');
// logging only a substring of the tokens, because logging security credentials is not advisable :)
console.log(`API key starts with: ${oneKeyOneCacheToken.authToken.substring(0, 10)}`);
console.log(`Expires At: ${oneKeyOneCacheToken.expiresAt.epoch()}`);
} else if (oneKeyOneCacheToken instanceof GenerateDisposableToken.Error) {
throw new Error(
`An error occurred while attempting to call generateApiKey with disposable token scope: ${oneKeyOneCacheToken.errorCode()}: ${oneKeyOneCacheToken.toString()}`
);
}

// Generate a disposable token with read-write access to a specific key prefix in all caches
const keyPrefixAllCachesToken = await authClient.generateDisposableToken(
DisposableTokenScopes.cacheKeyPrefixReadWrite(AllCaches, 'squirrel'),
ExpiresIn.minutes(30)
);
if (keyPrefixAllCachesToken instanceof GenerateDisposableToken.Success) {
console.log('Generated a disposable API key with access to keys prefixed with "squirrel" in all caches!');
// logging only a substring of the tokens, because logging security credentials is not advisable :)
console.log(`API key starts with: ${keyPrefixAllCachesToken.authToken.substring(0, 10)}`);
console.log(`Expires At: ${keyPrefixAllCachesToken.expiresAt.epoch()}`);
} else if (keyPrefixAllCachesToken instanceof GenerateDisposableToken.Error) {
throw new Error(
`An error occurred while attempting to call generateApiKey with disposable token scope: ${keyPrefixAllCachesToken.errorCode()}: ${keyPrefixAllCachesToken.toString()}`
);
}

// Generate a disposable token with read-only access to all topics in one cache
const allTopicsOneCacheToken = await authClient.generateDisposableToken(
TokenScopes.topicSubscribeOnly('squirrel', AllTopics),
ExpiresIn.minutes(30)
);
if (allTopicsOneCacheToken instanceof GenerateDisposableToken.Success) {
console.log('Generated a disposable API key with access to all topics in the "squirrel" cache!');
// logging only a substring of the tokens, because logging security credentials is not advisable :)
console.log(`API key starts with: ${allTopicsOneCacheToken.authToken.substring(0, 10)}`);
console.log(`Expires At: ${allTopicsOneCacheToken.expiresAt.epoch()}`);
} else if (allTopicsOneCacheToken instanceof GenerateDisposableToken.Error) {
throw new Error(
`An error occurred while attempting to call generateApiKey with disposable token scope: ${allTopicsOneCacheToken.errorCode()}: ${allTopicsOneCacheToken.toString()}`
);
}

// Generate a disposable token with write-only access to a single topic in all caches
const oneTopicAllCachesToken = await authClient.generateDisposableToken(
TokenScopes.topicPublishOnly(AllCaches, 'acorn'),
ExpiresIn.minutes(30)
);
if (oneTopicAllCachesToken instanceof GenerateDisposableToken.Success) {
console.log('Generated a disposable API key with access to all topics in the "squirrel" cache!');
// logging only a substring of the tokens, because logging security credentials is not advisable :)
console.log(`API key starts with: ${oneTopicAllCachesToken.authToken.substring(0, 10)}`);
console.log(`Expires At: ${oneTopicAllCachesToken.expiresAt.epoch()}`);
} else if (oneTopicAllCachesToken instanceof GenerateDisposableToken.Error) {
throw new Error(
`An error occurred while attempting to call generateApiKey with disposable token scope: ${oneTopicAllCachesToken.errorCode()}: ${oneTopicAllCachesToken.toString()}`
);
}

For more information on Momento tokens, including DisposableTokenScope and permission objects for authorization, see Auth API Reference.

FAQ

Is the traffic from the browser encrypted?
As with all traffic with Momento services, the web SDK is fully encrypted on the wire. In addition, the SDK uses TLS 1.2+ encryption.