bwip-js
bwip-js copied to clipboard
Add React Native support
There is no atob function in React Native, so I added polyfill. Work correct with Expo. Should work without
I thought react native used nodejs as its execution environment. Is the react bundler bringing in the browser version of bwip-js? I.e. is your code using the toCanvas() method?
I thought react native used nodejs as its execution environment. Is the react bundler bringing in the browser version of bwip-js? I.e. is your code using the
toCanvas()method?
There is no browser canvas in RN. Therefore, we cannot use the toCanvas() method
Something does not make sense. atob() is only used in the browser modules. The nodejs modules use Buffer methods to decode base64:
$ cd dist
$ grep atob *
bwip-js.js: var bstr = binary ? data : atob(data),
bwip-js.mjs: var bstr = binary ? data : atob(data),
bwip-js-min.js: var bstr = binary ? data : atob(data),
It appears the bundler is pulling in the browser module. Please comment out your atob() implementation and provide a stack trace of the reference error.
ReferenceError: Can't find variable: atob
at node_modules\react-native\Libraries\LogBox\LogBox.js:148:8 in registerError
at node_modules\react-native\Libraries\LogBox\LogBox.js:59:8 in errorImpl
at node_modules\react-native\Libraries\LogBox\LogBox.js:33:4 in console.error
at node_modules\expo\build\environment\react-native-logs.fx.js:27:4 in error
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:104:6 in reportException
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:171:19 in handleException
at node_modules\react-native\Libraries\Core\setUpErrorHandling.js:24:6 in handleError
at node_modules\expo-error-recovery\build\ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:294:29 in invoke
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:155:27 in invoke
at node_modules\regenerator-runtime\runtime.js:165:18 in PromiseImpl.resolve.then$argument_0
at node_modules\react-native\node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
at node_modules\react-native\node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:130:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:181:14 in _callImmediatesPass
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:441:30 in callImmediates
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:387:6 in __callImmediates
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:135:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:4 in flushedQueue

The bundler is pulling in the browser module. After doing some research, it appears there is a poorly documented setting that can be added to a module's package.json to override the bundler's default selection:
"react-native": "./dist/bwip-js-node.js",
Please add that config directive to the bwip-js package.json file and rebuild your project:

Now we get another problem. Project not start.
Unable to resolve module zlib from C:\Work\MobileApp\src\lib\bwip-js\dist\bwip-js-node.js: zlib could not be found within the project.
If you are sure the module exists, try these steps:
1. Clear watchman watches: watchman watch-del-all
2. Delete node_modules and run yarn install
3. Reset Metro's cache: yarn start --reset-cache
4. Remove the cache: rm -rf /tmp/metro-*
72 | // bwipjs.toBuffer(options[, callback])
73 | //
> 74 | // Uses the built-in graphics drawing and zlib PNG encoding to return a
| ^
75 | // barcode image in a node.js Buffer.
76 | //
77 | // `options` are a bwip-js/BWIPP options object.
React Native not use node js, so I think, we can't get access to zlib
Looks like you will need to bring in a pure javascript zlib implementation. This looks like a good possibility:
https://www.npmjs.com/package/react-zlib-js
So, I update PR. Now it pull nodejs module
A problem with your proposed changes is that is uses react-zlib-js to replace the native nodejs functionality. That will be a performance hit during the png encoding when running on node, The pako implementation is fast, but not as fast as native zlib.
A better alternative would be to create a react-native-specific npm package that bundles together the nodejs bwip-js module(s) and react-zlib-js. If you are willing to test it, I will create a new repo and npm package dedicated to react-native (and possibly react-on-the-browser since it should run there as well).
Why react, node js, electron and other here, and react native in other package? I think create new package is not good idea. Because we only need svg string, to display barcodes in react native. And the easiest way to get it is override atob() function. So, we can get this function for example by my first commit, or just add dependency from https://www.npmjs.com/package/base-64 (To be honest - I just copied the function from there)
Version 3.2.0 has experimental support for react-native. Please try it out and let me know of any issues. You must install react-zlib-js as an external dependency. See https://github.com/metafloor/bwip-js#react-native.
Closing this since it appears to be working...