flecks/website/docs/creating-a-fleck.mdx
2024-01-04 18:40:22 -06:00

156 lines
4.4 KiB
Plaintext

---
title: Creating a fleck
description: A fleck is a module but also so much more.
---
If you are following along from the previous getting started
[configuration page](./configuration), you have an application with 2 flecks:
- `@flecks/core`
- `@flecks/server`
<details>
<summary>About that "2 flecks" thing...</summary>
Actually, your server application has **4 flecks** at this point:
- `@flecks/core`
- `@flecks/core/server`
- `@flecks/server`
- `@flecks/server/server`
flecks will load the `[...]/server` fleck under any fleck that is loaded on the server. This is
also the case when using `@flecks/web` which will automatically load `[...]/client` flecks
which are only loaded in the browser. We'll be exploring this specifically in the next section.
If you're intersted in diving deeper, see [the platforms concept page](#todo).
Some frameworks make it a little more opaque to work with isomorphic code, but the flecks
philosophy is that visibility is believability: you'll have to be explicit about which code
runs where.
</details>
## Your first fleck
Let's make your website greet the user with a good ol' **hello world**.
To do this, you'll be creating your own little fleck. flecks also provides a built-in utility to
create a fleck.
:::note
You may have noticed that your little starter application has a `packages` directory. By default,
flecks structures your application as a monorepo.
This isn't any hard requirement, it's only a suggestion.
:::
### Create the fleck
Let's create our little fleck:
```bash
npx create-fleck say-hello
```
After some output, you'll find your new fleck at `packages/say-hello`. Let's inspect our
`build/flecks.yml`:
```yml title="build/flecks.yml"
'@flecks/core':
id: 'hello_world'
'@flecks/server': {}
// highlight-next-line
'@hello-world/say-hello:./packages/say-hello/src': {}
```
### 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
path to the package.
By the way, your other application code can import using the alias (e.g.
`require('@hello-world/say-hello');`)
[as if it were a package](https://webpack.js.org/configuration/resolve/#resolvealias).
<details>
<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).
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
There is a source file at `packages/say-hello/src/index.js` but for now it's empty. Let's fill it
out a bit:
```javascript title="packages/say-hello/src/index.js"
export const hooks = {
'@flecks/server.up': async () => {
process.stdout.write(' hello server\n');
},
};
```
Now, restart your application:
```bash
npm run start
```
You will be greeted by a line in the output:
```terminal
hello server
```
### flecks injection
Hook implementations may receive arguments. After any arguments, the `flecks` instance is always
passed.
`@flecks/server.up` doesn't pass any arguments, so the `flecks` instance is the first argument.
Let's see how to use the instance to read some configuration:
```javascript title="packages/say-hello/src/index.js"
export const hooks = {
'@flecks/server.up': async (flecks) => {
const {id} = flecks.get('@flecks/core');
process.stdout.write(` hello server: ID ${id}\n`);
},
};
```
This time, you will see:
```terminal
hello server: ID hello-world
```
:::note
...or whatever your application's ID is. We're assuming you're following along from
[the configuration page](./configuration).
:::
Next, we'll add and interact with some of the flecks shipped by default.