Conversation
kidroca
left a comment
There was a problem hiding this comment.
Some notes on the code
| }, | ||
| "dependencies": { | ||
| "ascii-table": "0.0.9", | ||
| "expensify-common": "git+https://github.com/Expensify/expensify-common.git#2e5cff552cf132da90a3fb9756e6b4fb6ae7b40c", |
There was a problem hiding this comment.
Specifying expensify-common under peer dependencies ensures both Expnesify/App and Expnsify/react-native-onyx use the same expensify-common version (the one from App)
| "expensify-common": ">=1", | ||
| "localforage": "^1.10.0", | ||
| "react": "^17.0.2", | ||
| "react": ">=17.0.2", |
There was a problem hiding this comment.
>= so React 18 is accepted as well
| "@react-native-async-storage/async-storage": { | ||
| "optional": true | ||
| }, | ||
| "localforage": { | ||
| "optional": true |
There was a problem hiding this comment.
async-storage and localforage are optional to let consumers use one or the other
| ] | ||
| } | ||
| }, | ||
| "sideEffects": false |
There was a problem hiding this comment.
This lets Webpack bundlers know that our code is not doing anything funky like change the Prototype or adding stuff to window and aids tree shaking
webpack.common.js
Outdated
| /^expensify-common\/.+$/, | ||
| /^lodash\/.+$/, |
There was a problem hiding this comment.
Regex syntax is intentional since we import subpaths of these modules
lodash/mergeexpensify-common/str/...
If we don't use a pattern the whole package is bundled even if it's a peer dependency: https://webpack.js.org/guides/author-libraries/#external-limitations
There was a problem hiding this comment.
Cool, I was reading some about this and wanted to look into it further. Thanks for adding it.
webpack.common.js
Outdated
| ..._.keys(pkg.peerDependencies), | ||
| ..._.keys(pkg.dependencies), |
There was a problem hiding this comment.
Our package dependencies are installed automatically into the consumer project node_modules
peerDependencies would be installed as well, or flagged as not met depending on the npm version
These are relatively easy to resolve if not installed, because we'll get an error that a module cannot be found
|
cc @tgolen |
tgolen
left a comment
There was a problem hiding this comment.
Found out we need the main field
This peer dependency is needed locally when we run tests
After webpack changes some unit tests broke due to mock resolution Because we're using the `react-native` preset of jest this file extension is .native.js. Otherwise, since jest prefers index.native.js over index.js it'll skip loading the mock
These presets are already covered by `metro-react-native-babel-preset` We should either use the metro preset or compose react/env/flow ourselves but not both
327e387 to
79881fd
Compare
We don't have to lint bundled code in dist Since now we have .web and .native indexes we need to tell eslint that it's valid to import `./storage` even thought there's no `index.js`, because there's `index.native.js` and `index.web.js`
This should aide debugging and inspecting the package `module: index.js` might be able to help to import Onyx and performing changes in `node_modules` without having to re-build Onyx
The typings aid code completion in IDEs (and also allow Onyx to be used in Typescript project)
These help with stack traces and debugging Onyx sources through parent projects Now that the code is minified we need these to trace calls like `Onyx.merge` from App
| presets: [ | ||
| require('metro-react-native-babel-preset'), | ||
| ], | ||
| plugins: [ | ||
| '@babel/plugin-proposal-class-properties', | ||
| ], |
There was a problem hiding this comment.
@tgolen I've found out the presets (react/env/flow) are all covered by metro-react-native-babel-preset, maybe we don't need any changes here, but I left the plugin
There was a problem hiding this comment.
Ah, OK. Good to know. The plugin is required, yeah. Thanks!
| module.exports = [ | ||
| webConfig, | ||
| webDevConfig, | ||
| nativeConfig, | ||
| nativeDevConfig, | ||
| ]; |
There was a problem hiding this comment.
Exporting an array of configs let's webpack build them in parallel
|
I've found a way to generate Not entirely sure why I don't have code completion - even when I change the import to
I'm not certain if the
One thing that we might do is "exports": {
".": {
"development": "./index.js",
"types": "./dist/types/index.d.ts",
"default": "./dist/native.min.js"
}which should load from raw source, but only when we import Can you review the new code and tell me what you think
|
tgolen
left a comment
There was a problem hiding this comment.
The changes look good to me. I didn't know that about webpack being able to build the configs in parallel. Neat!
I think the last thing is just adding a few comments and instructions so that it's clear what everything is for, and then this should be good to merge.
package.json
Outdated
| "main": "./dist/native.min.js", | ||
| "module": "./index.js", | ||
| "exports": { | ||
| "./web": { |
There was a problem hiding this comment.
Could you add a small section in the README about how to import this lib in a web-only application and maybe a quick description/example of using the development bundle (and why someone would want to use it)?
| }, | ||
| }); | ||
|
|
||
| const webDevConfig = merge(webConfig, { |
There was a problem hiding this comment.
Could you add a quick comment here explaining why there is a dev config (same for the native dev config)?
Onyx can be import as `react-native-onyx` in both native and web projects thanks to `react-native` and `browser` fields in `package.json` The `main` filed serves to provider pure source which satisfies code completion in IDEs, this renders .d.ts files unnecessary
|
Hey @tgolen, while writing the documentation I was testing stuff and found out how to get rid of the Another change is we no longer have to import
Using the Sorry for the new changes, but I think this makes the setup simpler and closer to what we previously had for |
tgolen
left a comment
There was a problem hiding this comment.
Awesome, I like that better. Cleans it up some!
README.md
Outdated
| Bundlers like Webpack respect that field and import code from the path resolved there | ||
|
|
||
| ```javascript | ||
| import Onyx, { withOnyx } from 'react-native-onyx/web'; |
There was a problem hiding this comment.
| import Onyx, { withOnyx } from 'react-native-onyx/web'; | |
| import Onyx, { withOnyx } from 'react-native-onyx'; |
Co-authored-by: Tim Golen <tgolen@gmail.com>
|
I agree with you that the only real reason it's helpful is for messing with
Onyx code directly (strictly a time-saver). I don't think we need to spend
too much time trying to provide that functionality, but I'm curious about
the development.js idea and see how that works.
…On Wed, May 18, 2022 at 10:01 AM Peter Velkov ***@***.***> wrote:
Removed .d.ts.map files
Will experiment with the .development.js idea and post back
—
Reply to this email directly, view it on GitHub
<#132 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAJMABZX7WF2IQWFJRJ5Z7DVKUH4PANCNFSM5WCHB3FA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Right now for web we directly return the minified code from One thing to note is that we still load bundled code, so live changes to source code would still not be reflected - to make changes to Onyx live you'd have to modify the non-minified code from If we want to save time on testing new thing in Onyx, perhaps we can make a script in App that
|
|
So strange. I wrote that reply months ago and it only now posted to GH. I do still think it's a problem worth fixing to make development on Onyx source code easier. We've been making a lot of performance changes, so it's been in active development lately. I like your second idea since that would allow us to edit the source code directly. Could we try that? |
|
I think maybe we should open a new GH issue for that |
Yep, we have almost everything in place, we just need to:
|
|
@kidroca @tgolen @parasharrajat just FYI, it looks like this PR likely caused this bug: Expensify/App#10622 |
|
Do you mean this PR specifically, or is there another? There are multiple attached to that issue. |
|
@puneetlath
The Android issue was because of the introduction of the Initially I guess we should have added documentation about only working with async function to
|
|
Ok good learnings! Anything we should do now? |
|
We can update method documentation and comments to mention that only Promise returning methods can be decorated We can update Onyx metrics to work on Web - we only disabled them so that Onyx can be used in other non react-native projects, because it caused issues with bundling - instead of applying a working around - disabling metrics for web (via a no-op web file), we can fix bundling |


Details
Bundle Onyx with Webpack to allow using Onyx outside of react-native
Using a test project with the follow package.json config
package.json
{ "name": "test-onyx", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.2.0", "@testing-library/user-event": "^13.5.0", "expensify-common": "git+https://github.com/Expensify/expensify-common.git#2e5cff552cf132da90a3fb9756e6b4fb6ae7b40c", "localforage": "^1.10.0", "react": "^18.1.0", "react-dom": "^18.1.0", "react-native-onyx": "git+https://github.com/kidroca/react-native-onyx.git#11dc5443e4d6e7cac3a967344996466bb26966c8", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] } }We can import and use
Onyxin a non react-native project, like we do in App:Using the following package.json fields we tell bundlers to load different Onyx configurations per environment
browser-> Onyx is loaded for non react-native projects and uses localforage to manage IndexedDbreact-native-> Same as what we used to have, Onyx is loaded and uses the native storagemain-> Right now this field only aids IDEs with code completion from the unmodified sourceRelated Issues
Slack thread: https://expensify.slack.com/archives/C01GTK53T8Q/p1652389473489429
Automated Tests
No new functionality added
Existing tests are still pass
Linked PRs