iTranslated by AI
Astro (Vite): Organizing Build Assets into Folders for Easier Delivery
In Astro's standard build, all assets are aggregated in the _astro/ folder.
However, in professional projects, it is common to be required to deliver assets with a "specific folder structure" or "consolidated CSS/JS files."
In this article, I will explain how to output files in an organized and easy-to-maintain format by leveraging Rollup settings.
1. Quick Start: Environment Setup
First, let's create a base project.
# 1. Create a project
npm create astro@latest my-project
# 2. Move to the directory and install dependencies
cd my-project
npm install astro-html-beautifier astro-relative-links
The two packages introduced here play an important role in enhancing the "quality" and "versatility" of the deliverables.
| Package Name | Role | Reason for Introduction |
|---|---|---|
| astro-html-beautifier | HTML Beautification | Astro's output HTML often has messy indentation due to componentization. This organizes it into clean, human-readable indentation. |
| astro-relative-links | Relativizing Paths | Normally, Astro paths are root-relative (starting with /), but this converts them to relative paths (starting with ./). This prevents broken links regardless of the server hierarchy where they are placed. |
Comparison image of folder structure
- Standard build: Everything is placed flatly in _astro/, and file names are hashed, making them indecipherable to humans.
- The method in this article: Purpose-specific folders are created under assets/, allowing the contents to be inferred from the file names.
2. Implementation: astro.config.mjs Settings
In this section, we describe the configuration to sort images, styles, and scripts into folders based on their extensions.
import { defineConfig } from 'astro/config';
import htmlBeautifier from 'astro-html-beautifier';
import relativeLinks from 'astro-relative-links';
export default defineConfig({
site: 'https://example.com/',
build: {
assets: 'assets/scripts', // Basic output destination for JS
},
vite: {
build: {
assetsInlineLimit: 0, // Set to 0 to force disable <style> inlining
cssCodeSplit: false, // Consolidate CSS into one
rollupOptions: {
output: {
// Settings for JS files
entryFileNames: `assets/scripts/script_[hash].js`,
// Settings for images, CSS, and other assets
assetFileNames: (assetInfo) => {
const rawName = assetInfo.names?.[0] ?? '';
// Distributing image files (replacing -- with / for layering)
if (/\.(gif|jpeg|jpg|png|svg|webp|mp4)$/.test(rawName)) {
const name = rawName.replace(/--/g, '/');
return `assets/images/${name}`;
}
// Distributing CSS files
if (/\.css$/.test(rawName)) {
return 'assets/styles/[name]_[hash].[ext]';
}
// Others (fonts, etc.)
return 'assets/[name].[ext]';
},
},
},
},
},
integrations: [
relativeLinks(), // Convert paths to relative format
htmlBeautifier({ // Beautify HTML
indent_size: 2,
indent_char: '\t',
}),
],
});
3. "Folder Hierarchy Hack" to Maintain Directory Structure
Normally, when building with Astro (Vite), the hierarchical structure in the source folder is ignored, and assets are output flatly. Therefore, we implement a trick to pseudo-restore the folder hierarchy by including -- in the file names.
Mechanism to Convert "--" into Folder Delimiters
The key is the following logic written in assetFileNames within astro.config.mjs.
const name = rawName.replace(/--/g, '/');
return `assets/images/${name}`;
Through this process, the -- in the file name is interpreted as / (path separator) at build time, and physical folders are generated.
| Original File Name | Output Path |
|---|---|
| src/assets/images/common/common--logo.png | assets/images/common/logo.png |
| src/assets/images/top/top--hero.jpg | assets/images/top/hero.jpg |
Naming files with long names like common--... during development is honestly a bit tedious. However, just by following this rule, you can gain the following benefits:
- Automatic Folder Sorting: Eliminates the need to manually move files after the build.
- Compliance with Delivery Requirements: Accurately reproduces the "usual folder structure" specified by the client without errors.
- Prevention of Broken Links: Since naming conventions are directly linked to paths, the structure becomes easier to predict.
The aim of this method is to automatically generate "well-organized delivery data" through a "little bit of ingenuity during development."
4. Switching "Hash Values" Based on Project Needs
You can choose between different settings depending on whether you need browser cache countermeasures or want to prioritize ease of management.
Pattern A: Prioritizing Cache Countermeasures (With Hash)
Append a random string to the file name to ensure the latest version is always loaded upon update.
entryFileNames: 'assets/scripts/script_[hash].js',
assetFileNames: 'assets/styles/[name]_[hash].[ext]',
Pattern B: Prioritizing Maintainability (Without Hash)
This is ideal when you are told, "We edit the HTML directly, so please don't change the file name."
entryFileNames: 'assets/scripts/main.js',
assetFileNames: 'assets/[name].[ext]',
Note: In this case, because file names are fixed, old cache is likely to remain in the browser.
You will need to take measures such as adding parameters like example.jpg?v=1234 on the HTML side.
5. Modifying .astro Files and Building
For this example, let's try adding the following to src/components/Welcome.astro.
---
import logo from '../assets/images/common/common--logo.png';
---
<img src={logo.src} />
Once reflected, execute the build with the following command:
npm run build
Unlike the standard Astro build, the folder structure of "traditional Web production" that is easy for humans to maintain will be reproduced.
Output Structure after Customization (Inside dist/)
dist/
├── index.html # Indentation is organized, paths are relative (./)
└── assets/
├── images/ # Layered by replacing "--" with "/"
│ ├── common/
│ │ └── logo.png
│ └── top/
│ └── hero.jpg
├── scripts/
│ └── script_a1b2c3d.js # JS aggregated here
└── styles/
└── index_e5f6g7h.css # All CSS consolidated into one
Key Points of the Structure
-
Aggregation in assets/: Instead of the default
_astro/, all resources are consolidated in the commonassets/directory. -
Restoration of Folder Hierarchy: A filename like
src/assets/images/common--logo.pngis converted into a physical folder structure likeassets/images/common/logo.pngafter the build. -
Guaranteed Relative Paths: Thanks to
astro-relative-links, paths are written as./assets/...fromindex.htmland../assets/...from lower-level pages likeabout/index.html. This ensures that the display will not break no matter which level of the server you upload it to.
With this structure, a person in charge who is asked to "change this wording a bit" after delivery can sufficiently modify the files without a build environment.
Summary: Matching Delivery Rules while Using Astro
The following improvements are now possible through these measures:
- Appearance of Code: Using htmlBeautifier to format machine-generated code into something readable.
- Path Resolution: Using relativeLinks to create data that won't have broken links regardless of placement.
- Ease of Management: Using the "--" hack and JS aggregation to make post-delivery file modifications easier.
"While using tools conveniently, ensure the deliverables strictly match the recipient's requirements (folder structure, etc.)." This was an introduction to customization aimed at "smoothing out communication" on the front lines.
Discussion