# A new approach to assets in 2.1.0.rc3

**URL:** <https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900>\
**Category:** development\
**Created:** [January 26, 2024, 10:07am UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900 "2024-01-26T10:07:25Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [January 26, 2024, 10:07am UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/1 "2024-01-26T10:07:25Z")

</div>

We’ll be making a Hanami 2.1.0.rc3 next month, and it will contain a new approach to asset compilation. I want to explain this here in detail so you can understand what’s coming, so you can know what to test with your apps, and to gather any feedback you may have!

## Background

Last year we released Hanami 2.1.0.rc1 and .rc2 and were preparing for the 2.1.0 final release when we encountered an issue with our assets handling: assets from different slices, but with the same base names would conflict and override each other in the final compiled `public/assets/` directory.

We explored [a fix for this](https://github.com/hanami/assets-js/pull/18) inside our hanami-assets JS package, and while we could have made that work, several downsides remained:

- We still required a duplicate (and incomplete) implementation of detecting Hanami slices
- We still required users to keep a redundant slice prefix in front of each slice’s assets (e.g. `javascript_tag("admin/app")` inside the `Admin` slice
- We still merged all slice assets into a single shared manifest, thereby breaking the isolation that slices otherwise provide
- It required us to keep and maintain a more complex esbuild wrapper, which would increase the chances of bugs or issues in the future.
- And because our usage of esbuild would have remained off its “golden path”, it increased our risk of hitting an evolutionary dead end for this overall approach.

Given all of this, we decided to step back and try a fresh approach to assets handling. I’ve now proven this approach will work, and I’d like to share it with you in advance of the upcoming rc3 release.

* * *

## The new approach: the `hanami` CLI invokes an esbuild process per slice

Previously, we invoked a single Node process that process that found all assets, compiled them with esbuild and then created a merged manifest. In the bug fix attempt I linked above, we looked at invoking an esbuild compilation per slice within the same single Node.js process (using async/await to run them in parallel).

With our new approach, our `hanami assets compile ` and `assets watch` commands will invoke a single esbuild process per slice, and will pass the relevant slice paths as arguments to each esbuild process. We’ll handle this by forking to a Ruby process per slice.

In this approach, slices will be detected faithfully, since it’s our Ruby code that already knows about all registered slices and their locations.

## esbuild compiles a single slice’s assets only, and outputs to a dedicated directory with a dedicated manifest

When our esbuild wrapper is invoked by the CLI, it will compile the assets within a _single slice only_, and output the compiled files to a dedicated directory for the slice:

- For the app, this is `public/assets/`
- For each slice, this is `public/assets/[slice_name]/`

A single `assets.json` manifest will be written into _each directory_, and will contain entries for _that slice’s assets only._

In this way, our usage of esbuild becomes much more typical: one input directory, one output directory. Nice and simple.

## Every slice will have its own independent `"assets"` component

With every slice having its own assets directory and its own assets manifest, this also means that every slice will have its own `Hanami::Assets` instance registered as a component with the `"assets"` key, providing access to the assets in that slice’s manifest.

## A slice can only access its own assets by default (with those assets no longer redundantly prefixed by the slice name)

Following from the above, this means a slice _will have access only to its own assets by default._

This means e.g. that `javascript_tag("app.js")` in an `Admin` slice will reference the file at `/public/assets/admin/app-[hash].js`.

Because each slice has its own assets component and its own underlying assets manifest, that means that you no longer need to provide the redundant slice name prefix that you had to do for the previous 2.1.0 release candidates. This is why you can write `javascript_tag("app.js")` instead of `javascript_tag("admin/app.js")`.

## Assets may be shared across slices via component imports and view context deps

Slices are meant to be serve as a means to isolate code, and the approach with assets will now take this same approach.

However, if you need to access assets from another slice, you can do so by:

1. Importing the `"assets"` component from the other slice
2. Including the imported assets component as a dependency of your slice’s view context
3. Referencing that assets object directly in your views/helpers: `javascript_tag(other_slice_assets["app.js"])`

This is not intended to be the mainstream approach, but the fact that it is possible should allow some flexibility where it is needed. See [this PR](https://github.com/hanami/hanami/pull/1372) for a clear demonstration.

## A slice may have its own `config/assets.js`

Lastly, if you need to provide custom esbuild options for a particular slice’s asset compilation, you will now be able to do this via a custom `config/assets.js` that will be picked up and used just for that slice. All you need to do is put the file inside the slice’s own `config/` directory: `slices/[slice_name]/config/assets.js`.

The app’s top-level `config/assets.js` will be used for all slices that do not have their own custom config.

* * *

## Where can I see this work?

Check out the following work-in-progress PRs:

- [Run multiple assets processes by timriley · Pull Request #131 · hanami/hanami-cli · GitHub](https://github.com/hanami/cli/pull/131)
- [Compile within single slice only by timriley · Pull Request #20 · hanami/hanami-assets-js · GitHub](https://github.com/hanami/assets-js/pull/20)
- [Require a root when initializing assets by timriley · Pull Request #136 · hanami/hanami-assets · GitHub](https://github.com/hanami/assets/pull/136)
- [Set up an assets provider per slice by timriley · Pull Request #1371 · hanami/hanami · GitHub](https://github.com/hanami/hanami/pull/1371)
- [Support cross slice assets by timriley · Pull Request #1372 · hanami/hanami · GitHub](https://github.com/hanami/hanami/pull/1372)

## When will the rc3 release be?

I’m hoping for first half of February.

I’d love some solid testing for a week or two. If all goes well, 2.1.0 stable will come next.

Thanks for checking this out, and I hope this new approach can provide the most solid foundation for assets in Hanami 2. If you have any feedback, please share it here.

---

<div class="post-metadata">

**Author:** ![katafrakt](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/katafrakt/32/735_2.png) [@katafrakt](https://discourse.hanakai.org/u/katafrakt)\
**Post date:** [January 26, 2024, 10:43am UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/2 "2024-01-26T10:43:19Z")

</div>

This looks great! Can’t wait to test it.

However, I think that sharing assets between slices might turn out to be more mainstream than you think 😉 (depending on how people use slices, of course) So it’s awesome to see this will be officially supported.

---

<div class="post-metadata">

**Author:** ![swilgosz](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/swilgosz/32/484_2.png) [@swilgosz](https://discourse.hanakai.org/u/swilgosz)\
**Post date:** [January 30, 2024, 9:39pm UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/3 "2024-01-30T21:39:52Z")

</div>

Yeah, I can’t wait to play with it either!

[I’ve published a few ideas how slices can be used](https://hanamimastery.com/episodes/36-scale-your-app-with-slices), but I can’t wait as community will come with other ideas.

For what I see currently, I’d be mostly interested in accessing root application assets in slices by default, and maybe having sth like: “shared” slices, which I’d import assets and other components from.

However, if I’d go with things like shared slices, maybe it would be better to not use app at all.

I’m still exploring cases where App root is useful and I’m not sure how I’ll use it when it comes to slices.

---

<div class="post-metadata">

**Author:** ![katafrakt](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/katafrakt/32/735_2.png) [@katafrakt](https://discourse.hanakai.org/u/katafrakt)\
**Post date:** [January 31, 2024, 9:35am UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/4 "2024-01-31T09:35:32Z")

</div>

Isn’t `app` just a “special slice”? I always thought it is - which is why I deleted it 😛 But I see I will need some kind of `shared` slice for common assets (and other stuff perhaps) too.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/solnic/32/757_2.png) [@solnic](https://discourse.hanakai.org/u/solnic)\
**Post date:** [February 1, 2024, 4:47pm UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/5 "2024-02-01T16:47:00Z")

</div>

> Isn’t `app` just a “special slice”

@katafrakt yep, a single-app setup means you just have one slice of a cake

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [February 2, 2024, 2:31am UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/6 "2024-02-02T02:31:42Z")

</div>

> [@katafrakt](#):
>
> This looks great! Can’t wait to test it.

Thanks for checking it out!

> [@katafrakt](#):
>
> However, I think that sharing assets between slices might turn out to be more mainstream than you think 😉 (depending on how people use slices, of course) So it’s awesome to see this will be officially supported.

This is useful input, thank you!

The ability to access assets from another slice was certainly a must have for me in terms of this new approach. However, I have mixed thoughts about how “clunky” it may feel to people: declaring the import in the slice file seems OK, but the need to then add is as a dep in the respective view context class, and then refer to those assets via a `some_slice_name_assets["..."]` call in your views may feel like too much friction.

Perhaps the this is “positive friction,” though, in that it may lead the user to reconsider other approaches than the wholesale import of another slice’s assets.

Either way, I think I have the right foundations in place now, such that we have the capability to cleanly build more streamlined experiences if we see enough user feedback about the need to share assets.

One thing I might consider before a release is whether there might be a smoother way to access assets from the **app** level. But I think we might have the ingredients for this already. If you want fully co-mingled assets across your Hanami app, just don’t put asset files into individual slices; keep them all in `app/assets/`. Then after that, if you add `"assets"` to the app’s `config.shared_app_component_keys`, then those single set of assets will be available in every slice.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [February 11, 2024, 7:14pm UTC](https://discourse.hanakai.org/t/a-new-approach-to-assets-in-2-1-0-rc3/900/7 "2024-02-11T19:14:44Z")

</div>

The work described up top is now fully implemented and available in the main branches of hanami, hanami-assets, hanami-assets-js and hanami-cli.

> [@timriley](#):
>
> If you want fully co-mingled assets across your Hanami app, just don’t put asset files into individual slices; keep them all in `app/assets/`. Then after that, if you add `"assets"` to the app’s `config.shared_app_component_keys`, then those single set of assets will be available in every slice.

I can also confirm that the above approach will work if you want to have a single set of shared assets across all slices.
