Nuxt 3 gives us two great options for managing all of our assets in our web app.
But what’s the difference, and how do you know which to use?
************************Short answer: use
~/assets by default, only using
~/public if you absolutely need to.
In this article I’ll share some simple questions you can ask yourself to figure out where to put your assets, as well as the differences between the two strategies.
Two Ways to Handle Assets
Not everything in your app is code.
There are lots of non-code assets:
- audio files
- stylesheets (yes, technically it’s code, but it’s not JS)
In any web app, including with Nuxt, we have two main ways to deal with these non-code assets:
- We can process them through our bundler
- We can leave them as is
While both of these are ways to handle assets, the first method uses the
~/assets folder and the second uses the
Yes, the naming is kind of confusing, but it’s a convention that has long been used by the broader web dev community, so we’re stuck with it.
How do you choose?
There are 3 main questions to ask yourself:
- Does this need to be processed in some way?
- Does this asset change often, or not at all?
- Does it need a specific filename?
1. Does this need to be processed in some way?
The first question is mostly self-explanatory.
If you have a bunch of images, you likely want to make sure those images are compressed and optimized before shipping them with your web application.
A sitemap, on the other hand, is good as it is. No need to do anything extra with it.
2. Does this asset change often, or not at all?
The last two questions impact how this asset will be cached.
Our code changes often, so we want to include it in our bundle. This is because our bundler will give our code bundle a unique name every time it changes, based on a hash of the contents.
(We also want to process our code, but let’s ignore that for a moment.)
This means the browser will be forced to always have the latest version of our code.
3. Does it need a specific filename?
Page crawlers will be looking for a file specifically called
robots.txt, so we need to preserve that filename.
For most other assets though, the filename doesn’t matter so much.
Let’s take a closer look at the differences between these two methods.
Any files that you put into the
~/public directory get included directly in the build output of your Nuxt app. They are not modified in any way.
This public directory is served at the root of your app. This means that if your
~/public folder looks like this:
public/ - cats.png - songs/ - dubstep.wav - chopin.mp3
You can access these files directly from your browser:
yourwebsite.com/cats.png yourwebsite.com/songs/dubstep.wav yourwebsite.com/songs/chopin.mp3
Remember, these files are not touched at all. The contents of
~/public are copied straight into your
These are common things we put in the
But generally, we’ll want to keep most things as assets.
All of the code in your application is processed by a bundler. In Nuxt 3, this is Vite by default.
The bundler will start at
app.vue and pull in all of its dependencies, then all of their dependencies, and so on, until all of the code in your app has been processed.
This becomes the bundled output that you can use to deploy your application.
If you import something other than “code” into a component, the bundler still has to include those files as well. Otherwise, they wouldn’t be deployed alongside all of your other code:
import screen1 from '~/assets/images/screen1.png'; import screen2 from '~/assets/images/screen2.png'; import screen3 from '~/assets/images/screen3.png'; import from '~/assets/styles/radStyleSheet.css';
When you do this, the bundler will do a few things:
- Process the file with any configured plugins
- Generate the bundled file with the file’s hash in the name (for caching purposes as we mentioned earlier)
- Replace the
importwith this new filename so your bundled code can find the file when it’s deployed
It doesn’t actually matter where you put these images or stylesheets. But we have to put all of these other assets somewhere to keep things organized, so we typically use
~/assets by convention.
One added benefit of importing assets directly like this, is that if anything is missing you will get build errors. That won’t happen if you reference something in your
~/public folder, since it isn’t processed at all.
Most things usually end up being processed by the bundler, so you’ll commonly find these in an
You can learn more about managing assets from the Nuxt docs.