LaunchDarkly Bootstrapping: (JS) Property Assignment Expected

1.4k Views Asked by At

I am setting up LaunchDarkly to control my first feature flag and its working fine from server & client side. Now I am trying LaunchDarkly Bootstrap approach (From the below given Link) and tried like below my code, but it's not accepting the double braces and I do not know How to get flag value by using the bootstrap approach, so where I did go wrong in my code?. Could anyone please help me with an example?

Link,

https://docs.launchdarkly.com/docs/js-sdk-reference#section-bootstrapping

Initialized client with Bootstrap option as below,

client = LDClient.initialize(sdkKey, userContext.user, options = {
        bootstrap: {
            {{ ldclient.all_flags(userContext.user) }}
       }
    });

And my function to get the flag value,

isFeatureEnabled: function (featureFlag, properties) {
        console.log("Before Variation");
        //we shall update the custom properties into user context.
        if (properties) {
            for (var k in properties) {
                userContext.user.custom[k] = properties[k];
            }
        }
        //later make the identity call to update the user details.
        client.identify(userContext.user, null, function () { /*rules updated*/
            console.log("New user's flags available");
            //validate the feature flag
            var showFeature = client.variation(featureFlag);
            if (!showFeature) {
                window.in8.platform.showUnauthorized('');
            }
            console.log("after Variation");
        });
    }
1

There are 1 best solutions below

1
On BEST ANSWER

Full disclosure, My name is John, and I am part of the support team here at LaunchDarkly. I'll be happy to help you out with this problem

Firstly, it appears you are using an older version of the bootstrapping example. The new example has a typo fix, and uses the new all_flags_state method.

I see two major issues here. There is the primary issue of how to bootstrap flag variations from the back-end to the front-end, and how to appropriately utilize LaunchDarkly when using bootstrapping. I will tackle the issue of how to bootstrap flag variations from the back-end first.

The example in LaunchDarkly's documentation utilizes templating to include the bootstrapped values to the front end. Templating is a strategy for including programmatically generated content in your static source or text files. Templating is commonly used when compiling or deploying code, or at runtime when serving content to clients. This is done to render information only available at that time in the final version.

Different templating languages behave in different ways, but generally speaking you include tokens in your source or text files which direct the template renderer to replace that token with data you supply it.

In the documentation it mentions that this example is for templating using Ruby, but the example is using Mustache rendering, and Mustache is available in many different languages. Templating is a strategy for including programmatically generated content in your static source or text files. This is commonly used when compiling or deploying code, or at runtime when serving content to clients. This is done to render information only available at that time in the final version.

The example may not work depending on which back-end language and framework you are using. According to the tags associated with your question, I feel safe to assume that you are using .NET to power your back-end, which doesn't have a prescribed templating language. There are many open source solutions out there, though.

In the following example I'm going to use https://github.com/rexm/Handlebars.Net to render the a users bootstrapped flag values into the result variable. I am going to borrow code available from the example in the handle bars repo, and from LaunchDarkly's hello-bootstrap and hello-dotnet repos, which are available here: https://github.com/launchdarkly/hello-bootstrap & https://github.com/launchdarkly/hello-dotnet

string source =
@"
<html>
    <head>
        <script src=""https://app.launchdarkly.com/snippet/ldclient.min.js""></script>
        <script>
            window.ldBootstrap={{ldBootstrap}};
            window.ldClientsideId=""{{ldClientsideId}}"";
            window.ldUser={{ldUser}};
        </script>
    </head>
    <body>
        <h1>LaunchDarkly server-side bootstrap example</h1>
        <ul>
             <li><code>normal client</code>: <span class=""normal"">initializing…</span></li>
             <li><code>bootstrapped client</code>: <span class=""bootstrap"">initializing…</span></li>
        </ul>

        <script>
            var user = window.ldUser;
            console.log(`Clients initialized`);
            var client = LDClient.initialize(window.ldClientsideId, user);
            var bootstrapClient = LDClient.initialize(window.ldClientsideId, user, {
                bootstrap: window.ldBootstrap
            });
            client.on('ready', handleUpdateNormalClient);
            client.on('change', handleUpdateNormalClient);
            bootstrapClient.on('ready', handleUpdateBootstrapClient);
            bootstrapClient.on('change', handleUpdateBootstrapClient);
            function handleUpdateNormalClient(){
                console.log(`Normal SDK updated`);
                render('.normal', client);
            }
            function handleUpdateBootstrapClient(){
                console.log(`Bootstrapped SDK updated`);
                render('.bootstrap', bootstrapClient);
            }

            function render(selector, targetClient) {
                document.querySelector(selector).innerHTML = JSON.stringify(targetClient.allFlags(user), null, 2);
            }
        </script>
    </body>
</html>";

var template = Handlebars.Compile(source);

Configuration ldConfig = LaunchDarkly.Client.Configuration.Default("YOUR_SDK_KEY");
LdClient client = new LdClient(ldConfig);
User user = User.WithKey("[email protected]")
    .AndFirstName("Bob")
    .AndLastName("Loblaw")
    .AndCustomAttribute("groups", "beta_testers");

var data = new {
    ldBootstrap: JsonConvert.SerializeObject(client.AllFlagsState(user)),
    ldUser = JsonConvert.SerializeObject(user),
    ldClientsideId = "YOUR_CLIENT_SIDE_ID"
};

var result = template(data);

You could take this example and adapt it to render your static source code when serving the page to your users.

The second issue is how you are utilizing the SDK. I see that you are calling identify before evaluating your user every time. Each time you call identify the SDK needs to reinitialize. This means that even after bootstrapping your initial variations you will force the SDK to reinitialize by calling identify, removing all benefits of bootstrapping. As a solution, detect if your user object has changed. if it has, then call identify. Otherwise, do not call identify so that the SDK uses the cached user attributes.

If you want to dive deeper into this and provide us with some more of the source for your wrapper you can reach out to us at [email protected]