Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 23e9658

Browse files
committed
WIP: move react-sdk and js-web-sdk from fs-labs into this repo
1 parent 004b5b3 commit 23e9658

File tree

155 files changed

+3252
-51119
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+3252
-51119
lines changed
File renamed without changes.

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"lerna": "3.2.1",
2+
"lerna": "3.4.3",
33
"version": "independent",
44
"packages": [
55
"packages/*"

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"test-xbrowser": "lerna run test-xbrowser --stream"
1212
},
1313
"dependencies": {
14-
"lerna": "^3.2.1"
14+
"lerna": "^3.4.3",
15+
"typescript": "^3.1.6"
1516
}
1617
}

packages/js-web-sdk/.gitignore

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
node_modules/
2-
lerna-debug.log
3-
npm-debug.log
4-
packages/*/lib
5-
.idea
6-
.npmrc
1+
dist
2+
coverage
3+
.nyc_output
4+
.rpt2_cache

packages/js-web-sdk/.vscode/settings.json

Lines changed: 0 additions & 3 deletions
This file was deleted.

packages/js-web-sdk/README.md

Lines changed: 151 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,175 @@
1-
# Fullstack Labs
1+
# JS SDK Wrapper
22

3-
## Installation
3+
# What is it
44

5-
This repo uses Lerna, to install all depedencies run:
5+
- A backwards compatible wrapper around the JavascriptSDK
6+
- Provides extendible datafile loading and caching strategies
7+
- Handles async loading of userId and UserAttributes
8+
- Provides mechanisms to block rendering / execution until Optimizely is loaeded with a fallback timeout
9+
- All new features are opt-in, can be used exactly the same way as JavascriptSDK if desired
610

11+
12+
# Datafile loading / management
13+
14+
## Load datafile already on the page
15+
16+
This is the ideal case and prevents a lot of timing issues and complexity, however we realize not all customers will have the ability to this.
17+
18+
```js
19+
import { Optimizely } from '@optimizely/js-web-sdk'
20+
const optimizely = new Optimizely({
21+
datafile: window.datafile,
22+
})
23+
// all calls can happen immediately after (sync)
24+
optimizely.activate('my-exp', 'user1')
725
```
8-
lerna bootstrap
26+
27+
## Load datafile by URL
28+
29+
This is not an optimal solution as it requires us to think about timing and ensure that we only call `optimizely` functions after the datafile is loaded or ensure we handle the case where `optimizely` is not ready and we need to delay loading or display a default.
30+
31+
_Asnyc load and wait until datafile is loaded_
32+
33+
```js
34+
import { Optimizely } from '@optimizely/js-web-sdk'
35+
36+
const optimizely = new Optimizely({
37+
SDKKey: 'GaXr9RoDhRcqXJm3ruskRa',
38+
})
39+
await optimizely.onReady()
40+
// datafile is gauranteed to be loaded
41+
initApp()
942
```
1043

11-
To run an individual project
44+
The above example may not be great, perhaps you want a gaurantee that the page wont block longer than X milliseconds.
45+
46+
_Asnyc load and wait up til 100ms_
47+
48+
```js
49+
import { Optimizely } from '@optimizely/js-web-sdk'
1250

51+
const optimizely = new Optimizely({
52+
SDKKey: 'GaXr9RoDhRcqXJm3ruskRa',
53+
})
54+
// dont block for more than 100sec
55+
await optimizely.onReady({ timeout: 100 })
56+
// at this point datafile may or may not be loaded
57+
// however calls to track will be queued when the datafile is ready
58+
initApp()
59+
60+
// additionally in other places you can hook into onReady without a timeout
61+
// to gaurantee optimizely is loaded
62+
optimizely.onReady().then(() => {
63+
// optimizely is gauranteed to be loaded at this point
64+
})
1365
```
14-
cd packages/PACKAGE_NAME
66+
67+
### Second page load
68+
69+
By default loading the datafile by URL will store the contents of the datafile in `localStorage`, on second page load we are guaranteed to have synchronous access to the datafile.
70+
71+
The underlying DatafileManager will also make a background request to get an updated datafile, however that will not be registered until the next instantiation of `Optimizely` which is usually the next page load.
72+
73+
_When using optimizely async the user will only have to pay the loading cost once on first page load, subsequent page loads are always synchronous_
74+
75+
### Using React
76+
77+
```js
78+
// ./optimizely.js
79+
import optimizelySDK from '@optimizely/js-web-sdk'
80+
81+
const optimizely = optimizelySDK.createInstance({
82+
SDKKey: 'GaXr9RoDhRcqXJm3ruskRa',
83+
userId: window.userId,
84+
})
85+
86+
export { optimizely }
1587
```
1688

17-
and lookup what available commands in in the `package.json` scripts field
89+
```jsx
90+
// ./App.jsx
91+
import React, { Component } from 'react'
92+
import { optimizely } from './optimizely'
93+
import {
94+
OptimizelyProvider,
95+
OptimizelyExperiment,
96+
} from '@optimizely/react-sdk'
97+
98+
class App extends Component {
99+
render() {
100+
<OptimizelyProvider optimizely={optimizely} timeout={50}>
101+
<OptimizelyExperiment experiment="header-test">
102+
{variation =>
103+
variation === 'detailed' ? <DetailedHeader /> : <SimpleHeader />
104+
}
105+
</OptimizelyExperiment>
106+
</OptimizelyProvider>
107+
}
108+
}
109+
```
18110

19-
## Packages
111+
In the above example, setting `timeout={50}` will allow any Optimizely components to wait up to 50ms for the datafile to load.
20112

21-
### JS Web SDK Wrapper
113+
_Benefits to the React approach_
114+
In the case where the datafile is already loaded, either from being on the page already or cached in local storage this approach doesn’t have a flash or a loading spinner.
22115

23-
[JS Web SDK README](packages/js-web-sdk/)
116+
On first page load, if the datafile is slow (due to slow connection) it will render the fallback.
24117

25-
An OptimizelySDK wrapper targeted for browsers
118+
# User management
26119

27-
### React SDK
120+
## Storing userId and attributes on instance
28121

29-
[React SDK README](packages/react-sdk/)
122+
This SDK supports remembering userId and attributes by passing them to instantiation
30123

31-
A collection of components to more easily implement fullstack AB Tests, Feature Test and Feature Variables
124+
```js
125+
import { Optimizely } from '@optimizely/js-web-sdk'
126+
const optimizely = new Optimizely({
127+
datafile: window.datafile,
128+
userId: window.userId
129+
attibutes: {
130+
plan_type: 'silver'
131+
}
132+
})
133+
// no need to pass userId or attributes
134+
optimizely.activate('my-exp')
32135

33-
An OptimizelySDK wrapper targeted for browsers, maintains state of user and attributes as well as supplying a simpler API.
136+
// you can always override on a per call basis
137+
optimizely.activate('my-exp', 'otheruser', {
138+
plan_type: 'gold',
139+
})
34140

35-
### React Example (TypeScript)
141+
// However this isn't recommeneded as "track" calls also need to match this
142+
// TODO: does easy event tracking fix this?
143+
```
144+
145+
## Generating a random user Id and storing in cookie
146+
147+
The following code will generate a random userId if the user doesnt already have one saved in a cookie.
36148

37-
[React Example TypeScript README](packages/react-example-ts/)
149+
```js
150+
import {
151+
Optimizely,
152+
CookieRandomUserIdLoader,
153+
} from '@optimizely/js-web-sdk'
38154

39-
### React Example (React v15)
155+
const optimizely = new Optimizely({
156+
datafile: window.datafile,
157+
userIdLoader: new CookieRandomUserIdLoader(),
158+
attibutes: {
159+
plan_type: 'silver'
160+
}
161+
})
162+
```
163+
164+
## Not managing User IDs
40165

41-
[React Example (React v15) README](packages/react-example-15/)
166+
Of course this is totally opt in, you can continue to pass userId into all api calls, the same as the Node Javascript SDK
42167

43-
### React Example (React v16)
168+
```js
169+
import { Optimizely } from '@optimizely/js-web-sdk'
44170

45-
[React Example (React v16) README](packages/react-example-16/)
171+
const optimizely = new Optimizely({
172+
datafile: window.datafile,
173+
})
174+
optimizely.activate('exp1', 'user1')
175+
```

packages/js-web-sdk/lerna.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

packages/js-web-sdk/package.json

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,82 @@
11
{
2-
"name": "root",
3-
"private": true,
2+
"name": "@optimizely/js-web-sdk",
3+
"version": "0.1.0",
4+
"description": "Wrapper for Optimizely JavscriptSDK",
5+
"author": "Jordan Garcia <jordan@optimizely.com>",
6+
"homepage": "",
7+
"license": "ISC",
8+
"main": "dist/js-web-sdk.js",
9+
"module": "dist/js-web-sdk.mjs",
10+
"typings": "lib/src/index.d.ts",
11+
"directories": {
12+
"lib": "lib",
13+
"test": "tests"
14+
},
15+
"scripts": {
16+
"tsc": "rm -rf lib/ && tsc",
17+
"test": "karma start karma.conf.js --single-run",
18+
"test:watch": "karma start karma.conf.js",
19+
"build": "rm -rf dist/ && yarn tsc && node ./scripts/build.js",
20+
"cover": "nyc mocha test/**",
21+
"coveralls": "npm run cover -- --report lcovonly && cat ./coverage/lcov.info | coveralls",
22+
"prepublishOnly": "npm run build-browser-umd && npm test && npm run test-xbrowser"
23+
},
24+
"dependencies": {
25+
"@optimizely/optimizely-sdk": "^3.0.0-rc2"
26+
},
427
"devDependencies": {
5-
"@types/node": "^10.12.5",
6-
"lerna": "^3.4.3",
7-
"typescript": "^3.1.6"
8-
}
28+
"@types/chai": "^4.1.7",
29+
"@types/mocha": "^5.2.5",
30+
"@types/sinon": "^7.0.4",
31+
"chai": "^4.2.0",
32+
"coveralls": "^3.0.2",
33+
"istanbul": "^0.4.5",
34+
"karma": "^3.1.4",
35+
"karma-chrome-launcher": "^2.2.0",
36+
"karma-mocha": "^1.3.0",
37+
"karma-webpack": "^3.0.5",
38+
"mocha": "^5.2.0",
39+
"mocha-lcov-reporter": "^1.3.0",
40+
"nyc": "^13.1.0",
41+
"puppeteer": "^1.11.0",
42+
"rollup": "^1.1.2",
43+
"rollup-plugin-commonjs": "^9.2.0",
44+
"rollup-plugin-node-resolve": "^4.0.0",
45+
"rollup-plugin-replace": "^2.1.0",
46+
"rollup-plugin-typescript2": "^0.19.2",
47+
"rollup-plugin-uglify": "^6.0.1",
48+
"sinon": "^7.2.3",
49+
"ts-loader": "^5.3.3",
50+
"typescript": "^3.1.6",
51+
"webpack": "^4.29.0"
52+
},
53+
"nyc": {
54+
"include": [
55+
"src/**/*.ts",
56+
"src/**/*.tsx"
57+
],
58+
"extension": [
59+
".ts",
60+
".tsx"
61+
],
62+
"require": [
63+
"ts-node/register"
64+
],
65+
"reporter": [
66+
"text-summary",
67+
"html"
68+
],
69+
"sourceMap": true,
70+
"instrument": true
71+
},
72+
"publishConfig": {
73+
"access": "public"
74+
},
75+
"files": [
76+
"dist/",
77+
"lib/",
78+
"LICENSE",
79+
"CHANGELOG",
80+
"README.md"
81+
]
982
}

0 commit comments

Comments
 (0)