forked from twbs/bootstrap
-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Prototype] Migrate docs from Hugo to Astro 🚀 #9
Closed
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
julien-deramond
changed the title
feat(docs): migrate docs from Hugo to Astro
Migrate docs from Hugo to Astro 🚀
Feb 20, 2023
julien-deramond
force-pushed
the
main-jd-bootstrap-astro
branch
from
March 6, 2023 18:30
fbc02ec
to
1ada453
Compare
* fix: remove useless astro script and fix package.json indentation * fix: remove default template content * feat: refactor layouts * feat: move new site src & dist folders * feat: load configm from config.yml * feat: add prettier * fix: config type * feat: add astro check * feat: add typecheck to lint script * fix: eqeqeq * feat: rename and move DocsNavbar & DocsVersions * feat: move skippy * feat: move scripts & icons * feat: add head component * feat: add header component * fix: stricten layout type in components * fix: add missing docs layout * feat: add canonical url * feat: refactor navigation links * chore: add todo * refactor: production check to avoid a string * refactor: versioned docs path * fix: docsearch doc version * feat: page title * chore: add todo * feat: add social * chore: add todos * feat: load styles * fix: disable prettier in base layout * chore: add todos * refactor: move style imports
* feat: pass down title to navigation component This enables a markdown page with a "Examples" title to highlight the matching header link item. * feat: port svg icons * fix: srcset syntax with embedded src * feat: add semver regular expression * feat: add home icons component content * feat: add home themes component content * refactor: move entirely astro to site-new The source code is now in site-new/src, dist in site-new/dist, etc. * feat: add (temporary) color modes * fix: opt-out explicitely of astro js bundling for external scripts
…strap + replace URLs in home/*.astro components
…URLs in Favicons.astro
* fix: pass down astro props to base layout * feat: 404 page ui This commit introduces the concept of layout `overrides` to add custom attributes to the <body /> and <main /> tags. * fix: remove unused exports * docs: document base layout props This also refactor frontmatter props to use `MarkdownLayoutProps` as they should. * feat: 404 page title * chore: remove 404 description todo already handled * feat: docs layout body overrides * feat: add MastHead component
* feat: example extra_js integrity * feat: auto import type definitions * fix: cheatsheet-rtl syntax issues * feat: versioned docs paths validation
julien-deramond
force-pushed
the
main-jd-bootstrap-astro
branch
from
March 24, 2023 07:03
b37a052
to
d3e6e81
Compare
julien-deramond
changed the title
Migrate docs from Hugo to Astro 🚀
[Prototype] Migrate docs from Hugo to Astro 🚀
Mar 24, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Introduction
This PR is a Work In Progress to migrate our documentation from Hugo to Astro, see if it's worth it and gather feedback from the team regarding such a potential migration.
A preview of the current state of the migration deployed by Netlify is available here.
This PR is co-authored by @HiDeoo.
Why?
Please note that the various points below are not exhaustive and are mostly based on the current implementation and usage of Hugo in Bootstrap, and the same goes for Astro.
Hugo's limitations
Hardcoded version number
The current version number of Bootstrap is still hardcoded a lot in the current documentation website in various places:
config.yml
file.Bumping the version number requires to change all these places manually, which can be error-prone and time-consuming. In this migration attempt, we took the opportunity to refactor this and use a single source of truth for the version number, which is defined in the
config.yml
file and is used everywhere else, even to generate dynamic routes like/docs/5.3/getting-started/introduction/
. This means that bumping the version number in the documentation website will only require to change a single file.Extensibility
According to the discussion that happened when switching to Hugo and this open Bootstrap issue, a lot of back and forth had to happen between Bootstrap team and the Hugo main developer to make the website work as expected. Even today, it still feels like there are some places where we're limited to what Hugo can do and we lack some flexibility, one example coming to mind is the way the ToC is generated. This discussion, even if the issue wasn't finally a real issue, shows that we are really dependent on the Hugo implementation and choices.
The fact that Hugo is written in Go makes it a bit difficult to contribute to it if we ever have to, especially considering the languages mostly used by the Bootstrap community. It also means that we're limited to what the Hugo team is willing to ship in its binary (we are relying on
hugo-bin
for this) and we can't really extend it to our needs easily.Astro is written in TypeScript/JavaScript and is a lot more flexible in this regard. It is also a lot more extensible and this migration attempt has shown this. In order to reduce the number of changes, we tried to stick to the current way of doing things as much as possible, even if this means not 100% doing things the Astro way and using all the features it provides. Even with that restriction, we were able to implement ourselves all the features without needing to contribute to Astro itself, which is a good sign. It even goes as far as controlling how Markdown is parsed and rendered.
Documentation
This is only a personal opinion but I'm often lost in the documentation where I don't always understand how the features are really working and how to finally exploit all of Hugo's possibilities and power with autonomy. It feels like you need to know exactly what you are looking for to properly find it in the documentation.
Dynamic routes
While working on a pull request to add a glossary for all our classes, I stumbled upon a limitation of Hugo regarding generating dynamic routes. Building upon this new glossary feature, I want to add pages in the documentation to preview the changes between 2 versions of Bootstrap.
Using a new process, I generate a list of classes shipped in each version of Bootstrap and then use these lists to generate diffs between 2 versions. Using all these data, I want to generate various routes to access these diffs, e.g.
/docs/5.3/changes/5.0.2...5.3.0/
. According to this issue, it is currently not possible in Hugo.Workarounds exist, but they are not really satisfying as they require using another process to dynamically create pages at build time in the correct folder and with proper naming, for Hugo to be able to pick them up and remove them at the end of the build process.
Astro provides a way to generate any dynamic routes directly through TypeScript/JavaScript which is a lot more flexible and easier to use.
Syntax
Hugo uses Go Templates, provides a primer documentation about it, and also links to the Go documentation for more details. This last link can be overwhelming for someone who doesn't know Go and is not familiar with the syntax.
The Go templating syntax definitely has a learning curve, can be very confusing and hard to read for many people at first sight which can make it hard to contribute to the documentation website, e.g. the following syntax examples:
Another point that can be annoying with Go Templates is when rendering plain text (e.g. an attribute value) using ranges, conditions, etc. Due to the fact that, unlike HTML, white spaces are significant in text, it can be difficult to make templates that both outputs the correct format and are easy to read. For example, the following code:
will output:
To get
value1
without the leading and trailing white spaces, we either need to inline the condition, which can make the code hard to read if there are multiple conditions, or use the different{{-
and-}}
syntax, which is not very intuitive and can be hard to remember.Astro's limitations/disadvantages
Astro's cons
Build time
Hugo is blazingly fast. There is no denying that. Astro is not as fast as Hugo, but we are still far from being slow and close to the build time we had when using Jekyll. This basic benchmark proves that for a production build of the entire website:
Although Astro is not as fast as Hugo, it is important to note that the process used in this migration is doing a lot more things than the current ones. All the logic is written in a type-safe language (TypeScript) so this requires more work, and a lot of effort has been put into adding more confidence to not ship a broken website by validating and typing a lot of data.
For example, all the configuration from
config.yml
is validated before building the website, e.g. ensuring a field containing a URL actually has a valid URL, that a version number is semver compliant, etc. The same goes for the data but also frontmatters of all pages, e.g. if a documentation page expects to have a frontmatter fieldtitle
which is a string, it will fail to build if it's not the case or it is missing.Syntax
Even if the syntax is most of the time simpler than Hugo's, it is still a new syntax to learn for the Bootstrap team and there is a learning curve. Astro component syntax is a superset of HTML and is meant to feel familiar to anyone with experience writing HTML or JSX. Regarding content, this migration uses MDX (.mdx) files which bring added features like support for JavaScript expressions and components in Markdown content.
Altho, in the effort to reduce changes with the current website and stick to some concept used with Hugo, some bits can definitely feels more complex and verbose. These cases can probably be simplified and refactored in the future if we decide to go with Astro and adopt a more Astro way of doing things but this was not the goal of this migration attempt.
To support some of these concepts, we also had to extend Astro, and even tho it was fairly easy, it is some extra code to maintain.
TypeScript
The logic and code are written in TypeScript, which has benefits but also some drawbacks. It is a bit more verbose than JavaScript, can feel a bit more complex to write, and adds some overhead to the build process. The choice to use TypeScript was made to give more confidence and reduce the risk of shipping a broken website and also increase the developer experience, especially with auto-completion or inline documentation in code editors but it should be noted that this is not a requirement for Astro and it can be used with JavaScript as well so we could decide to switch to JavaScript if we feel like it's too much of a burden.
Astro's pros
Some of the pros of Astro have already been mentioned in the previous section but here are some more.
Language/platform/ecosystem
Astro is written in TypeScript/JavaScript running on Node.js which is close to the tools and languages used by Bootstrap. The Bootstrap community is also way more familiar with JavaScript than Go if we ever need to deep dive into the codebase of the build process to either fix a bug or add a feature.
This also means that any library published on npm can be used in Astro, which can be a huge advantage when it comes to adding more complex features to the website. Markdown processing is built around Remark and Rehype which have a huge ecosystem of plugins and tools to extend the Markdown syntax and the HTML output.
Community
Astro is still a young project but it is growing fast and has a very active community. The Discord server is very active and the core team is very responsive and helpful. By relying on a more modern and trendy tool, we might be able to attract new contributors to the project, and also seems like a good way to communicate that Bootstrap is compatible with modern tools and technologies.
Potential enhancements
This pull request is already huge and as stated in the beginning, the goal was to migrate the website to Astro without changing the current website too much by porting some concepts from Hugo to Astro. Using Astro and its components-based approach, there should be a lot of things that should be easier to do later on, like:
How to test
To test this PR locally, after checking out the branch, running
npm install && npm run astro-dev
should start a local development server onhttp://localhost:3000
with the new website.To test a production version locally, run
npm run astro-build && npm run astro-preview
and point your browser tohttp://localhost:3000
.Online preview is also available for this PR on Netlify which is the hosting solution currently used by Bootstrap for PRs.
GitHub Pages preview is not provided here to avoid dealing with the setup of GitHub pages on a fork and setting up a custom base href which would be different from the one used in the main repo. The easiest way is to run
npm run astro-build
and copy the content ofsite-new/dist
like we would do it for a release.Implementation details
Check implementations details
Folder structure
Everything related to the new website is in the
site-new
directory at the moment. This is temporary and should be renamed if we decide to go with Astro. Here is a list of the most important directories:site-new/src
contains the source of the website that will be built by Astro.site-new/src/assets
contains assets that are handled by Astro, e.g. bundled, minified, etc. like some JavaScript code used by the website, examples and their associated assets, etc.site-new/src/content
contains Astro Content Collections representing various content of the website that can either be Markdown or MDX files.site-new/src/content/callouts
contains all the reusable callouts used in the documentation.site-new/src/content/docs
contains the documentation content.site-new/static
contains files that are copied as-is to the final build directory.Configuration and data
In order to simplify the migration, the
config.yml
file has been kept around but simplified. It now only contains configuration related to Bootstrap (and not to the technology used by the website, e.g. Hugo or Astro which is configured insite-new/astro.config.ts
), can be edited without any chance to break the website, and everything in it is accessible, validated and type-safe.Data files have also been kept around and are now validated against a schema to ensure all required values are present and all values are of the correct type.
Configuration and data values are easily accessible from Markdown files (even frontmatter) or TypeScript files with a syntax similar to Hugo's
{{ .Site.Params.foo }}
:Having everything type-safe and validated also means that we get auto-completion or inline documentation in code editors, e.g. in VS Code:
Layouts
Layouts are Astro components used to provide a reusable UI structure, such as a page template. Located in
site-new/src/layouts
, they mimic the current Hugo layouts:BaseLayout.astro
is the base layout for all pages.DocsLayout.astro
is the layout for all documentation pages.ExamplesLayout.astro
is the layout for all examples pages.RedirectLayout.astro
is the layout used to redirect to another page.SingleLayout.astro
is the layout used for pages that don't need a specific layout.Shortcodes
Still in the idea of not introducing too many changes at once, the concept of shortcodes has been kept around. They are now Astro components (everything is pretty much components in Astro) located in
site-new/src/components/shortcodes
. They are automatically loaded by Astro and can be used in Markdown files like this:Setup
Editor
Astro works with any code editor. The team is maintaining an official Astro VS Code Extension that unlocks several key features and developer experience improvements for Astro projects like syntax highlight, TypeScript type information, and Intellisense for
.astro
files.Prettier
Prettier, a popular formatter for JavaScript, HTML, CSS, and more, is used in the new website for Astro components and TypeScript files to ensure a consistent code style but it should be noted that this is a choice and totally optional as Astro doesn't require it.
If using the official Astro VS Code Extension or the Astro language server within another editor, code formatting with Prettier is included out of the box.
Linting
The linting process for the new website is currently split into various parts:
astro check
that runs Astro-related diagnostics (such as type-checking within.astro
files).ESLint is not yet part of this combo yet but will be easily added in the future for the documentation website but also for code snippets like it is done in the current website.
Deployments
Regarding deployments, there are 2 different targets to take into account: Netlify for previews deployments and GitHub Pages for the main website.
Netlify
This PR is already deployed to Netlify and a preview is available here.
Regarding settings, only 2 settings need to be defined in the Netlify UI:
The publish directory is where we build the new website, it is
site-new/dist
at the moment.The build command is the command to build the new website, it is
npm run astro-netlify
at the moment and mimics what thenetlify
npm script was doing.GitHub Pages
Running
npm run astro-build
will createsite-new/dist
.Some files are generated which are not in Hugo
_site
directory but are present ingh-pages
at the root level:gh-pages
)The other files are the same as Hugo
_site
:An extra
_astro
directory is created.All the "redirection" directories and their
index.html
exist with the same content:about
components
examples
getting-started
migration
docs/5.3
contains the same structure of folders:about
assets
components
content
customize
dist
examples
forms
getting-started
helpers
index.html
layout
migration
utilities
The main difference we can observe is the loading of
_astro/*.js
that will handle the assets which is done differently in Hugo.Some discrepancies can be observed in the HTML files but don't change the behavior.
Closing remarks
Surprisingly, it only took a few weeks with a few hours here and there to completely rewrite all the documentation in Astro.
Some tricky things were not planned but we managed to quickly find a workaround each time without having to create an issue or a discussion upstream. Autonomy is the first word that comes to my mind.
Even after a few years working on Bootstrap (and Orange fork), I still find Hugo's syntax challenging and sometimes even magical (see twbs#38308). In a few days, I felt more confident with Astro's syntax, closer to what web developers are used to.
Types definitely provide a safety net and give a lot more confidence in not shipping a broken website.
I can't guarantee it but I got the feeling that we might have more contributors by having an Astro-based documentation. Moreover, a lot of plugins are already in place and we could benefit from a lot of them in the future to have a more modern documentation without too much effort.
I really liked this experience with Astro.
It is also important to note that even tho this PR might not be merged, it was a good exercise to learn more about Astro and see how it could be used to build the Bootstrap website. It also helped us to identify some issues in the current website that we will or were able to fix and contribute to the project.
Boostrap upstream fixes
bootstrap-social-logo.png
twbs/bootstrap#38164metaDataFormat
from the config, not used anymore since 2019: Remove metaDataFormat setting gohugoio/hugoDocs#908group
frontmatter property could be entirely removed from all pages.placeholder
shortcode color and background params when 'img' markup twbs/bootstrap#38263