skygear-SDK-JS icon indicating copy to clipboard operation
skygear-SDK-JS copied to clipboard

"Uncaught TypeError: Cannot read property 'WebSocket' of undefined" with webpack

Open cheungpat opened this issue 7 years ago • 2 comments

This error is thrown in browser in a webpack project.

browser.js:2 Uncaught TypeError: Cannot read property 'WebSocket' of undefined
    at Object.<anonymous> (browser.js:2)
    at __webpack_require__ (bootstrap 9d9eeff259ebc6257fd0:676)
    at fn (bootstrap 9d9eeff259ebc6257fd0:87)
    at Object.<anonymous> (pubsub.js:30)
    at __webpack_require__ (bootstrap 9d9eeff259ebc6257fd0:676)
    at fn (bootstrap 9d9eeff259ebc6257fd0:87)
    at Object.defineProperty.value (container.js:54)
    at __webpack_require__ (bootstrap 9d9eeff259ebc6257fd0:676)
    at fn (bootstrap 9d9eeff259ebc6257fd0:87)
    at Object._typeof (index.js:7)

The package.json looks like this

{
  "dependencies": {
    "babel-core": "^6.25.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-flow": "^6.23.0",
    "babel-preset-stage-2": "^6.24.1",
    "eslint": "^4.4.1",
    "eslint-import-resolver-webpack": "^0.8.3",
    "eslint-plugin-flowtype": "^2.35.0",
    "express": "^4.15.4",
    "less": "^2.7.2",
    "less-loader": "^4.0.5",
    "lodash": "^4.17.4",
    "skygear": "^1.1.0",
    "style-loader": "^0.18.2"
  },
  "devDependencies": {
    "babel-loader": "^7.1.1",
    "css-loader": "^0.28.4",
    "extract-text-webpack-plugin": "^3.0.0",
    "webpack": "^3.5.4",
    "webpack-dev-middleware": "^1.12.0",
    "webpack-hot-middleware": "^2.18.2"
  }
}

Two workaround exists (ONLY ONE OF THE FOLLOWINGS):

{
  // add the following in webpack.config.js
  externals: {
    'websocket': 'window.WebSocket'
  }
}

Alternatively,

{
  module: {
    rules: [
      {
        test: /\.js$/,
        // add this line in webpack.config.js
        exclude: [/node_modules/],
      },
    ]
  }
}

The skygear generator appears to work, but it is based on webpack 1.12.0.

There is not yet a conclusion as to how to solve this problem.

cheungpat avatar Aug 14 '17 06:08 cheungpat

also refer to https://github.com/webpack/webpack-dev-server/issues/174 where some suggest not all node_modules dependency are ready for babel https://github.com/webpack/webpack-dev-server/issues/174#issuecomment-102303060

samMeow avatar Aug 14 '17 07:08 samMeow

I think the more correct way to get window is Function('return this')() instead. The content in Function constructor is non-strict regardless of the environment it is created in.

Originally posted by @andy0130tw in https://github.com/webpack/webpack-dev-server/issues/174#issuecomment-467771912

I had this problem after an upgrade to angular 8.1 and it works perfectly after doing what he suggested. I made a small patch.js to run after npm install in my package.json

const { readFileSync, writeFileSync,existsSync } = require('fs');
const patchIdentifier = '//-patched';

const fileToPatch = './node_modules/websocket/lib/browser.js';
const codeToPatch= 'var _global = (function() { return this; })();';
const patchCode = "var _global = Function('return this')();" + patchIdentifier;

function doPatch(fileName,sourceCode) {
  if (!existsSync(fileName)) {
    console.log('file not found '+fileName)
    process.exit(0);
  }
  const contents = readFileSync(fileName).toString().split('\n');
  // Check if code has been patched already
  const hasBeenPatched = contents.find(line => line.indexOf(patchIdentifier) !== -1);
  
  if (!hasBeenPatched) {
    const lineNumber = contents.findIndex(line => line.indexOf(sourceCode) !== -1);
    if (lineNumber < 0) {
      console.error('Could not find source code. Please check ' + fileName + ' and update the patch accordingly');
      process.exit(1);
    }
    // replace the line
    contents.splice(lineNumber, 1, patchCode);
    const updatedContents = contents.join('\n');
    writeFileSync(fileName, updatedContents);

    console.log('websocket browser.js has been Monkey patched');
  } else {
    console.log('websocket browser.js has already been patched');
  }
}
doPatch(fileToPatch,codeToPatch);
process.exit(0);

NicolasKritter avatar Jul 24 '19 08:07 NicolasKritter