Asset Imports Without JavaScript Modifications

Hi everyone.

I’m sure many have come across this issue when developing with elm: I am using a web bundler (Vite in this case), and I would like to be able to import assets like images in a reasonable way. In JavaScript you would do that by just importing the image file, which then gets translated by Vite to the url of the file inside the build output, etc.
This is obviously harder in elm because imports work differently. For webpack, there is elm-assets-loader and elm-asset-webpack-loader, both of which rewrite the JavaScript generated by Elm at build time to replace function calls and strings respectively with import statements.

This seems to work somewhat, but feels brittle and not very elm-like.
I’m interested in how other people in the community handle this issue. I’ve thought about using code generators to create a function for each asset in my project and then do some usage analysis to decide which assets to actually bundle, but I’m not really sure this would work great either.


At work we import assets in JavaScript (using Parcel), and pass them in as flags to Elm. The downside is that it can be a bit annoying to pass them around.

My current dream setup would be code generation, I think. Just a small script that reads a directory of assets and produces an Elm file with one top-level value for each asset. It could even do hashing to allow for far-future caching. elm-review would take care of finding unused values, and thus unused assets.

My plan is to not care about which assets are used in which applications. I’m thinking just serve all the assets for all the apps. It won’t affect users at all, only deploy size.

If you do go with usage analysis, it might be enough with some regex on the compiled JS (in --optimize mode). The following should give you all used top-level values (defined by you, not packages) without false positives:

grep -E '^var \$author\$project\$[a-zA-Z$]+' elm.js

But also – looking back at how we’ve used assets at work, it feels like just having a static/ or public/ folder and hardcoded strings referring to them could have worked out pretty well. Instead of having 0 asset bugs, we might have had 1 but instead a simpler setup. Tradeoffs.


Caveat: I haven’t actually used this tool I am about to mention.

I was looking through Elm 2021, a year in review and came across elm-embed, which it seems may be usable in this situation. Instead of modifying the JS into an import statement and then relying on Vite to transform those into URLs, this could directly embed the URLs. The downside is that you would need to actually know how an image will be converted into a URL (if the image ends up with a hashed file name, this may not work).

At work, we have passed asset base URLs into Elm as flags and then (optimistically) computed the asset URLs for things like icons, which feels …meh.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.