Browser SDKs

Vue SDK

Install and configure the Vue SDK, and evaluate configs and feature flags in Vue components

Introduction

The Vue SDK is intended to be used by Vue web applications running on modern web browsers. All modern web browsers on popular platforms should be supported.

The minimum supported version of Vue is 3.2.24.

Browser SDKs are tested on the latest versions of Chrome, Firefox, Safari, and Edge.

Telemetry collection within browser SDKs uses Web Workers to aggregate and send telemetry data. If the SDK runs on older browsers without Web Workers support, config evaluation will continue to work but no telemetry data will be collected for that session.

Installation

The SDK can be installed from NPM: https://www.npmjs.com/package/@configdirector/vue-sdk

npm install --save @configdirector/vue-sdk

Configure the plugin

Configure the Vue plugin with your client SDK key. This approach installs the ConfigDirectorPlugin and initializes the client asynchronously while your app is rendering:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";

const app = createApp(App);

app.use(ConfigDirectorPlugin, { sdkKey: "YOUR-CLIENT-SDK-KEY" });

app.mount("#app");

Alternatively, you can explicitly await on initializing the client before mounting the Vue app. The initialization timeout can be provided in the timeout option in milliseconds (defaults to 3,000ms). If initialization times out, the client will be returned and it will continue to attempt to initialize in the background:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin, initializeClient } from "@configdirector/vue-sdk";

async function bootstrap() {
  const app = createApp(App);

  const client = await initializeClient({ sdkKey: "YOUR_CLIENT_SDK_KEY" });
  app.use(ConfigDirectorPlugin, client);

  app.mount("#app");
}

bootstrap();

Additional configuration options

These configuration options can be passed in as plugin options to the ConfigDirectorPlugin or as additional options to initializeClient.

context

The user context to be used during targeting rules evaluation:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";

const app = createApp(App);

app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR-CLIENT-SDK-KEY",
  context: {
    id: "12345",
    name: "Example User",
    traits: {
      region: "North America", // Any arbitrary traits which can be referenced in targeting rules
    },
  },
});

app.mount("#app");

logger

By default, the SDK logs to the console and it is set to log warnings and errors only. You can configure a logger by either creating a ConfigDirector console logger with a different log level, or by implementing the ConfigDirectorLogger interface to provide your own logger. The interface can be used to create an adapter to another logging library.

Configure the ConfigDirector console logger to a different level:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin, createConsoleLogger } from "@configdirector/vue-sdk";

const app = createApp(App);

app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR-CLIENT-SDK-KEY",
  logger: createConsoleLogger("debug"),
});

app.mount("#app");

Implement your own logger adapter:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin, ConfigDirectorLogger } from "@configdirector/vue-sdk";

const myLogger: ConfigDirectorLogger = {
  debug: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  info: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  warn: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
  error: function (message: string, ...args: any): void {
    // your specific logging library implementation here
  },
};

const app = createApp(App);

app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR-CLIENT-SDK-KEY",
  logger: myLogger,
});

app.mount("#app");

appName and appVersion

These options allow you to provide your application's name and version. These values can be used in targeting rules conditionals. For example, if a certain feature should only be enabled starting with a certain version of your application.

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";

const app = createApp(App);

app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR-CLIENT-SDK-KEY",
  appName: "YOUR-APP-NAME",
  appVersion: "1.0.2",
});

app.mount("#app");

timeout

The timeout, in milliseconds, to be used in initialization and when updating the context. This is how long the initializeClient function will wait for data from ConfigDirector services before resolving its Promise. If the timeout is reached, initializeClient will return but the client will still be in an unready status and returning default values. The client will continue to attempt to connect and retrieve config values in the background.

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin, initializeClient } from "@configdirector/vue-sdk";

async function bootstrap() {
  const app = createApp(App);

  const client = await initializeClient({
    sdkKey: "YOUR_CLIENT_SDK_KEY",
    timeout: 2_000, // 2,000 milliseconds timeout, defaults to 3,000
  });
  app.use(ConfigDirectorPlugin, client);

  app.mount("#app");
}

bootstrap();

mode

The connection mode, which can be either streaming or polling. It is recommended to use the default of streaming unless you have a specific need to use polling instead. Defaults to streaming.

pollingInterval

The interval, in seconds, between requests for config updates when mode is polling. It has no effect in streaming mode. A value below the minimum of 30 seconds is raised to 30 seconds and a warning is logged. Defaults to 60 seconds. See Polling intervals.

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";

const app = createApp(App);
app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR_CLIENT_SDK_KEY",
  mode: "polling",
  pollingInterval: 120,
});
app.mount("#app");

url

The base URL used to connect to ConfigDirector services. This should only be provided if your environment requires you to configure a proxy server in order to connect to ConfigDirector services.

Retrieve config values

Retrieve a config value with the useConfigValue composable:

YourComponent.vue
<script setup lang="ts">
import { useConfigValue } from "@configdirector/vue-sdk";

const { value } = useConfigValue("my-config-key", false);
</script>

<template>
  <div>my-config-key is : {{ value }}</div>
</template>

You can also determine if the client is still initializing, so rather than transition from the default value to the evaluated value, you can show a loading state until the client is ready and config values are evaluated:

YourComponent.vue
<script setup lang="ts">
import { useConfigValue } from "@configdirector/vue-sdk";

const { value, loading } = useConfigValue("my-config", "default value");
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else>my-config is : {{ value }}</div>
</template>

Alternatively, you can also use the useClientStatus composable to retrieve just the status:

YourComponent.vue
<script setup lang="ts">
import { useClientStatus } from "@configdirector/vue-sdk";

const { loading } = useClientStatus();
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else><SomeComponentThatUsesConfigValues /></div>
</template>

Update the user context

A user context can be provided when initializing the plugin:

main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";

const app = createApp(App);

app.use(ConfigDirectorPlugin, {
  sdkKey: "YOUR-CLIENT-SDK-KEY",
  context: {
    id: "12345",
    name: "Example User",
    traits: {
      region: "North America", // Any arbitrary traits which can be referenced in targeting rules
    },
  },
});

app.mount("#app");

The user context can also be updated via the useContext composable:

YourComponent.vue
<script setup lang="ts">
import { useConfigValue, useContext } from "@configdirector/vue-sdk";

const { updateContext } = useContext();
const { value } = useConfigValue("my-config-key", false);

const onUpdate = () => {
  updateContext({
    id: "654321",
    name: "Another User",
    traits: {
      region: "Australia",
    },
  });
};
</script>

<template>
  <div>my-config-key is : {{ value }}</div>
  <button type="button" @click="onUpdate">Update Context</button>
</template>
In client SDKs (browser and mobile), updating the user context re-establishes a new connection to ConfigDirector servers with the new context. While the new connection is in flight, config values will continue to evaluate to the currently cached values from the prior user context.

useClient composable

In the event that you need to have access to the underlying Javascript ConfigDirectorClient instance for more complex behaviors, you can access the instance via the useClient composable:

YourComponent.vue
<script setup lang="ts">
import { useClient } from "@configdirector/vue-sdk";

const { client } = useClient();

// Utilize the client for more involved logic
</script>

<template>
  <div>A component with more complex usage</div>
</template>
Proceed with caution when using the useClient composable. The useConfigValue and useContext composables manage listeners and cleanup automatically. However, if you make use of the useClient composable, you must manage cleaning up any listeners yourself.
Additionally, any calls to dispose, unwatch, or unwatchAll on the client instance can have unintended side effects and may result in subtle bugs.

Test your components

Use the SDK's testing entry point, @configdirector/vue-sdk/testing, to test components that read your configs and flags. It creates a test client: the SDK's real client connected to an in-memory server that your test controls. Only the connection to ConfigDirector is replaced. Everything else is the same code that runs in production, including the plugin and the composables, so your components behave exactly as they do against ConfigDirector, and no network connection is opened and no telemetry is sent.

Install the production plugin with the test client's client, the same way you would install it with a pre-initialized client:

Checkout.test.ts
import { nextTick } from "vue";
import { render, screen } from "@testing-library/vue";
import { ConfigDirectorPlugin } from "@configdirector/vue-sdk";
import { createTestClient } from "@configdirector/vue-sdk/testing";
import Checkout from "./Checkout.vue";

test("shows the new checkout when the flag is on", async () => {
  const testClient = createTestClient({ values: { "new-checkout": true } });

  render(Checkout, { global: { plugins: [[ConfigDirectorPlugin, testClient.client]] } });

  await screen.findByText("New checkout");

  testClient.setValue("new-checkout", false);
  await nextTick();
  screen.getByText("Classic checkout");
});

The plugin calls initialize on a client that is neither ready nor initializing, so the first assertion uses findBy… rather than getBy…; a test client whose client was initialized before app.use is ready on the first render, as with initializeClient. Await nextTick() after setValue, removeValue, and replaceValues, since they update the composables' refs synchronously and Vue renders on the next tick. The plugin's clientReady and contextUpdated handlers stay registered for the app's lifetime, as in production.

Test client controls

values, setValue, removeValue, and replaceValues take native values, and the config type follows from each value: a boolean, an integral number (integer), any other number (float), a string, or a plain object or array (json). holdInitialization, completeInitialization, and failInitialization drive initialize, so the loading and default statuses can be tested, and holdContextUpdate, completeContextUpdate, and failContextUpdate do the same for updateContext. contextUpdates records the context of every initialize and updateContext call. The JavaScript SDK's testing section describes every control and what to expect from the client.