skygear-SDK-JS
skygear-SDK-JS copied to clipboard
"Uncaught TypeError: Cannot read property 'WebSocket' of undefined" with webpack
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.
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
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);