optimizely / javascript-sdk

JavaScript SDK for Optimizely Feature Experimentation and Optimizely Full Stack (legacy)
https://www.optimizely.com/products/experiment/feature-experimentation/
Apache License 2.0
80 stars 82 forks source link

Cloudflare Worker runtime use issues #348

Closed defjosiah closed 4 years ago

defjosiah commented 5 years ago

What I wanted to do

I would like to use the optimizely-sdk in a cloudflare worker (have been emailing/talking to @asaschachar about this use-case). Specifically, need the ability to:

  1. Use either features flags (rollouts) or assign experiment variations
  2. Track conversions events from the worker
  3. Update the datafile using a webhook
  4. Use a datafile from cloudflare k/v storage (updated via the webhook in point 3)

What I expected to happen

Add imports to @optimizely/optimizely-sdk, bundle with webpack, able to use the sdk in cloudflare workers.

What actually happened

The sdk failed when using the node version, because it couldn't find the Buffer object. The sdk failed when using the browser version, because it couldn't find "localStorage".

Steps to reproduce

  1. Approach 1: Attempted to use the "node" version of the library "lib/index.node.js". Ran into incompatibilities with the "Buffer" node builtin.

optimizely-sdk: v3.2.0 webpack.config.js

const path = require('path');
module.exports = {
  target: 'webworker',
  optimization: {
    minimize: false,
  },
  resolve: {
    // Resolve module first, before main and browser,
    // so import from optimizely doesn't bring in the browser version
    mainFields: ['module', 'main', 'browser'],
  },
  output: {
    filename: 'worker.js',
    path: path.resolve(__dirname, 'build/'),
  },
};
worker.js:1366 Uncaught TypeError: Cannot read property 'TYPED_ARRAY_SUPPORT' of undefined
    at Object.<anonymous> (VM5 worker.js:1366)
    at Object.<anonymous> (VM5 worker.js:3114)
    at __webpack_require__ (VM5 worker.js:114)
    at Object.<anonymous> (VM5 worker.js:13317)
    at __webpack_require__ (VM5 worker.js:114)
    at Object.<anonymous> (VM5 worker.js:3872)
    at Object.<anonymous> (VM5 worker.js:3957)
    at __webpack_require__ (VM5 worker.js:114)
    at Object.<anonymous> (VM5 worker.js:12931)
    at __webpack_require__ (VM5 worker.js:114)

Attempted various alias'es for the Buffer module, and a polyfill (npm install buffer), but it unfortunately doesn't work.

  1. Approach 2: attempted to use the browser version of the optimizely library optimizely-sdk: v3.2.0

webpack.config.js

const path = require('path');
module.exports = {
  target: 'webworker',
  optimization: {
    minimize: false,
  },
  output: {
    filename: 'worker.js',
    path: path.resolve(__dirname, 'build/'),
  },
};
  ReferenceError: localStorage is not defined
          at LocalStorageStore.getMap (evalmachine.<anonymous>:10702:24)
          at LocalStorageStore.values (evalmachine.<anonymous>:10669:49)
          at LocalStoragePendingEventsDispatcher.PendingEventsDispatcher.sendPendingEvents (evalmachine.<anonymous>:10586:40)
          at Object.createInstance (evalmachine.<anonymous>:5353:32)
          at Object.<anonymous> (evalmachine.<anonymous>:5229:27)
          at Generator.next (<anonymous>)
          at fulfilled (evalmachine.<anonymous>:5169:58)
          at process._tickCallback (internal/process/next_tick.js:68:7)

This version technically "works", as in, it'll assign a feature (haven't checked if the activate calls are going through to our custom dispatcher, I'd guess that they aren't going through, because this happens in sendPendingEvents).

  1. Approach 3: Current optimizely-sdk master The unconditional wrapping of a custom dispatcher in the localStorage wrapper was removed in (https://github.com/optimizely/javascript-sdk/pull/289). I manually linked to this build of the library, and the localStorage errors were no longer present.

@optimizely/optimizely-sdk version:3.2.0

Browser and version: Cloudflare Workers Environment

node version: 10.15.3

webpack version: 4.29.6

mjc1283 commented 5 years ago

Hi defjosiah,

Thanks for filing this issue. We’ve released version 3.2.2 containing the fix you referenced (from https://github.com/optimizely/javascript-sdk/pull/289). This should make the browser entry point usable as long as you pass in a custom event dispatcher. Hope this helps - please let us know.

defjosiah commented 5 years ago

Just upgraded to v3.2.2, and deployed successfully, thanks for the quick turnaround!