The carefree-board
project, or cfb
for short, is a lightweight, modular, and
easy-to-use board
library.
board
can be thought of 'drawboard' / 'canvas' / '2D graphics world' / ..., depending on what you want to build with it (e.g., a drawing app, an infinite canvas, a 2D game, ...).
carefree-board
needs deno
2.x to run. After you have installed
deno
, a web-native demo can be launched by:
deno task run:web
This will start the demo at http://localhost:1245
, and you can play with the cfb
.
Currently this demo only supports:
- Display some contents on the screen, namely:
- Two squares.
- A 'Hello, World!' text.
- Respond to pointer events - you can drag the contents around!
- Undo / Redo the dragging actions by clicking the corresponding 'buttons'.
This demo can run on both desktop and mobile browsers, but there are some additional features that are only available on desktop browsers:
- Undo / Redo by pressing the
Ctrl
+z
/Ctrl
+Shift
+z
keys. - Zoom in / out by rolling the mouse wheel while pressing the
Ctrl
/Meta
key. - Move the board globally by:
- pressing the
Space
key and dragging the mouse. - rolling the mouse wheel to move up / down.
- rolling the mouse wheel while pressing the
Shift
key to move left / right.
- pressing the
You can also visit here, which is hosted by
deno deploy
, to play around with the demo.Notice that I put single quotes to 'buttons' - this is because they are not real buttons, but just rectangle
node
s that can respond to pointer events.
carefree-board
is still in its VERY EARLY stage, and mainly serves as a POC. The
final goal is to define a set of abstract interfaces that can be extended to everything
related to 2D graphics.
All submodules are structured under a deno
workspace, and their functionalities are as
follows:
cfb-core
: implements the core components ofcfb
.cfb-svg
: implementssvg
exporters forcfb
.cfb-web
: a web-native renderer forcfb
that transpiles the data structures intodom
elements.
It REALLY took me couple of days to figure out how to manage a hybrid deno
monorepo. Let me define it - a hybrid deno
monorepo is a monorepo that:
- All members are
deno
first modules. - Some members are
browser
specific modules, and need to have a runnable frontend demo.
The second part is where nightmare begins. I struggled quite a bit to figure out how to correctly do the linkings / bundlings / servings. Finally I made it to what I think simple and elegant, and I'd like to share some experience here:
Hint: after all these setups, everything is TIDY and BLAZINGLY FAST compared to the traditional
webpack
/rollup
/tsconfig
/package.json
/ ... mess, which makes me feel all the efforts are worth it!
- Export everything in
main.ts
(to distinguish frommod.ts
that can be used in bothnode
andbrowser
environments) (exmaple). - Write startup codes in
public/index.ts
, which may import the workspace members and setup the application (example). - Use
esbuild
in adeno
script to bundleindex.ts
(notmain.ts
!) into a singlejs
file. It's common practice here towatch
for changes (example). - Write an
index.html
that includes the bundledjs
file. If the startup codes need to refer to some concretedom
elements, make sure to include the<script>
tag after the elements are defined (example). - Use
Deno.serve
to serve theindex.html
(example). - Happy coding!
One implicit step is that we need to create an
imports.json
explicitly. This step is to makednt
/esbuild
/deno publish
happy, and I think it can (and maybe should) be skipped once thedeno
ecosystem becomes more mature.
Some common deno
tasks for development:
deno task check
: will run bunch of checks asynchronously, includingfmt
,lint
,test
, drypublish
, etc.deno task bump
: bump the patch version in eachdeno.json
file no matter what.
Some common deno
tasks for CI:
deno task build
: build into npm packages withdnt
.deno task publish:npm
: publish the npm packages.
There are several module-specific tasks as well:
deno task {cmd}:web
: tasks specific tocfb-web
, seecfb-web
section below for more details.
A common .vscode/settings.json
for this project is as follows:
{
"deno.enable": true,
"deno.lint": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"[json]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[markdown]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[typescript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
}
}
I did not use
{
"...": "...",
"editor.defaultFormatter": "denoland.vscode-deno"
}
directly because I found its priority is not high enough in my case.
A common setup for developing cfb-web
is as follows:
- Open two terminals.
- In the first terminal, run
deno task dev:web
, this should be able to watch ALL changes in the workspace. - In the second terminal, run
deno task start:web
, this should start a local server athttp://localhost:1245
and you can test the changes in the browser. Notice that there are no hot-reload, so you need to refresh the page manually when changes are made.