forked from roman01la/uix
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,7 @@ yarn add [email protected] [email protected] | |
- [Code linting](/docs/code-linting.md) | ||
- [Utilities](/docs/utilities.md) | ||
- [Examples](/core/dev/uix/examples.cljs) | ||
- [Internals](/docs/internals.md) | ||
|
||
## Testing | ||
|
||
|
@@ -78,6 +79,7 @@ _Note: to ensure you're using the right Node.js version, you can use [nvm](https | |
once in the directory. Otherwise the Node.js version you use is in the `.nvmrc` file. See nvm repo for more documentation._ | ||
|
||
## Publishing | ||
|
||
1. Update version in core/release.edn, dom/release.edn and in README.md | ||
2. Update docs if needed | ||
3. Update CHANGELOG.md | ||
|
@@ -89,6 +91,7 @@ cd dom && CLOJARS_PASSWORD={YOUR_CLOJARS_TOKEN} clj -A:release --skip-tag | |
``` | ||
|
||
## Who's using UIx2? | ||
|
||
- [Pitch](https://pitch.com/) | ||
- [Cognician](https://info.cognician.com/) | ||
- [Multiply](https://multiply.co/) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Internals | ||
|
||
This document describes internals of UIx to give you a better overview how the library works internally. | ||
|
||
## High level overview | ||
|
||
On the surface UIx is a wrapper for React.js, it consists of two packages: `uix.core` and `uix.dom`, the former wraps `react` and the latter wraps `react-dom`. | ||
|
||
![](uix_internals_1.png) | ||
|
||
## uix/dom package | ||
|
||
`uix.dom` namespace is a thin wrapper around `react-dom` API, as simple as that. `uix.dom.server` is a custom made serializer that allows to render UIx components on JVM (of course third-party JS components won't run on JVM, so the JVM renderer is mostly useful for purely UIx made UIs or HTML templating, think static website generators). | ||
|
||
## uix/core package | ||
|
||
This one is a lot more involved. While the core package wraps a public API from `react`, it also makes hooks nicer, runs an internal linter and compiles components and UI structure into a more efficient code. | ||
|
||
### `defui` and `fn` macros | ||
|
||
`defui` is how you define a UIx component. What the macro is doing? Multiple things: | ||
|
||
1. Handles props passing, to make sure that Clojure's data structures can be used as component props, otherwise React will destroy them when validating props object | ||
2. Emits React component when compiling as ClojureScript and a plain function when running on JVM | ||
3. Injects `react-refresh` setup for [hot-reloading](/docs/hot-reloading.md) in dev | ||
4. Assignes readbale component name to improve debugging (those names are printed in stack traces and in React DevTools) | ||
5. Makes sure that a component is a single-arity function that takes a map of props | ||
6. Runs a [linter](/docs/code-linting.md) on component's body | ||
|
||
`uix.core/fn` macro is similar to `defui`, but should be used to create anonoymous components, which is useful for [render props technique](https://reactjs.org/docs/render-props.html). | ||
|
||
### `$` macro | ||
|
||
`$` is basically `React.createElement`, but with API that makes it nicer to use in Clojure world. Here's what it does: | ||
|
||
1. Runs a linter that validates element syntax | ||
2. Compiles DOM elements into Clojure-less code, for performance, when possible | ||
|
||
#### Element compiler | ||
|
||
This part, while there's not much code to it, is propbably where the most of complexity in UIx lives. | ||
|
||
`uix.compiler.aot` namespace (ahead of time compiler) takes care of compiling `$` elements to ClojureScript that is as close as possible to plain JS from performance standpoint. The compilation process boils down to transforming something like `($ :div {:on-click on-click} ...)` into `(react/createElement "div" #js {:onClick on-click} ...)`. The end goal is to have as less Clojure data types as possible in the end to achieve best performance. | ||
|
||
The compiler is not strict and makes a set of tradeoffs to provide flexibility for developers. Thus it's allowed to have dynamic (resolved at runtime) props, although in that case props map will be interpreted at runtime. | ||
|
||
### Hooks | ||
|
||
UIx wraps all React's default hooks and adds an extra layer to hide differences between JS and Clojure world, to make sure that writing is a bit less annoying: | ||
|
||
1. Compiles vector of deps into JS array | ||
2. Runs a linter to check for invalid usages of deps | ||
3. Handles React's requirement to return either a function or `js/undefined` from a hook in a way that `nil` becomes acceptable return value as well | ||
|
||
### Linter | ||
|
||
`uix.linter` implements a built-in linter that takes care of validating components and hooks. The linter is extensible via [public API](/docs/code-linting.md#custom-linters). | ||
|
||
The linter leverages ClojureScript's analyazer to retrieve information about code structure at compile-time. This data provides info about local and global vars, usages of vars, and of course the data structure representing the code being analyzed. | ||
|
||
When analyzing the linter collects and reports errors into ClojureScript's analyzer, that then takes care of printing those errors in terminal, failing a build and propagating them into shadow-cljs's on screen error display. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.