Skip to content

[OPTIMIZELY] - ERROR crypto$1.randomBytes is not a function #792

@smalljimmy

Description

@smalljimmy

Hi

I am using Optimizely Fullstack (browser javascript) through rollup. I notice following error when the experiment is activated in the browser:

[OPTIMIZELY] - ERROR 2022-10-25T01:59:23.886Z crypto$1.randomBytes is not a function :

image

In the console, I can see the uuid node version was used (not the rng-browser.js)

image

I tried different settings but leads to no success

If I bundle the project with vite, it works and the rng is using the browser version:

image

Any idea why rollup not pick the browser version?

Package.json:

{
"private": true,
"name": "template",
"version": "1.0.0",
"jest": {
"verbose": true,
"coverageDirectory": "./coverage",
"coverageThreshold": {
"global": {
"branches": 30,
"functions": 30,
"lines": 30,
"statements": 30
}
}
},
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.19.4",
"@babel/preset-typescript": "^7.17.12",
"@rollup/plugin-alias": "^4.0.0",
"@rollup/plugin-beep": "^1.0.0",
"@rollup/plugin-commonjs": "^23.0.0",
"@rollup/plugin-html": "^1.0.0",
"@rollup/plugin-json": "^5.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@rollup/plugin-replace": "^5.0.0",
"@rollup/plugin-typescript": "^9.0.1",
"@segment/analytics-next": "^1.44.0",
"@sveltejs/vite-plugin-svelte": "^1.0.9",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/svelte": "^3.2.2",
"@testing-library/user-event": "^14.4.3",
"@tsconfig/recommended": "^1.0.1",
"@tsconfig/svelte": "^3.0.0",
"@types/chart.js": "^2.9.37",
"@types/dinero.js": "^1.6.2",
"@types/grecaptcha": "^3.0.4",
"@types/inputmask": "^5.0.3",
"@types/js-cookie": "^3.0.2",
"@types/lodash": "^4.14.186",
"@types/node": "^18.8.3",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-helmet": "^6.1.5",
"@types/testing-library__jest-dom": "^5.14.5",
"@types/uuid": "^8.3.4",
"@types/validator": "^13.7.4",
"@types/vimeo__player": "^2.16.3",
"@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6",
"@vitejs/plugin-react": "^2.1.0",
"@vitest/coverage-c8": "^0.24.3",
"@xstate/test": "^0.5.0",
"autoprefixer": "^10.4.12",
"c8": "^7.12.0",
"carbon-components-svelte": "^0.60.0",
"cssnano": "^5.1.13",
"dotenv": "^16.0.3",
"eslint": "^8.19.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-svelte3": "^3.4.1",
"faker": "^4.1.0",
"htmlnano": "^2.0.0",
"jsdom": "^20.0.1",
"less": "^4.1.3",
"msw": "^0.47.4",
"npm-run-all": "^4.1.5",
"openapi-types": "^12.0.2",
"postcss": "^8.4.18",
"postcss-easings": "^3.0.1",
"postcss-import": "^15.0.0",
"postcss-preset-env": "^7.8.2",
"posthtml": "^0.16.6",
"posthtml-hash": "^1.2.2",
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.7.0",
"resize-observer-polyfill": "^1.5.1",
"rimraf": "^3.0.2",
"rollup": "^3.2.3",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-svelte": "^7.1.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-visualizer": "^5.8.3",
"sass": "^1.55.0",
"svelte": "^3.52.0",
"svelte-check": "^2.9.2",
"svelte-preprocess": "^4.10.7",
"tailwindcss": "^3.1.8",
"terser": "^5.15.1",
"tslib": "^2.4.0",
"typed-css-modules": "^0.7.2",
"typed-scss-modules": "^7.0.1",
"typescript": "^4.8.4",
"vite": "^3.1.8",
"vitest": "^0.24.3"
},
"dependencies": {
"@datadog/browser-logs": "^4.21.2",
"@datadog/browser-rum": "^4.21.2",
"@floating-ui/dom": "^1.0.2",
"@floating-ui/react-dom": "^1.0.0",
"@floating-ui/react-dom-interactions": "^0.10.1",
"@fortawesome/fontawesome-pro": "^6.2.0",
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-brands-svg-icons": "^6.2.0",
"@fortawesome/pro-light-svg-icons": "^6.2.0",
"@fortawesome/pro-regular-svg-icons": "^6.2.0",
"@fortawesome/pro-solid-svg-icons": "^6.2.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@fortawesome/sharp-solid-svg-icons": "^6.2.0",
"@optimizely/js-sdk-utils": "^0.4.0",
"@optimizely/optimizely-sdk": "^4.9.2",
"@storybook/testing-library": "^0.0.13",
"@testing-library/dom": "^8.19.0",
"@vimeo/player": "^2.18.0",
"@xstate/cli": "^0.1.7",
"@xstate/immer": "^0.3.0",
"@xstate/react": "^3.0.1",
"@xstate/svelte": "^1.0.0",
"ahooks": "^3.7.2",
"antd": "^4.23.6",
"antd-mobile": "^5.24.1",
"babel": "^6.23.0",
"chart.js": "^3.5.1",
"chartjs-adapter-date-fns": "^2.0.0",
"concurrently": "^6.4.0",
"core-js": "^3.25.5",
"cross-fetch": "^3.1.5",
"crypto-browserify": "^3.12.0",
"date-fns": "^2.23.0",
"dayjs": "^1.11.5",
"driver.js": "^0.9.8",
"ethos-design-system": "github:getethos/ethos-design-system#v1.2.34",
"flatpickr": "^4.6.9",
"imask": "^6.4.3",
"immer": "^9.0.7",
"inputmask": "^5.0.7",
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"object-assign": "^4.1.1",
"path-to-regexp": "^6.2.0",
"randombytes": "^2.1.0",
"rc-tabs": "^11.16.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-imask": "^6.4.3",
"react-router-dom": "^6.4.2",
"rollup-plugin-browserify-transform": "^1.0.1",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"sirv-cli": "^2.0.2",
"tippy.js": "^6.3.7",
"uuid": "^9.0.0",
"validator": "^13.7.0",
"vest": "^4.5.0",
"whatwg-fetch": "^3.6.2",
"xlsx": "^0.18.5",
"xstate": "^4.33.6"
},
"scripts": {
"build": "rimraf build && rollup -c rollup.config.csr.mjs",
"build:pr": "NODE_ENV=production PARTNER_API_BASE_URL='https://api' CORE_FE_ROOT='https://core-fe' CMS_FE_ROOT='https://cms-fe' API_GATE_WAY_URL='https://api-gateway' run-p build",
"build:production": "NODE_ENV=production run-p build",
"build:css": "tailwindcss -i src/css/tailwind.css -o public/tailwind.css --minify",
"postbuild": "cp -r public build && node postbuild.js",
"autobuild": "rollup -c rollup.config.csr.mjs -w",
"dev:css": "tailwindcss -i src/css/tailwind.css -o public/tailwind.css --watch",
"dev:p": "rimraf public && concurrently "yarn dev:css" "yarn autobuild"",
"dev": "rimraf public && run-p autobuild",
"start": "sirv build --single",
"start:dev": "sirv public --dev --single",
"dev:v": "vite",
"build:v": "vite build",
"preview:v": "vite preview",
"test": "vitest",
"test:watch": "vitest watch",
"coverage": "vitest --coverage",
"lint": "npx eslint "{,!(node_modules|public)//}*.{js,svelte}"",
"fix": "npx eslint --fix "{,!(node_modules|public)/
/}.{js,svelte}"",
"validate": "svelte-check",
"xstate:typegen": "xstate typegen "src/**/
.ts?(x)"",
"xstate:typegen:dev": "xstate typegen "src//*.ts?(x)" --watch",
"typecss": "tcm -p 'src/
/.module.css' && yarn typed-scss-modules src/**/.module.scss --nameFormat all --exportType default"
},
"browserslist": [
"defaults"
],
"browser": [
"uuid"
]
}`

Rollup config:

import alias from '@rollup/plugin-alias'
import beep from '@rollup/plugin-beep'
import commonjs from '@rollup/plugin-commonjs'
import html, { makeHtmlAttributes } from '@rollup/plugin-html'
import json from '@rollup/plugin-json'
import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import typescript from '@rollup/plugin-typescript'
import * as fs from 'fs'
import template from 'lodash/template.js'
import copy from 'rollup-plugin-copy'
import livereload from 'rollup-plugin-livereload'
import postcss from 'rollup-plugin-postcss'
import svelte from 'rollup-plugin-svelte'
import { terser } from 'rollup-plugin-terser'
import { visualizer } from 'rollup-plugin-visualizer'
import { serve } from './serve.mjs'

import aliasOptions from './rollup.alias.config.js'
import replaceOptions from './rollup.replace.config.js'
import svelteConfig from './svelte.config.js'
import lessOptions from './less.options.js'
import globals from 'rollup-plugin-node-globals';
import builtins from 'rollup-plugin-node-builtins';

console.log('--- rollup.config.csr ---')
console.log('mode', mode)
const production = ['stage', 'production'].includes(mode)

const config = [
{
input: 'src/index.ts',
output: {
// Inline source maps are handy during development due to their speed
sourcemap: production ? true : 'inline',
format: 'es',
name: 'app',
dir: 'public',
// turns index.js -> index..js
entryFileNames: '[name].[hash].js',
manualChunks: {
react: ['react', 'react-dom'],
},
},
preserveEntrySignatures: false,
plugins: [
alias(aliasOptions),

  svelte(svelteConfig),

  postcss({
    extract: true,
    minimize: true,
    inject: false,
    use: {
      less: lessOptions,
    },
    extensions: ['.sass', '.scss', '.less', '.css'],
  }),

  replace(replaceOptions),

  resolve({
    browser: true,
    resolveOnly: module => !module.includes('@optimizely/optimizely-sdk/node_moduels/uuid'),
  }),
  commonjs(),
  builtins({crypto: true}),
  globals(),
  typescript({
    tsconfig: './tsconfig.json',
    compilerOptions: {
      sourceMap: production,
    },
  }),


  !production && serve(),

  !production && livereload('public'),

  production && terser(),

  copy({
    targets: [{ src: 'static/**/*', dest: 'public/' }],
    // required to prevent unnecessary copying from reloads during watch mode
    copyOnce: !production,
    // we don't want the plugin to remove directory structure by default
    flatten: false,
  }),

  copy({
    targets: [{ src: 'src/iframe.html', dest: 'public/' }],
    // required to prevent unnecessary copying from reloads during watch mode
    copyOnce: !production,
    // we don't want the plugin to remove directory structure by default
    flatten: false,
  }),

  html({
    publicPath: '/',
    template: ({ attributes, files, publicPath, title }) => {
      let templateFile = fs.readFileSync('src/index.html')

      // This is adapted from the default template function in the HTML plugin.
      const scripts = (files.js || [])
        .map(({ fileName }) => {
          const attrs = makeHtmlAttributes({
            ...attributes.script,
            nonce: production ? '**CSP_NONCE**' : 'rAnd0m123',
          })
          return `<script src="${publicPath}${fileName}"${attrs}></script>`
        })
        .join('\n')

      const stylesheets = (files.css || [])
        .map(({ fileName }) => {
          const attrs = makeHtmlAttributes(attributes.link)
          return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`
        })
        .join('\n')

      const exec = template(templateFile.toString())
      return exec({
        mode,
        attributes,
        title,
        scripts,
        stylesheets,
        BOND_SEGMENT_CLIENT_KEY:
          mode === 'production' ? 'fdhg3J5PV7ClE4kPjVHcg1k3FYSIMOoo' : 'IrQ8o3vZnygSSTaO5RkwwU3F3m3IqDcj',
        CSP_NONCE: production ? '**CSP_NONCE**' : 'rAnd0m123',
        htmlAttributes: makeHtmlAttributes(attributes.html),
      })
    },
  }),

  beep(),
  json({
    compact: true,
  }),

  !production && visualizer(),
],
watch: {
  clearScreen: true,
  include: 'src/**',
},

}
]

export default config

tsconfig.json:

{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["node_moduels//*", "src//.d.ts", "src/**/.ts", "src//*.js", "src//.svelte", "src/**/.jsx", "src//.tsx"],
"exclude": ["sapper/
", "public/*", "src/serviceWorker.ts", "
/tests/**/.tsx"],
"compilerOptions": {
"jsx": "react",
"target": "ESNext",
"module": "ESNext",
"resolveJsonModule": true,
"types": ["svelte", "node", "grecaptcha", "vitest/globals"],
"typeRoots": ["node_modules/@types", "src/types"],
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"baseUrl": ".",
"noEmitOnError": true,
"paths": {
"actions/
": ["src/actions/"],
"components/
": ["src/components/"],
"constants/
": ["src/constants/"],
"contexts/
": ["src/contexts/"],
"css/
": ["src/css/"],
"generated/
": ["src/generated/"],
"icons/
": ["src/icons/"],
"machines/
": ["src/machines/"],
"pages/
": ["src/pages/"],
"services/
": ["src/services/"],
"stores/
": ["src/stores/"],
"transitions/
": ["src/transitions/"],
"utils/
": ["src/utils/"],
"framework/
": ["src/framework/"],
"ui/
": ["src/ui/*"],
"randombytes": ["node_modules/randombytes"],
"crypto": [
"node_modules/crypto-browserify"
],
}
}
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions