Astro is a static site generator which enables you to use a familiar javascript component architecture while shipping less client-side Javascript.
Problem with Sub-Path deployment
When you are not using a custom domain, Gitlab Pages deploys your website to a sub-path, e.g., http(s)://username.example.io/repository-name/
.
Due to an open bug, Astro ignores the buildConfig.site
configuration, which is necessary to rewrite all asset paths.
Solution
This is a small script which manually touches all files in the output directory and rewrites the paths. To use the script, copy it to your project’s root folder and name the file postbuild.mjs
.
import fs from 'fs'
import path from 'path'
import astroConfig from './astro.config.mjs'
const PUBLIC_DIR = astroConfig.dist || "dist"
const argvs = process.argv.slice(2);
if ((argvs[0] === '--p' || argvs[0] === '-path') && argvs[1]) {
let files = [];
const extensions = ['.html', '.css', '.js', '.json']
const PRODUCTION_URL = argvs[1]
const replaceUrlsInFiles = function(dirPath, arrayOfFiles) {
files = fs.readdirSync(dirPath)
files.forEach(function(file) {
const current = fs.statSync(dirPath + "/" + file)
if (current.isDirectory()) {
replaceUrlsInFiles(dirPath + "/" + file, arrayOfFiles)
} else {
const filePath = path.join(
path.dirname(
(
import.meta.url).replace(/file\:/, '')), dirPath, "/", file)
if (extensions.includes(path.extname(filePath))) {
let content = fs.readFileSync(filePath)
content = String(content).replace(/src="\//g, `src="${PRODUCTION_URL}`)
content = String(content).replace(/href="\//g, `href="${PRODUCTION_URL}`)
content = String(content).replace(/url\("\//g, `url("${PRODUCTION_URL}`)
content = String(content).replace(/src='\//g, `src='${PRODUCTION_URL}`)
content = String(content).replace(/href='\//g, `href='${PRODUCTION_URL}`)
content = String(content).replace(/url\('\//g, `url('${PRODUCTION_URL}`)
fs.writeFileSync(filePath, content)
}
}
})
}
if (PRODUCTION_URL && process.env.NODE_ENV === 'production') {
replaceUrlsInFiles(PUBLIC_DIR, files)
} else {
console.log('skip postbuild')
process.exit(0)
}
} else {
console.error('please provide a path argument "-path", "--p"')
process.exit(1)
}
You can now use the script as a post-build hook via NPM scripts.
{
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"postbuild": "node ./postbuild.mjs -path https://username.example.io/repository-name/",
"preview": "astro preview"
},
}
Conclusion
I hope this script helps you out until the bug in Astro is fixed. If you have some time to spare, please consider contributing to Astro :)
Top comments (3)
To cover for relative
./assets
paths, I used this instead. You can remove all the String(...).replace in the above code and replace with this (6 to 3 lines by account for single and double-quotes in the same regex).Great, thanks!
Your script worked for me, so thanks for sharing it! In my effort to find a more idiomatic solution I encountered this link from a Reddit thread: github.com/ixkaito/astro-relative-... and it did the trick as well. Sharing in case other people are having the same problem.
It's seems a little weird that Astro doesn't support this as a normal configuration setting, considering it's was originally a static website generator, as I understand it.