-
Notifications
You must be signed in to change notification settings - Fork 31
chore: add an example app for browser sdk #1019
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1048727
31e0dd9
f4ad1e7
22f3a41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # LaunchDarkly sample javascript application | ||
|
|
||
| # ⛔️⛔️⛔️⛔️ | ||
|
|
||
| > [!CAUTION] | ||
| > This example is created against a non-production SDK which means things may change and this example might | ||
| > not work while this message is visible. | ||
|
|
||
| # ☝️☝️☝️☝️☝️☝️ | ||
|
|
||
| We've built a simple browser application that demonstrates how this LaunchDarkly SDK works. | ||
|
|
||
| Below, you'll find the build procedure. For more comprehensive instructions, you can visit your [Quickstart page](https://app.launchdarkly.com/quickstart#/) or | ||
| the [{name of SDK} reference guide](https://docs.launchdarkly.com/sdk/client-side/javascript). | ||
|
|
||
| ## Build instructions | ||
|
|
||
| Modify [app.ts](./src/app.ts) with the following changes: | ||
|
|
||
| 1. Set the value of the {`clientSideID`} variable in {file name} to your client-side ID: | ||
| ```typescript | ||
| const clientSideID = "my-client-side-id"; | ||
| ``` | ||
|
|
||
| 2. If there is an existing boolean feature flag in your LaunchDarkly project that | ||
| you want to evaluate, set `flagKey` to the flag key: | ||
| ```typescript | ||
| const flagKey = "my-flag-key"; | ||
| ``` | ||
|
|
||
| 3. If you haven't already, install and build the project: | ||
| ```bash | ||
| yarn && yarn build | ||
| ``` | ||
|
|
||
| 4. On the command line, run `yarn start` | ||
| ```bash | ||
| yarn start | ||
| ``` | ||
| > [!NOTE] | ||
| > The `yarn start` script simply runs `open index.html`. If that is not working for you, | ||
| > you can open the `index.html` file in a browser for the same results. | ||
|
|
||
| The application will run continuously and react to the flag changes in LaunchDarkly. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| body { | ||
| margin: 0; | ||
| background: #373841; | ||
| color: white; | ||
| font-family: | ||
| -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', | ||
| 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; | ||
| -webkit-font-smoothing: antialiased; | ||
| -moz-osx-font-smoothing: grayscale; | ||
| text-align: center; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1"> | ||
| <title>LaunchDarkly tutorial</title> | ||
| <script src="./dist/app.js" defer></script> | ||
| <link rel="stylesheet" href="./index.css"> | ||
| </head> | ||
| <body></body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "name": "@launchdarkly/browser-example", | ||
| "version": "0.0.0", | ||
| "private": true, | ||
| "description": "LaunchDarkly example for JavaScript Browser SDK", | ||
| "homepage": "https://github.com/launchdarkly/js-core/tree/main/packages/sdk/browser/example", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/launchdarkly/js-core.git" | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "packageManager": "yarn@3.4.1", | ||
| "type": "module", | ||
| "scripts": { | ||
| "start": "open index.html", | ||
| "clean": "rm -rf dist dist-static", | ||
| "build": "npm run clean && tsdown" | ||
| }, | ||
| "dependencies": { | ||
| "@launchdarkly/js-client-sdk": "workspace:^" | ||
| }, | ||
| "devDependencies": { | ||
| "tsdown": "^0.17.0-beta.4", | ||
| "typescript": "^5.9.3" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { initialize } from '@launchdarkly/js-client-sdk'; | ||
|
|
||
| // Set clientSideID to your LaunchDarkly client-side ID | ||
| const clientSideID = ''; | ||
|
|
||
| // Set flagKey to the feature flag key you want to evaluate | ||
| const flagKey = 'sample-feature'; | ||
|
|
||
| // Set up the evaluation context. This context should appear on your | ||
| // LaunchDarkly contexts dashboard soon after you run the demo. | ||
| const context = { | ||
| kind: 'user', | ||
| key: 'example-user-key', | ||
| name: 'Sandy', | ||
| }; | ||
|
|
||
| const div = document.createElement('div'); | ||
| document.body.appendChild(div); | ||
| div.appendChild(document.createTextNode('Initializing...')); | ||
| try { | ||
| const ldclient = initialize(clientSideID); | ||
| const render = () => { | ||
| const flagValue = ldclient.variation(flagKey, false); | ||
| const label = `The ${flagKey} feature flag evaluates to ${flagValue}.`; | ||
| document.body.style.background = flagValue ? '#00844B' : '#373841'; | ||
| div.replaceChild(document.createTextNode(label), div.firstChild as Node); | ||
| }; | ||
|
|
||
| ldclient.on('error', () => { | ||
| div.replaceChild(document.createTextNode('Error caught in client SDK'), div.firstChild as Node); | ||
| }); | ||
|
|
||
| ldclient.on('change', () => { | ||
| render(); | ||
| }); | ||
|
|
||
| ldclient.identify(context).catch(() => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we moved to a result returning method, we shouldn't need the catch, correct? Or we need to make sure we cannot throw from that method.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can assume top-level await? Then just await the result? |
||
| div.replaceChild(document.createTextNode('Error identifying client'), div.firstChild as Node); | ||
| }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Identify error handling uses catch but promise never rejectsThe |
||
| } catch (error) { | ||
| div.replaceChild( | ||
| document.createTextNode(`Error initializing LaunchDarkly client: ${error}`), | ||
| div.firstChild as Node, | ||
| ); | ||
| document.body.style.background = '#373841'; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "allowSyntheticDefaultImports": true, | ||
| "declaration": true, | ||
| "declarationMap": true, | ||
| "lib": ["ES2017", "dom"], | ||
| "module": "ESNext", | ||
| "moduleResolution": "node", | ||
| "noImplicitOverride": true, | ||
| "resolveJsonModule": true, | ||
| "rootDir": ".", | ||
| "outDir": "dist", | ||
| "skipLibCheck": true, | ||
| "sourceMap": true, | ||
| "inlineSources": true, | ||
| "strict": true, | ||
| "stripInternal": true, | ||
| "target": "ES2017", | ||
| "allowJs": true | ||
| }, | ||
| "include": ["src"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| /* eslint-disable import/no-extraneous-dependencies */ | ||
| import { defineConfig } from 'tsdown'; | ||
|
|
||
| export default defineConfig({ | ||
| entry: 'src/app.ts', | ||
| platform: 'browser', | ||
| outDir: 'dist', | ||
| noExternal: ['@launchdarkly/js-client-sdk'], | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we could set this up to work with a .env, or regular environment variable, then that would be good.
Generally speaking this approach results in accidental commits of tokens. Client-side IDs are not secret, so it isn't a big issue, but still nice to not have to worry about it.
If you do use a .env, then you can make sure it is in the git ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(We can do the same thing with the flagKey, for convenience.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea for this kind of example, I think we can inject those values during build time... I'll refactor this example, once we get the waitForInit PR in.