Skip to content

Commit 4c6f0a3

Browse files
committed
Initial commit
1 parent 634812c commit 4c6f0a3

35 files changed

+6981
-1
lines changed

.eslintrc.cjs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module.exports = {
2+
root: true,
3+
parser: '@typescript-eslint/parser',
4+
plugins: [
5+
'@typescript-eslint',
6+
],
7+
extends: [
8+
'eslint:recommended',
9+
'plugin:@typescript-eslint/recommended',
10+
'prettier'
11+
],
12+
rules: {
13+
quotes: ['error', 'single', { avoidEscape: true }],
14+
'@typescript-eslint/no-unused-vars': [
15+
2,
16+
{ args: 'all', argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
17+
],
18+
},
19+
};

.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# build output
2+
dist/
3+
4+
# dependencies
5+
node_modules/
6+
7+
# logs
8+
*.log*
9+
10+
# environment variables
11+
.env
12+
.env.production
13+
14+
# macOS-specific files
15+
.DS_Store
16+
17+
# emacs temporary files
18+
.#*

.prettierignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package.json
2+
package-lock.json
3+
*.md

.prettierrc.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"arrowParens": "always",
3+
"bracketSpacing": true,
4+
"parser": "typescript",
5+
"semi": true,
6+
"singleQuote": true,
7+
"tabWidth": 2,
8+
"trailingComma": "es5",
9+
"useTabs": false,
10+
"overrides": [
11+
{
12+
"files": "*.json",
13+
"options": {
14+
"parser": "json"
15+
},
16+
"files": ["*.css","*.scss"],
17+
"options": {
18+
"parser": "scss"
19+
}
20+
}
21+
]
22+
}

README.md

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
# solid-bookstore-a
2-
Segregated UI in Action with SolidJS
2+
3+
[MobX](https://mobx.js.org)'s Michel Weststrate picked up the idea of the [Humble Dialog](./assets/TheHumbleDialogBox.pdf) (2002) (see also [Humble Object](http://xunitpatterns.com/Humble%20Object.html)) in [UI as an Afterthought](https://michel.codes/blogs/ui-as-an-afterthought) (2019), a topic he had previously touched on in his [2017 React Amsterdam talk](https://youtu.be/3J9EJrvqOiM?t=710).
4+
5+
This repo takes the [2017 React & MobX demo](https://github.com/mweststrate/react-mobx-shop/tree/react-amsterdam-2017) and "ports" it to [SolidJS](https://www.solidjs.com/) but preserves the notion of the [Segregated DOM](https://martinfowler.com/bliki/SegregatedDOM.html) to enable lightning fast [microtesting](https://youtu.be/H3LOyuqhaJA) (and perhaps [improving](https://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html) the client-side application design in the process).
6+
7+
The idea of applying [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) ([Hexagonal Architecture](https://web.archive.org/web/20191210095000/https://alistair.cockburn.us/hexagonal-architecture/)) to the front-end is fielded regularly (e.g. [1](https://medium.com/@Killavus/hexagonal-architecture-in-javascript-applications-and-how-it-relates-to-flux-349616d1268d), [2](https://dev.to/huytaquoc/a-different-approach-to-frontend-architecture-38d4), [3](https://dev.to/xurxodev/moving-away-from-reactjs-and-vuejs-on-front-end-using-clean-architecture-3olk)) but the concept itself originates from back-end software. It's easily overlooked that some web applications can [ill afford](https://alistapart.com/article/responsible-javascript-part-1/) to take on bloat resulting from a front-end framework **and** a state management solution plus any code necessary to decouple the UI from the client-side behaviour:
8+
9+
> [you’re making a trade-off in terms of initial performance](https://timkadlec.com/remembers/2020-04-21-the-cost-of-javascript-frameworks/#the-big-picture).
10+
11+
SolidJS is unique as its [component boundaries vanish during runtime](https://dev.to/this-is-learning/components-are-pure-overhead-hpm). That makes it possible to assemble client-side behaviour purely from the [reactive primitives](https://www.solidjs.com/guides/reactivity#introducing-primitives) and [reactive stores](https://www.solidjs.com/docs/latest/api#using-stores). Using this approach "application components" tend to manifest around [stores](./src/stores) and can be wired together separately from the UI. The UI elements ([pages](./src/pages), [components](./src/components)) then simply snap onto the application core ([Shop](./src/stores/Shop.ts)) without the typical decoupling overhead.
12+
13+
This results in an application core that can be microtested without the overhead of rendering any markup or interacting with a surrogate DOM. This leaves the behavioural tests free to provide lightning fast [feedback](https://twitter.com/mfeathers/status/997570047185842176) during development while the remaining less responsive UI tests can be delayed to less frequently exercised integration tests.
14+
15+
Currently this demo compiles to a ~37Kb (~15Kb gzipped) build.
16+
17+
---
18+
19+
## Notes
20+
* Yes, this could use a bit more work; perhaps later.
21+
* SolidJS's reactive primitives only work within a tracked context. On the client-side [render](https://www.solidjs.com/docs/latest/api#render) ([`index.tsx`](.src/index.tsx)) is responsible for creating that environment.
22+
* When testing outside of the browser an owner scope has to be explicitly created with [`createRoot`](https://www.solidjs.com/docs/latest/api#createroot) for the test to run in. The [rootAndRun()](./tests/helpers/index.ts) testing utility wraps a test passed as a factory in such a scope. See the [demo test](./tests/demo.skip.ts) for a rudimentary example and [Testing your Solid.js code with jest](https://dev.to/lexlohr/testing-your-solidjs-code-2gfh) for more background.
23+
* When running server-side SolidJS's reactivity is deliberately curtailed to properly support SSR. For the client-side code under test to operate as intended it is necessary to direct the module loader to load the browser version of SolidJS instead of the server version. This is accomplished with [`solid-register`](https://github.com/atk/solid-register). For more background see [Testing Solid.js code beyond jest](https://dev.to/lexlohr/testing-solidjs-code-beyond-jest-39p).
24+
* [uvu](https://github.com/lukeed/uvu) was selected for its speed and [minimalist](https://medium.com/javascript-scene/why-i-use-tape-instead-of-mocha-so-should-you-6aa105d8eaf4) API.
25+
26+
---
27+
28+
Clone the repo (requires node.js 16.9 or later):
29+
```
30+
$ cd solid-bookstore-a
31+
$ npm i
32+
$ npm run test
33+
```
34+
35+
… and watch the tests fly. To launch the app …
36+
37+
```
38+
$ npm run dev
39+
```

assets/TheHumbleDialogBox.pdf

78 KB
Binary file not shown.

index.html

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<meta name="theme-color" content="#000000" />
7+
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
8+
<link rel="stylesheet" href="/src/assets/index.css" />
9+
<title>SolidJS Book Shop</title>
10+
</head>
11+
<body>
12+
<noscript>You need to enable JavaScript to run this app.</noscript>
13+
<div id="root"></div>
14+
15+
<script src="/src/index.tsx" type="module"></script>
16+
</body>
17+
</html>

0 commit comments

Comments
 (0)