Off Notes on Docusaurus Publishing
Docusaurus Version: 3.4.0
CloudFront Function Version: cloudfront-js-2.0
Essential Notes
`trailingSlash`
affectsbuild
and subsequently deployment
`trailingSlash`
configuration in docusaurus.config.[language]
looks innocuous but affects the build
output.
`trailingSlash=false`
generates a build
folder where docs
markdown translates page1.md
to page1.html
and folder1/page2.md
to folder1/page2.html
. Call this Build Type 1.
`trailingSlash=true`
or not defining the `trailingSlash`
configuration generates a build
folder where docs
markdown translates page1.md
to page1/index.html
and folder1/page2/index.html
. Call this Build Type 2.
These two types make no material difference to a GitLab Pages deployment but does impact an S3 + CloudFront deployment.
The latter configurations of /index.html
in folders, i.e. Build Type 2, allow one to define Error Handling in CloudFront by specifying /index.html
as a fallback on 403
error responses which are generated when CloudFront attempts to access either a relative path or path that does not exist. Both cases appear as a 403 Access Denied
to a CloudFront Distribution trying to access the associated S3 bucket via Origin Access Control (OAC).
This error behaviour is a known behaviour with the recommended set-up.
At this point with the Error pages configured — users will see pages loading the root page before loading the subfolder pages. Similarly for non-existent pages, the root page is loaded before Docusaurus’ 404 page appears. The effect is users see a kind of “flashing” effect on load, which is undesirable.
For a complete solution, an additional CloudFront Function is required.
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI is missing a file name.
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check whether the URI is missing a file extension.
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
This part of the solution is also referenced here, here and here.
With the CloudFront Function, the Error pages configuration is no longer required for handling subdirectory page routing but is still required for non-existent path routing. The flashing effect will remain on the non-existent paths.
No suitable CloudFront or S3 configuration could be found for the former, i.e. Build Type 1, where individual pages appear as [page*].html
.
Addendum: Exploring Possible Solutions on Build Type 1
Trying to write an intercepting CloudFront Function, an idea from above, that rewrites a request.uri
to the respective .html
pages causes a rendering issue with Docusaurus. Docusaurus thinks there is an issue with the `baseUrl`
and mistakenly thinks the `baseUrl`
is /page1.html/
in the case of https://[your-domain]/page1.html
even if otherwise defined in the docusaurus.config.[language]
file.
The rendering issue similarly exists for the root https://[your-domain]
or https://[your-domain]/
, with Docusaurus thinking the baseUrl is /
and recommending a change to /
.
Sample CloudFront Function
function handler(event) {
var request = event.request;
var line = request.uri
var url = line.split('//').pop()
var trimmed = (url.endsWith('/')) ? url.slice(0, -1) : url
var pieces = trimmed.split('/')
var slug = pieces[pieces.length - 1]
var toReturn = ''
if (slug.endsWith('.html')) {
if (line.endsWith('/')) {
toReturn = line.slice(0, -1)
} else {
toReturn = line
}
} else {
if (pieces.length > 1 && line.endsWith('/')) {
toReturn = line.slice(0, -1) + '.html'
} else if (pieces.length > 1 && !line.endsWith('/')) {
toReturn = line + '.html'
} else if (pieces.length <= 1) {
toReturn = line
}
}
request.uri = toReturn
return request;
}
Associating the above CloudFront Function to the CloudFront Distribution resolves the 403
error behaviour but causes some rendering issues with Docusaurus.
To further explore if this can be resolved so as to use Build Type 1.