flecks/website/docs/creating-a-fleck.mdx
2024-01-04 03:23:04 -06:00

175 lines
5.0 KiB
Plaintext

---
title: Creating a fleck
description: A fleck is a module but also so much more.
---
import Create from '@site/helpers/create';
If you are following along from the previous getting started
[configuration page](./configuration), you have an application with 3 flecks:
- `@flecks/core`
- `@flecks/server`
- `@flecks/web`
<details>
<summary>About that "3 flecks" thing...</summary>
Actually, your server application has 6 flecks at this point:
- `@flecks/core`
- `@flecks/core/server`
- `@flecks/server`
- `@flecks/server/server`
- `@flecks/web`
- `@flecks/web/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 cheesier 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:
<Create type="fleck" pkg="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': {}
'@flecks/web': {}
// 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"
exports.hooks = {
'@flecks/web/client.up': async () => {
window.document.body.append('hello world');
},
};
```
Now, restart your application and visit your website. Glorious, isn't it?
## Everything so far... plus Electron!
Let's add another core fleck. flecks ships with a core fleck `@flecks/electron`. This runs your
application inside of an instance of [Electron](https://www.electronjs.org/). You'll add the fleck:
```bash
npx flecks add @flecks/electron
```
Then you'll update your `build/flecks.yml` like so:
```yml
'@flecks/core':
id: 'hello_world'
'@flecks/electron': {}
// highlight-start
'@flecks/server':
up:
- '...'
- '@flecks/web'
- '@flecks/electron'
// highlight-end
'@flecks/web': {}
'@hello-world/say-hello:./packages/say-hello/src': {}
```
### ~~flecking~~ pecking order
We added some configuration to `@flecks/server`. The `up` key configures the order in which flecks
are initialized when the server comes up. We make sure `@flecks/web` serves a webpage before
`@flecks/electron` tries to visit it.
:::tip
`'...'` just means "everything else": if any other flecks implement that hook then they will run
here. It is valid to provide entries both before and after `'...'`.
The default configuration of
`@flecks/server.up` is simply:
```yml
'@flecks/server':
up:
- '...'
```
However in this case the order of hook execution is undefined. That's why we configure it
explicitly.
:::
Finally `npm start` and you will see something like this:
![An image of our simple hello world application running inside an Electron window](./flecks-electron.png)
Isn't it beautiful? :relieved: