caught ReferenceError: global is not defined
Closed this issue · 5 comments
Great library!
For some reason, today ng-qrcode failed with a big fat error.
Uncaught ReferenceError: global is not defined
at Object.../../node_modules/node-libs-browser/node_modules/buffer/index.js (index.js:43)
at __webpack_require__ (bootstrap:79)
at Object.../../node_modules/qrcode/lib/core/reed-solomon-encoder.js (reed-solomon-encoder.js:3)
at __webpack_require__ (bootstrap:79)
at Object.../../node_modules/qrcode/lib/core/qrcode.js (qrcode.js:10)
at __webpack_require__ (bootstrap:79)
at Object.../../node_modules/qrcode/lib/browser.js (browser.js:4)
at __webpack_require__ (bootstrap:79)
at Module.../../node_modules/ng-qrcode/fesm2015/ng-qrcode.js (ng-qrcode.js:1)
I did some Googling and found:
global is not available as of Angular 6.
Library authors should not depend on this property. See this post: angular/angular-cli#9827 (comment)
As a workaround for now, I am putting this is my polyfills.ts
(window as any).global = window;
Thanks for the report. I've generally found myself making a similar polyfill in most angular projects for one reason or another, but agree with the reasoning behind the comment you linked.
Based on the stack trace it's coming from a deeply nested dependency, so there may not be a lot I can do, but I'll investigate and at the least add a note to the readme if it's not practical to patch the underlying dependency.
I wouldn't feel comfortable adding such a polyfill to the library itself, as that feels a bit presumptuous to do in a library
Thanks @mnahkies. I saw that too. Just thought I'd reach out in any case.
I've had a more detailed investigation into this, and it's actually quite a tricky situation.
The issue
Looking at the https://github.com/feross/buffer repository, you'll notice that the bug is present in the 4.x branch, but not master - it's fixed on buffer@5.x
.
I made a new project, and then did:
$ npm ls buffer
top level project
├─┬ @angular-devkit/build-angular@0.900.0-rc.5
│ └─┬ webpack@4.41.2
│ └─┬ node-libs-browser@2.2.1
│ └── buffer@4.9.2
└─┬ ng-qrcode@3.0.1
└─┬ qrcode@1.4.4
└── buffer@5.4.3
So you can see, that the qrcode
module actually directly depends on the correct dependency, but unfortunately a different version gets brought in by webpack
through node-libs-browser
. Upgrading node-libs-browser
isn't an option as it is deprecated and no longer used in webpack@5
For whatever reason webpack chooses to bundle up the old v4 version instead of the v5 version that our dependency actually wants.
Ideally the angular team would update angular to use webpack@5
which would remove the node-libs-browser
dependency and solve our immediate issue.
However this seems a bit of a band aid solution, as the current way that the angular/webpack bundling is working seems to completely preclude the ability to have two libraries in the dependency tree that depend on incompatible library versions co-exist correctly.
I don't know enough about webpack configuration to know if this is a problem that can be solved through tweaks there, but bottom line is that angular 9 still depends on webpack 4 and so this specific problem won't be going away by itself in a hurry.
Possibly related webpack issue: webpack/webpack#9739
Workarounds
I can see two different workarounds, each with pro's/con's. I'll go ahead and document these on the readme and then close this issue.
Define global
in index.html
Edit your applications index html to have a script section in the <head>
like this:
<script>window.global = window</script>
This is something that I personally end up doing with most angular projects, but your mileage may vary.
Note: as @bjornharvold originally noted you could also put this in polyfills.ts as
(window as any).global = window;
However I'd be slightly wary as I'm unsure if polyfills.ts gets executed when rendering using SSR / Angular Universal on NodeJS for example, and I don't have a project to hand that I can test this with unfortunately.
caveat this means that qrcode will still be obtaining an outdated version of buffer compared to what it is expecting. I haven't seen this cause any issues so far though.
Force node-libs-browser
to use buffer@^5.4.3
Methods:
- with npm https://github.com/rogeriochaves/npm-force-resolutions
- with yarn https://yarnpkg.com/lang/en/docs/selective-version-resolutions/
- manually edit the appropriate lockfile's (only really useful for testing)
From what I can tell this also fixes the problem, and is technically more correct as it means that the version of buffer
expected by qrcode
will be provided.
Closing as per above comment.
Note that with some further observation I've found that it doesn't affect every project, seems to be a bit of luck involved as to how the node modules directory structure ends up looking - deleting package-lock.json
/ node_modules
and then running npm install
may resolve for some projects.
Note that webpack@5 is still in beta (as of 2020 02 20)