Vue SDK 2.x to 3.0 migration guide

This topic explains the changes in the Vue SDK 3.0 release and how to adapt code that uses a 2.x version of the Vue SDK to use version 3.0 or later.

Version 3.0 includes several breaking changes. The SDK moved from the standalone launchdarkly-vue-client-sdk package into the js-core monorepo as @launchdarkly/vue-client-sdk. It now builds on the same client-side platform as the JavaScript SDK.

Read the JavaScript SDK 3.x to 4.0 migration guide too

Version 2.x of the Vue SDK wrapped version 3.x of the JavaScript SDK. Version 3.0 of the Vue SDK wraps @launchdarkly/js-client-sdk, which is the JavaScript SDK at version 4.0 and higher.

The changes described in the JavaScript SDK 3.x to 4.0 migration guide also apply to the Vue SDK. They include changes to LDOptions, flag change listeners, the identify method, and analytics events.

Prerequisites

To complete this migration, you need the following:

  • Vue version 3.3 or later
  • The latest 2.x version of the Vue SDK installed in your application. To find it, visit Vue SDK releases on GitHub.

Version 2.0 deprecated the user option, which version 3.0 removes. Your editor should flag instances of user in your code, so you can replace it with context before you begin migrating to 3.0.

Supported Vue versions for Vue SDK v3.0

Version 3.0 of the Vue SDK requires Vue 3.3 or later. The reactive flag keys in version 3.0 use Vue’s toValue function and the MaybeRefOrGetter type introduced in Vue 3.3. To learn more, read Flag evaluation changes.

Understanding what changed in version 3.0

There are several significant changes in version 3.0 of the Vue SDK:

  • Package name and location changes: The package is now @launchdarkly/vue-client-sdk, and several exported names changed.
  • Plugin and options changes: The Vue plugin is now LDVuePlugin, and you pass options to the underlying JavaScript SDK using an ldOptions property object. LDPlugin is still exported, but it is now an interface for plugins to LaunchDarkly clients and not a Vue plugin.
  • Context changes: The context option is now required, and version 3.0 removed the deprecated user option.
  • Client initialization changes: You create the client with the plugin or a provider component, rather than with ldInit.
  • Initialization status changes: useInitializationStatus reports the full initialization lifecycle, and replaces the boolean value that useLDReady returned.
  • Flag evaluation changes: Typed composables such as useBoolVariation replace the generic useLDFlag composable, and each one accepts a reactive flag key.
  • Client access changes: useLDClient returns an LDVueClient object, which adds methods for inspecting the initialization state and subscribing to context changes.
  • Support for multiple LaunchDarkly environments: You can connect to more than one environment from the same application.
  • Removed APIs: This section lists all parts of the version 2.x API that version 3.0 removes.

Package name and location changes

In version 3.0 of the SDK, the package is named @launchdarkly/vue-client-sdk. To begin the migration, uninstall the 2.x package and install the 3.0 package:

npm uninstall launchdarkly-vue-client-sdk

Next, update your import statements. Both the package name and several of the exported names changed:

import { LDPlugin, useLDFlag } from 'launchdarkly-vue-client-sdk';

Plugin and options changes

In version 3.0 of the SDK, the plugin object and its options type are renamed. The options you pass through to the underlying JavaScript SDK move to a dedicated ldOptions property, so they no longer collide with Vue’s own plugin options pattern.

Here are the renamed plugin exports and options:

Version 2.xVersion 3.0
LDPluginLDVuePlugin
LDPluginOptionsLDVuePluginOptions
options, for JavaScript SDK configurationldOptions property
streaming, a top-level optionstreaming, inside ldOptions

Version 3.0 still exports the name LDPlugin, but it refers to a different type. In version 2.x, LDPlugin was the Vue plugin that you installed with app.use(). In version 3.0, LDPlugin is the interface for LaunchDarkly SDK plugins. These plugins extend the LaunchDarkly client rather than your Vue app. You pass these plugins to the underlying JavaScript SDK in the plugins field of ldOptions. If your version 2.x code imports LDPlugin to install the Vue plugin, change that import to LDVuePlugin.

In version 2.x, clientSideID was optional, because you could provide it later in a call to ldInit. Version 3.0 requires both clientSideID and context when you install the plugin or create a provider.

Here is a comparison of plugin registration in v2.x and v3.0:

import { createApp } from 'vue';
import { LDPlugin } from 'launchdarkly-vue-client-sdk';
import App from './App.vue';
createApp(App)
.use(LDPlugin, {
clientSideID: 'example-client-side-id',
context: { kind: 'user', key: 'example-user-key' },
streaming: true,
})
.mount('#app');

Context changes

In version 2.x, you could pass either a context or a deprecated user field to the plugin. If you passed both, context took precedence. If you omitted both, the SDK created an anonymous user context, { kind: 'user', anonymous: true }, on your behalf.

Version 3.0 removes the deprecated user field, and requires you to provide context with LDVuePluginOptions, createLDProvider, and createClient. There is no implicit fallback to an anonymous context. To use an anonymous context, construct it explicitly:

// Omitting both context and user created an anonymous context automatically.
app.use(LDPlugin, {
clientSideID: 'example-client-side-id',
});

To learn more about contexts, read Contexts.

Client initialization changes

In version 3.0 of the SDK, there are two ways to create the client and provide it to your components:

  • LDVuePlugin, which you install with app.use(), provides the client to your entire app.
  • createLDProvider returns a component that you render in your template. Unlike LDVuePlugin, the provider component supports initializing and failed slots. The slots enable you to gate rendering on the initialization state without calling a composable.

Both the plugin and the provider start the client immediately unless you pass deferInitialization: true. If you defer initialization, retrieve the client later with useLDClient() and call client.start() yourself.

Version 3.0 removes the version 2.x ldInit() composable and the LD_INIT injection key it relied on. A descendant component can no longer create the client, because the client always exists as soon as the plugin or provider runs.

Here is the new client initialization pattern:

import { createApp } from 'vue';
import { LDPlugin } from 'launchdarkly-vue-client-sdk';
import App from './App.vue';
createApp(App)
.use(LDPlugin, {
clientSideID: 'example-client-side-id',
context: { kind: 'user', key: 'example-user-key' },
})
.mount('#app');

Here is how to gate rendering with the provider’s slots:

Vue SDK v3.0 gated rendering
<template>
<LDProvider>
<template #initializing>Loading...</template>
<template #failed="{ error }">Error: {{ error.message }}</template>
<MyApp />
</LDProvider>
</template>

Here is the new deferred initialization pattern:

// main.ts
app.use(LDPlugin, { deferInitialization: true });
// In a component:
import { ldInit } from 'launchdarkly-vue-client-sdk';
const [isReady, client] = ldInit({
clientSideID: 'example-client-side-id',
context: { kind: 'user', key: 'example-user-key' },
});

Version 3.0 also adds the startOptions and bootstrap options, which control the initialization timeout and bootstrap data at the plugin or provider level. If you set both bootstrap and startOptions.bootstrap, the top-level bootstrap value takes precedence. Here is an example:

Vue SDK v3.0 startOptions and bootstrap
app.use(LDVuePlugin, {
clientSideID: 'example-client-side-id',
context: { kind: 'user', key: 'example-user-key' },
startOptions: { timeout: 5 },
bootstrap: serverSideFlagValues,
});

For advanced patterns such as testing or multi-step bootstrapping, createClient and createLDProviderWithClient let you create and own the client instance separately from the provider component that renders it. When you use createLDProviderWithClient, you are responsible for calling client.start(). This pattern has no version 2.x equivalent. Here is an example:

Vue SDK v3.0 client and provider ownership
import { createClient, createLDProviderWithClient } from '@launchdarkly/vue-client-sdk';
const client = createClient('example-client-side-id', { kind: 'user', key: 'example-user-key' });
const LDProvider = createLDProviderWithClient(client);
await client.start({ timeout: 5 });

Initialization status changes

In version 2.x, useLDReady() returned a Readonly<Ref<boolean>> object backed by the LD_READY injection key.

Version 3.0 removes both useLDReady and LD_READY. useInitializationStatus() now returns a ComputedRef<InitializationStatus> object. InitializationStatus is a discriminated union that covers the full initialization lifecycle, with a status of 'initializing', 'complete', 'timeout', or 'failed'. If the status is 'failed', the object also includes an error field.

Here is how to read the initialization status:

<script setup lang="ts">
import { useLDReady } from 'launchdarkly-vue-client-sdk';
const isReady = useLDReady();
</script>
<template>
<div v-if="isReady">Ready</div>
<div v-else>Loading...</div>
</template>

To replicate the version 2.x boolean, derive it with computed:

Deriving v2.x boolean status in Vue SDK v3.0
const status = useInitializationStatus();
const isReady = computed(() => status.value.status === 'complete');

Flag evaluation changes

In version 2.x, the generic useLDFlag<T>(key, defaultValue?) composable, backed by the LD_FLAG injection key, evaluated any flag type using a type parameter.

Version 3.0 removes both useLDFlag and LD_FLAG. Flag evaluation now uses typed composables: useBoolVariation, useStringVariation, useNumberVariation, and useJsonVariation. Each composable accepts a flag key and a default value, and infers the return type from the composable name rather than from a type parameter. The default value is now required.

Here is the new flag evaluation pattern:

<script setup lang="ts">
import { useLDFlag } from 'launchdarkly-vue-client-sdk';
const showBanner = useLDFlag<boolean>('show-banner', false);
const theme = useLDFlag<string>('ui-theme', 'default');
</script>

Each typed composable also has a *VariationDetail counterpart that returns the full evaluation detail, including the evaluation reason and the variation index. This has no version 2.x equivalent. Here is an example:

Vue SDK v3.0 flag evaluation detail
import { useBoolVariationDetail } from '@launchdarkly/vue-client-sdk';
const detail = useBoolVariationDetail('example-flag-key', false);
// detail.value.value -> boolean
// detail.value.reason -> LDEvaluationReason
// detail.value.variationIndex -> number | null

In version 3.0, every variation composable also accepts a reactive key, either a Ref<string> or a getter function. This means a component can change which flag it evaluates at runtime without unmounting. Here is an example:

Vue SDK v3.0 runtime flag evaluation
import { ref } from 'vue';
import { useBoolVariation } from '@launchdarkly/vue-client-sdk';
const flagKey = ref('example-flag-key');
const enabled = useBoolVariation(flagKey, false);
flagKey.value = 'another-flag-key'; // `enabled` re-evaluates automatically

Client access changes

In version 2.x, useLDClient(), backed by the LD_CLIENT injection key, returned the base LDClient from the underlying JavaScript SDK.

Version 3.0 removes LD_CLIENT, and useLDClient() returns an LDVueClient. LDVueClient is a superset of LDClient that adds the getInitializationState(), getInitializationError(), onContextChange(), onInitializationStatusChange(), and isReady() methods. All of the existing LDClient methods are still available.

Here is how to access the client:

import { useLDClient } from 'launchdarkly-vue-client-sdk';
import type { LDClient } from 'launchdarkly-vue-client-sdk';
const client: LDClient = useLDClient();
await client.identify({ kind: 'user', key: 'example-user-key' });

Support for multiple LaunchDarkly environments

Version 3.0 adds createLDVueInstanceKey(), which creates a Vue InjectionKey. You can pass the key to the injectionKey option on a plugin or provider, and to the optional injectionKey parameter on any composable. This lets you connect to more than one LaunchDarkly environment in the same application. This has no version 2.x equivalent.

Here is an example:

Vue SDK v3.0 environment injectionKey
import {
createLDVueInstanceKey,
createLDProvider,
useBoolVariation,
} from '@launchdarkly/vue-client-sdk';
const experimentKey = createLDVueInstanceKey();
const ExperimentProvider = createLDProvider('example-client-side-id', context, {
injectionKey: experimentKey,
});
// In a child component:
const inExperiment = useBoolVariation('example-flag-key', false, experimentKey);

If you nest providers that use the same injection key, the inner provider shadows the outer one for its descendants. To avoid this, create a separate injection key for each environment.

Removed APIs

Version 3.0 removes the following APIs:

  • The LDPlugin Vue plugin, replaced with LDVuePlugin. Version 3.0 still exports an LDPlugin type, but it is the interface for LaunchDarkly SDK plugins. To learn more, read Plugin and options changes.
  • LDPluginOptions, replaced with LDVuePluginOptions.
  • ldInit(). The plugin and provider now create the client. To control when the client connects to LaunchDarkly, use deferInitialization and client.start(). To learn more, read Client initialization changes.
  • useLDReady(), replaced with useInitializationStatus().
  • useLDFlag(), replaced with the typed variation composables useBoolVariation(), useStringVariation(), useNumberVariation(), and useJsonVariation().
  • The LD_INIT, LD_READY, LD_CLIENT, and LD_FLAG injection keys. Composables now read from a single injection key, which you can override with createLDVueInstanceKey(). To learn more, read Support for multiple LaunchDarkly environments.
  • The deprecated user option, replaced with the required context option.
  • The top-level streaming option. Set streaming inside ldOptions instead.

Updating your dependencies

@launchdarkly/js-client-sdk is a dependency of @launchdarkly/vue-client-sdk. You do not need to install or update it separately.

To learn more about the version 3.0 API, read the Vue SDK reference.