doc: final bits for preview

This commit is contained in:
cha0s 2024-01-29 11:48:06 -06:00
parent 9e663c5248
commit 9ceaab6245
10 changed files with 290 additions and 110 deletions

View File

@ -2,12 +2,6 @@ export const hooks = {
/**
* Define docker containers.
*
* :::warning
*
* The user running the server must have Docker privileges.
* See: https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user
*
* :::
* @invoke MergeUniqueAsync
*/
'@flecks/docker.containers': () => ({

View File

@ -0,0 +1,112 @@
---
title: Compilation
description: Flecks may be subject to compilation.
---
A fleck will not always be compiled. Distributed flecks in production (e.g. one you install from
`npm`) have already gone through a compilation step and will load very fast.
There are some conditions that, when matched, will result in a fleck being compiled.
flecks takes a build manifest such as:
```
'@flecks/build': {}
'@flecks/core': {}
'@flecks/server': {}
'@aliased/fleck:./packages/aliased-fleck': {}
```
and determines both the **roots** and **paths** that compose the application, and whether they
require compilation.
## Roots
A root is the package root of a fleck. A package root is defined as a directory with a
`package.json` file.
Multiple fleck paths may share the same root.
<details>
<summary>Sneaky little fleckses</summary>
`@flecks/react`'s root contains 7 flecks!
- `@flecks/react`
- `@flecks/react/client`
- `@flecks/react/router`
- `@flecks/react/router/client`
- `@flecks/react/router/server`
- `@flecks/react/server`
- `@flecks/react/tabs`
</details>
A root prefers to discover flecks within the `src` directory, but will fallback to discovering
files under the root if that fails.
## Paths and aliases
Paths are the **human-readable** names of flecks. From our example above, `@aliased/fleck` is a
path. `./packages/aliased-fleck` is an **alias**.
:::tip[Compilation condition]
The root path of an aliased fleck is **compiled**.
:::
### Symlinks
:::tip[Compilation condition]
If a root path is a symlinked path, the root path is **compiled**.
:::warning[Land of linkin']
Remember when you're linking a fleck to **link the output `dist` directory** and not the root path
of the fleck.
When building a fleck, [`package.json` is processed](./package-json) and that processed output
should ideally be the `package.json` that your package manager sees.
Don't worry: if the linked path ends with `/dist`, the parent directory will be used as the root
path!
:::
:::tip[Link 'em up]
When you are developing anything Sufficiently Complex:tm:, best practice is to symlink your
dependent fleck so that your package manager can do its job and manage your dependency tree.
:::
## Pitfalls with aliasing
:::warning[Aliased modules spaghetti]
When an aliased fleck is compiled, its own `node_modules` directory is added to the module search
paths for the application. This makes it **very easy** to get started writing a modular fleck.
There can easily come a point where aliased flecks in an application may have very esoteric
relationship between their `node_modules` directories, including but not limited to duplicate
versions of libraries being included in a compilation.
flecks makes very little effort to solve this problem as it is considered out of scope.
:::
:::warning[Unlikely alias]
You probably shouldn't do things like name an alias the same thing as a package that actually
exists in your `node_modules` directory. This is mitigated if you use the default monorepo
structure (unless your application name is identical to a monorepo organization that already
exists on `npm`: **don't do that**).
:::
All that being said, **aliasing exists** and it can take you pretty far!
If you'd like to help define better behavior for these edge cases you could always
[submit a pull request](https://github.com/cha0s/flecks/compare). :smile:

View File

@ -67,7 +67,7 @@ After some output, you'll find your new fleck at `packages/say-hello`. Let's ins
### Aliasing for the win
Notice there's a colon separating the path for this one. This is because this is an
[aliased fleck](#todo). The part before the colon is the alias and the part after is the
[aliased fleck](./compilation#paths-and-aliases). The part before the colon is the alias and the part after is the
path to the package.
By the way, your other application code can import using the alias (e.g.
@ -78,23 +78,11 @@ By the way, your other application code can import using the alias (e.g.
<summary>Wait, my modules don't have to be in <code>node_modules</code>?</summary>
Nope! When you're developing applications, it can be real nice to
just pull in local source "packages". If you're wondering how this works, see
[the alias concept page](#todo).
just pull in local source "packages".
That being said, sharing your packages on npm is a cool thing to do, so be rad and share your
awesome flecks with the rest of us!
:::warning
You probably shouldn't do things like name an alias the same thing as a package that actually
exists in your `node_modules` directory. This is mitigated if you use the default monorepo
structure (unless your application name is identical to a monorepo organization that already
exists on `npm`: don't do that).
If you'd like to help define what happens in these edge cases you could
always [submit a pull request](https://github.com/cha0s/flecks/compare). :smile:
:::
</details>
### Your first hook

View File

@ -230,35 +230,24 @@ import {Flecks} from '@flecks/core/server';
export const hooks = {
// highlight-start
'@flecks/server.up': async (flecks) => {
const {Content, Tag} = flecks.db.Models;
console.log(
'There were',
await Content.count(), 'pieces of content',
'and',
await Tag.count(), 'tags.',
);
},
'@flecks/server.up': Flecks.priority(
async (flecks) => {
const {Content, Tag} = flecks.db.Models;
console.log(
'There were',
await Content.count(), 'pieces of content',
'and',
await Tag.count(), 'tags.',
);
},
{after: '@flecks/db/server'},
),
// highlight-end
'@flecks/db.models': Flecks.provide(require.context('./models')),
}
```
We have to configure `build/flecks.yml` so that the database comes up before we try to use it:
```yml
'@db_test/content:./packages/content/src': {}
'@flecks/build': {}
'@flecks/core':
id: db_test
'@flecks/db': {}
// highlight-start
'@flecks/server':
up:
- '@flecks/db'
- '@db_test/content'
// highlight-end
```
We use [`Flecks.priority`](./ordering#fleckspriority) so that the database comes up before we try to use it.
Now, another `npm start` will greet us with this line in the output:
@ -328,7 +317,7 @@ restart it, you'll get a fresh new database every time. It was **quick to get st
but this isn't very helpful for any real purpose. Let's make a change to our `build/flecks.yml`:
```yml title="build/flecks.yml"
'@db_test/content:./packages/content/src': {}
'@db_test/content:./packages/content': {}
'@flecks/build': {}
'@flecks/core':
id: db_test
@ -392,7 +381,7 @@ npx flecks add -d @flecks/docker
Configure `build/flecks.yml`:
```yml title="build/flecks.yml"
'@db_test/content:./packages/content/src': {}
'@db_test/content:./packages/content': {}
'@flecks/build': {}
'@flecks/core':
id: db_test
@ -404,20 +393,9 @@ Configure `build/flecks.yml`:
username: postgres
// highlight-end
'@flecks/docker': {}
// highlight-start
'@flecks/server':
up:
- '@flecks/docker'
- '@flecks/db'
- '@db_test/content'
// highlight-end
'@flecks/server': {}
```
Notice that we configured `@flecks/server.up` to make sure to enforce a specific order in which
our server flecks come up: first `@flecks/docker` to spin up the database, then
`@flecks/db` to connect to the database, and finally our `@db_test/content` fleck to interact with
the database. This is important!
Now `npm start` will reveal the following message in the logs:
```
@ -457,46 +435,6 @@ There are 2 tags.
Awesome, we have a connection to a real postgres database!
<details>
<summary>Where is the docker container?</summary>
You may notice that the first time you start your application there is a delay while Docker spins
up your new database server. This is normal. You may have also noticed that subsequent runs speed
up to near-instantaneous. This is also normal!
`@flecks/docker` runs your container in a manner that outlives your application. If you kill your
application and then run:
```
docker ps
```
You will see a line for your postgres database looking something like:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
<SOME_ID> postgres "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp db_test_sequelize
```
You'll see under the `NAMES` column heading, there is an entry called `db_test_sequelize`. That's
our database! You can always
```
docker kill db_test_sequelize
```
to free up any resources being used. flecks keeps the containers running so that you get a nice
fast application start.
:::note[What's in a name?]
The container name is based off of `@flecks/core.id` which by default is `flecks`. If you change
your application's ID, the container name will be different!
:::
</details>
## Production
Sure, spinning up a database like magic is spiffy for development, but you probably want to be a

View File

@ -3,3 +3,70 @@ title: Docker
description: Spin up containers and orchestrate your production application.
---
Integrate your application with [Docker](https://www.docker.com/).
## Spin up containers
`@flecks/docker` can spin up containers for rapid development.
:::warning
The user running the server must have Docker privileges.
See: https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user
:::
Adding `@flecks/docker` to your `build/flecks.yml` will discover and spin up containers in
development. For instance, if you have `@flecks/db` in your `build/flecks.yml`, `@flecks/docker`
will automatically spin up a database.
See **Implementations** under
[the `@flecks/docker.containers` documentation](./flecks/hooks#flecksdockercontainers) to find
implementations of Docker containers.
`@flecks/docker` runs your container in a manner that outlives your application. If you kill your
application and then run:
```
docker ps
```
You will see lines for your containers looking something like:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
<SOME_ID> postgres "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp [FLECKS_ID]_sequelize
```
:::tip[What's in a name?]
The container name is based off of `@flecks/core.id` which by default is `flecks`. If you change
your application's ID, the container name will be different!
:::
You'll see under the `NAMES` column heading, there is an entry called `[FLECKS_ID]_sequelize`. That's
our database container! You can always
```
docker kill [FLECKS_ID]_sequelize
```
to free up any resources being used. flecks keeps the containers running so that you get a nice
fast application start.
## Build and orchestrate for production
`@flecks/docker` hooks the server build to include a `Dockerfile` and a `docker-compose.yml` to
both build and orchestrate your application with Docker.
By default, these will be found at `dist/server` after building your application.
After building, the application could be composed in Docker Compose using the following command:
```
docker-compose -f dist/server/docker-compose.yml up
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,11 +0,0 @@
---
description: It might matter where your code is running.
---
# Isomorphism
All this code we're writing could be running on your Node.js server, it could be running in the
browser, or both.
flecks solves this problem with [platforms](#todo) and the intelligent inclusion of only the code
relevant to the platform where the code is running.

View File

@ -0,0 +1,73 @@
---
title: package.json and entrypoints
description: Entrypoint detection and more.
---
# `package.json` and entry points
When developing a fleck (or any other package), we can specifiy the files included in the package
within our `package.json`'s `"files"` key. However, flecks augments your source `package.json`
during the build process and outputs a **built `package.json`**.
If you generate a fleck using `create-fleck`, its `"files"` key will look like this:
```json
"files": [
"index.js"
],
```
This tells flecks that `index.js` is an
[entry point](https://webpack.js.org/concepts/entry-points/). Any file resolvable by webpack will
be treated as an entry point and a separate file will be built and output.
flecks automatically adds some paths to the `"files"` key of your built `package.json`:
- `build` directory
- `src` directory (if sources exist)
- **sourcemaps** for each entry point (e.g. `index.js` -> `index.js.map`)
- `test` directory (if tests exist)
:::tip[Hook that one, too]
`@flecks/fleck` invokes a hook
[`@flecks/fleck.packageJson`](./flecks/hooks#flecksfleckpackagejson) which exposes this for any
other fleck to process `package.json` when building a fleck.
For instance, `@flecks/web` implements this hook. `@flecks/web` will automatically output
CSS, fonts, and other frontend assets to the `assets` directory in your build output. If any of
these frontend assets exist, `@flecks/web` will automatically add the `assets` directory to the
`"files"` key of your built `package.json`. You don't have to think about it!
:::
If you look at the
[published `@flecks/react` package on `npm`](https://www.npmjs.com/package/@flecks/react?activeTab=code)
you will see a tree of files published in the package:
![A screenshot showing the file tree of the `@flecks/react` package on `npm`](./flecks-react-npm.png)
However, if you look at
[the `"files"` key definition in `package.json` in the `@flecks/react` source](https://github.com/cha0s/flecks/blob/master/packages/react/package.json#L22)
you will see that it includes far fewer files:
```json
"files": [
"client.js",
"context.js",
"fake-context.js",
"index.js",
"router/client.js",
"router/context.js",
"router/index.js",
"router/server.js",
"server.js",
"tabs.js"
],
```
Think of your `"files"` key as a sort of `exports`, but for your files. Other code could `import`
any of those paths (e.g. `@flecks/react/client`, `@flecks/react/router/client`,
`@flecks/react/tabs`, etc.).
You don't have to think about or remember any of those other files! Let flecks handle it for you.

View File

@ -0,0 +1,17 @@
---
title: Platforms
description: It might matter where your code is running.
---
Platforms automatically discover flecks based on the platform where the code is running.
A fleck may provide a `/client` or `/server` path which is automatically included or excluded based
on the current platform.
:::tip[For example]
The `@flecks/react` fleck includes a `@flecks/react/client` and `@flecks/react/server` fleck. So
you can simply add `@flecks/react` to your `build/flecks.yml` and it will include everything
automatically for the server and client side.
:::

View File

@ -11,6 +11,7 @@ export default {
items: [
'installation',
'configuration',
'compilation',
'creating-a-fleck',
'adding-flecks',
],
@ -37,7 +38,8 @@ export default {
'hooks',
'gathering',
'ordering',
'isomorphism',
'platforms',
'package-json',
'documentation',
],
},