Skip to content

Commit

Permalink
fix(console.log): add custom chrome formatters (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
becomingbabyman committed Apr 7, 2021
1 parent 04be26b commit e74f757
Show file tree
Hide file tree
Showing 27 changed files with 2,712 additions and 1,631 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '12'
- uses: actions/setup-java@v1
with:
java-version: 1.8
- uses: DeLaGuardo/setup-clojure@3.2
with:
cli: 1.10.1.693
- run: yarn install --frozen-lockfile
- run: yarn test
- run: yarn semantic-release
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ jobs:
with:
node-version: '12'

- uses: actions/setup-java@v1
with:
java-version: 1.8

- uses: DeLaGuardo/setup-clojure@3.2
with:
cli: 1.10.1.693

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Publish Examples

on:
push:
branches: [ master ]
on: push

jobs:
publish-examples:
Expand All @@ -14,6 +12,14 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '12'

- uses: actions/setup-java@v1
with:
java-version: 1.8

- uses: DeLaGuardo/setup-clojure@3.2
with:
cli: 1.10.1.693

- name: Get yarn cache directory path
id: yarn-cache-dir-path
Expand Down Expand Up @@ -46,9 +52,25 @@ jobs:

- run: yarn shadow-cljs release dev

- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
id: extract_branch

- name: Publish to GitHub Pages 🚀
uses: JamesIves/github-pages-deploy-action@releases/v3
uses: JamesIves/github-pages-deploy-action@4.1.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages # The branch the action should deploy to.
FOLDER: public # The folder the action should deploy.
branch: gh-pages
folder: public
target-folder: branches/${{ steps.extract_branch.outputs.branch }}

- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_CHANNEL: proj-dev-homebase-react
SLACK_COLOR: ${{ job.status }} # or a specific color like 'green' or '#ff00ff'
SLACK_ICON: https://github.com/homebaseio.png?size=200
SLACK_MESSAGE: "- :github: Branch: <https://github.com/homebaseio/homebase-react/tree/${{ steps.extract_branch.outputs.branch }}|${{ steps.extract_branch.outputs.branch }}>\n- :card_file_box: devcards: https://homebaseio.github.io/homebase-react/branches/${{ steps.extract_branch.outputs.branch }}/index.html"
SLACK_TITLE: "Published ${{ steps.extract_branch.outputs.branch }} to GitHub Pages :rocket:"
SLACK_USERNAME: Homebase
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ pom.xml.asc
.hgignore
.hg/
.vscode
.cpcache
48 changes: 43 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,42 @@ This hook returns the current database client with some helpful functions for sy

Check out the [Firebase example](https://homebaseio.github.io/homebase-react/#!/example.todo_firebase) for a demonstration of how you might integrate a backend.

## Debugging tips
## Debugging
Homebase React uses ClojureScript and its corresponding data format EDN internally. We then compile all of that to Javascript using the Google Closure Compiler (closure not clojure, I know right) to get as small a bundle as possible. Then we provide APIs (react hooks) that accept JSON and do all the conversion to EDN and back again behind the scenes.

EDN and Clojure provide far more safety and extensibility than JSON and Javascript. Clojure being immutable by default and EDN being extensible. This lets us build and support features that would be unwieldy in JSON and JS.

However, the tradeoffs are:

1. A larger bundle size. Some of the Clojure runtime cannot be compiled away even though the closure compiler is really aggressive.
2. Clojure error messages sometimes leak into JS land. We try to annotate the ones we know about so they make sense to JS devs, but it's far from perfect and if you see something weird please create an issue.
3. Our code is released already minified. We do this because most people do not develop with the google closure compiler and other build tools are not nearly as effective at optimizing this code. This makes debugging homebase-react while developing a bit harder since the code is not very readable, but we think the tradeoff is worth it to provide a smaller bundle size. And to compensate we try to build enough supporting dev tooling so you never need to read the compiled source.
4. Confusing console logs. EDN data looks different from JSON and to add to that, homebase-react mostly outputs entities, which are lazy data types and not very helpful when logged out with the default console formatting. See custom chrome formatters below for a vastly improved logging experience.

### Custom chrome console log formatters
If you develop with [Chrome](https://www.google.com/chrome/) or a Chromium browser like Brave or Edge you'll get significantly more meaningful logs for entities `console.log(anEntity)` due to our use of custom chrome :formatters. These custom formatters allow us to perform lazy database queries to fetch all of an entity's attributes, including references to other entities and all reverse references to the current entity. They let you access your entire data graph from the console, with any logged out entity as an entry point.

**To enable custom chrome formatters**

**1.** Open the preferences panel in chrome devtools by clicking the cog.

<img alt="image of chrome devtools preferences button" src="public/images/enable_chrome_formatters_1.png" width="400">

**2.** Toggle `Enabled custom formatters` on.

<img alt="image of chrome devtools custom formatters toggle" src="public/images/enable_chrome_formatters_2.png" width="400">

**3.** Keep the chrome console open and refresh the page. Any logged out entities should now have the custom formatting.

<img alt="image of custom entity chrome console logs" src="public/images/enable_chrome_formatters_3.png" width="400">

**Live demo:** open the console while on the [todo example](https://homebaseio.github.io/homebase-react/#!/dev.example.todo) page.

**Remember**: for custom formatters to work `console.log(anEntity)` must be called *after* you open the chrome console. Anything logged out before you open the console will not have custom formatting applied because chrome processes those logs in the background.

### *DEPRECATED* `_recentlyTouchedAttributes`

*Use [custom chrome formatters](#custom-chrome-formatters) instead.*

If you set `debug` to `true` in your configuration, you will be able to access the `_recentlyTouchedAttributes` attribute on entities. `_recentlyTouchedAttributes` will show any cached attributes for a given entity. This is helpful for approximating that entity's schema and values.

Expand All @@ -199,12 +234,15 @@ If you set `debug` to `true` in your configuration, you will be able to access t

## Roadmap

1. Document integration with more backends
2. Swap [Datascript](https://github.com/tonsky/datascript) out for [Datahike](https://github.com/replikativ/datahike)
1. Improve developer tools: custom chrome formatters, DB admin console extension
2. Rewrite React ↔ Homebase cache
1. Support async DB access (for Datahike)
2. Reactive query planning (better perf on pages with lots of live reads)
3. Swap [Datascript](https://github.com/tonsky/datascript) out for [Datahike](https://github.com/replikativ/datahike)
1. Immutability
2. History / Change Tracking
3. Persist to IndexedDB
4. [Local-first](https://www.inkandswitch.com/local-first.html) conflict resolution for offline caching and sync between multiple devices
4. Persist to IndexedDB
5. [Local-first](https://www.inkandswitch.com/local-first.html) conflict resolution for offline caching and sync between multiple devices

## Limitations
Homebase React is currently not a good choice for read-heavy applications (e.g. Twitter, ecommerce). We plan to support these query patterns with our [platform](http://homebase.io) eventually.
Expand Down
10 changes: 10 additions & 0 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{:paths ["src"]
:deps {thheller/shadow-cljs {:mvn/version "2.11.25"}
devcards/devcards {:mvn/version "0.2.7"}
datascript/datascript {:mvn/version "1.0.7"}
reagent/reagent {:mvn/version "1.0.0-alpha2"}
inflections/inflections {:mvn/version "0.13.2"}
binaryage/devtools {:mvn/version "1.0.2"}
homebaseio/datalog-console {:git/url "https://github.com/homebaseio/datalog-console" :sha "91d5b6009d66807ceec9807a1f8ed099a0a6f219"}
;; homebaseio/datalog-console {:local/root "../datalog-console"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}}}
2 changes: 1 addition & 1 deletion docs/0100|Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ As data and our need to annotate and organize it grows, so does our need for sup

To solve this problem, modern write-heavy applications such as Superhuman, Roam Research, and Facebook Messenger built their own embedded data layers to enable these more sophisticated user experiences.

Homebase-react enables developers to access the same embedded datalog database as Roam Research through React hooks. You no longer have to build out a team or learn specialized tools like Clojure in order to build a delightful write-heavy application.
Homebase React enables developers to access the same embedded datalog database as Roam Research through React hooks. You no longer have to build out a team or learn specialized tools like Clojure in order to build a delightful write-heavy application.

## Install

Expand Down
14 changes: 13 additions & 1 deletion docs/0200|Quick_Start.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
> We recommend everyone start by [enabling custom chrome formatters](/docs/homebase-react/main/debugging#custom-chrome-formatters) for a much better debugging experience.
![image of custom entity chrome console logs](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_3.png?raw=true)

Ok. Let's get going.

Homebase React creates a local relational database for your React app.

Adding `HomebaseProvider` automatically creates the database.

```js
import { HomebaseProvider } from 'homebase-react'

Expand Down Expand Up @@ -33,4 +41,8 @@ const App = () => {
</button>
)
}
```
```

For a step by step guide take a look at the [tutorial](/docs/homebase-react/main/tutorial).

Check out the [API docs](/docs/homebase-react/main/api) to learn about our other hooks like [`useQuery`](/docs/homebase-react/main/api#usequery) and [`useClient`](/docs/homebase-react/main/api#useclient).
8 changes: 7 additions & 1 deletion docs/0300|Tutorial.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
This tutorial takes you through our [Todo Example](https://homebaseio.github.io/homebase-react/#!/example.todo).

## Custom chrome formatters

> We recommend everyone start by [enabling custom chrome formatters](/docs/homebase-react/main/debugging#custom-chrome-formatters) for a much better debugging experience.
![image of custom entity chrome console logs](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_3.png?raw=true)

## HomebaseProvider

Let's get started.
Welcome back. Let's get started for real.

`HomebaseProvider` is a component that wraps your React app and creates a local relational database. This database is then accessible to any child components via React Hooks.

Expand Down
4 changes: 4 additions & 0 deletions docs/0400|API.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
> We recommend everyone start by [enabling custom chrome formatters](/docs/homebase-react/main/debugging#custom-chrome-formatters) for a much better debugging experience.
![image of custom entity chrome console logs](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_3.png?raw=true)

## `HomebaseProvider`

The HomebaseProvider wraps your React app and makes a relational database accessible to all of your components. Configure it with `lookupHelpers` and `initialData`.
Expand Down
43 changes: 43 additions & 0 deletions docs/0675|Debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Homebase React uses ClojureScript and its corresponding data format EDN internally. We then compile all of that to Javascript using the Google Closure Compiler (closure not clojure) to get as small a bundle as possible. Then we provide APIs (react hooks) that accept JSON and do all the conversion to EDN and back again behind the scenes.

EDN and Clojure provide far more safety and extensibility than JSON and Javascript; Clojure being immutable by default and EDN being extensible. This lets us build and support features that would be unwieldy in JSON and JS.

However, the tradeoffs are:

1. A larger bundle size. Some of the Clojure runtime cannot be compiled away even though the closure compiler is really aggressive.
2. Clojure error messages sometimes leak into JS land. We try to annotate the ones we know about so they make sense to JS devs, but it's far from perfect and if you see something weird please create an issue.
3. Our code is released already minified. We do this because most people do not develop with the google closure compiler and other build tools are not nearly as effective at optimizing this code. This makes debugging homebase-react while developing a bit harder since the code is not very readable, but we think the tradeoff is worth it to provide a smaller bundle size. And to compensate we try to build enough supporting dev tooling so you never need to read the compiled source.
4. Confusing console logs. EDN data looks different from JSON and to add to that, homebase-react mostly outputs entities, which are lazy data types and not very helpful when logged out with the default console formatting. See custom chrome formatters below for a vastly improved logging experience.

### Custom chrome formatters
If you develop with [Chrome](https://www.google.com/chrome/) or a Chromium browser like Brave or Edge you'll get significantly more meaningful logs for entities `console.log(anEntity)` due to our use of custom chrome :formatters. These custom formatters allow us to perform lazy database queries to fetch all of an entity's attributes, including references to other entities and all reverse references to the current entity. They let you access your entire data graph from the console, with any logged out entity as an entry point.

**To enable custom chrome formatters**

**1.** Open the preferences panel in chrome devtools by clicking the cog.

![image of chrome devtools preferences button](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_1.png?raw=true)

**2.** Toggle `Enabled custom formatters` on.

![image of chrome devtools custom formatters toggle](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_2.png?raw=true)

**3.** Keep the chrome console open and refresh the page. Any logged out entities should now have the custom formatting.

![image of custom entity chrome console logs](https://github.com/homebaseio/homebase-react/blob/master/public/images/enable_chrome_formatters_3.png?raw=true)

**Live demo:** open the console while on the [todo example](https://homebaseio.github.io/homebase-react/#!/dev.example.todo) page.

**Remember**: for custom formatters to work `console.log(anEntity)` must be called *after* you open the chrome console. Anything logged out before you open the console will not have custom formatting applied because chrome processes those logs in the background.

### DEPRECATED `_recentlyTouchedAttributes`

*Use [custom chrome formatters](#custom-chrome-formatters) instead.*

If you set `debug` to `true` in your configuration, you will be able to access the `_recentlyTouchedAttributes` attribute on entities. `_recentlyTouchedAttributes` will show any cached attributes for a given entity. This is helpful for approximating that entity's schema and values.

```js
<HomebaseProvider config={{ debug: true }}>
<App/>
</HomebaseProvider>
```
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"firebase": "^8.0.2",
"firebaseui": "^4.7.1",
"highlight.js": "10.4.1",
"hoist-non-react-statics": "^3.3.0",
"husky": "5.0.0-beta.0",
"jest": "26.6.0",
"jest-performance-testing": "^1.0.0",
Expand All @@ -77,8 +78,11 @@
"react": "16.14.0",
"react-component-benchmark": "0.0.4",
"react-dom": "16.14.0",
"react-grid-layout": "^0.16.6",
"react-icons": "^2.2.7",
"react-performance-testing": "^1.2.3",
"react-test-renderer": "^16.14.0",
"reakit": "^0.11.1",
"semantic-release": "17.2.3",
"semantic-release-cli": "5.4.0",
"shadow-cljs": "2.11.4",
Expand Down
Binary file added public/images/enable_chrome_formatters_1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/enable_chrome_formatters_2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/enable_chrome_formatters_3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/logo-blk.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 12 additions & 12 deletions shadow-cljs.edn
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
;; shadow-cljs configuration
{:source-paths
["src"]

:dependencies
[[devcards "0.2.7"]
[datascript "1.0.1"]
[reagent "1.0.0-alpha2"]
[inflections "0.13.2"]
[camel-snake-kebab "0.4.2"]]

{:deps true
:dev-http {3000 "public"}
:nrepl {:port 3333}
:builds
{:dev {:target :browser
:output-dir "public/js"
:asset-path "/js"
:compiler-options {:devcards :true
:externs ["datascript/externs.js"]
:output-feature-set :es6}
:modules {:main {:init-fn dev.example.core/init}}
:js-options {:resolve {"devcards-marked" {:target :npm :require "marked"}
Expand All @@ -28,9 +20,17 @@
:output-to "out/node-tests.js"
:ns-regexp "-test$"
:autorun true}
:npm {:target :npm-module
:npm {:target :node-library
:output-to "dist/js/homebase.react.js"
:output-dir "dist/js"
:entries [homebase.react]
:exports {:HomebaseProvider homebase.react/HomebaseProvider
:useClient homebase.react/useClient
:useTransact homebase.react/useTransact
:useEntity homebase.react/useEntity
:useQuery homebase.react/useQuery}
:compiler-options {:optimizations :advanced
:externs ["datascript/externs.js"]
:pseudo-names false
:pretty-print false
:output-wrapper false
:source-map false}}}}
4 changes: 4 additions & 0 deletions src/dev/example/js/array.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const Items = () => {
const [store] = useEntity({ identity: 'store 1' })
const [transact] = useTransact()

// Try opening the console in Chrome with custom formatters enabled
// https://homebase.io/docs/homebase-react/main/debugging#custom-chrome-formatters
console.log(store)

let newI = null
const onDragOver = React.useCallback((e) => {
e.preventDefault()
Expand Down
3 changes: 3 additions & 0 deletions src/dev/example/js/counter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const App = () => (
const Counter = () => {
const [counter] = useEntity({ identity: 'counter' })
const [transact] = useTransact()
// Try opening the console in Chrome with custom formatters enabled
// https://homebase.io/docs/homebase-react/main/debugging#custom-chrome-formatters
console.log(counter)
return (
<div>
Count: {counter.get('count')}
Expand Down
3 changes: 3 additions & 0 deletions src/dev/example/js/todo-firebase.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ const TodoList = () => {
// or sibling Todos don't trigger unnecessary re-renders.
const Todo = React.memo(({ id }) => {
const [todo] = useEntity(id)
// Try opening the console in Chrome with custom formatters enabled
// https://homebase.io/docs/homebase-react/main/debugging#custom-chrome-formatters
console.log(todo)
return (
<div>
<div
Expand Down
6 changes: 4 additions & 2 deletions src/dev/example/js/todo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ const TodoList = () => {
// or sibling Todos don't trigger unnecessary re-renders.
const Todo = React.memo(({ id }) => {
const [todo] = useEntity(id)
// Try opening the console in Chrome with custom formatters enabled
// https://homebase.io/docs/homebase-react/main/debugging#custom-chrome-formatters
console.log(todo)
return (
<div>
<div
Expand Down Expand Up @@ -234,8 +237,7 @@ const TodoFilters = () => {
type="checkbox"
checked={filters.get('showCompleted')}
onChange={(e) =>
transact([{ todoFilter: { id: filters.get('id'), showCompleted: e.target.checked } }])
}
transact([{ todoFilter: { id: filters.get('id'), showCompleted: e.target.checked } }])}
/>
</label>
&nbsp;·&nbsp;
Expand Down

4 comments on commit e74f757

@vercel
Copy link

@vercel vercel bot commented on e74f757 Apr 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on e74f757 Apr 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on e74f757 Apr 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on e74f757 Apr 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

homebase-example-todo – ./examples/todo

homebase-example-todo-homebaseio.vercel.app
homebase-example-todo.vercel.app
homebase-example-todo-git-master-homebaseio.vercel.app

Please sign in to comment.