Skip to content
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

SvelteKit Tailwind Website #10

Closed
wants to merge 3 commits into from
Closed

SvelteKit Tailwind Website #10

wants to merge 3 commits into from

Conversation

AlistairKeiller
Copy link

@AlistairKeiller AlistairKeiller commented Oct 14, 2022

SvelteKit Tailwind website

Summary

This proposal introduces using SvelteKit and Tailwind for the iced.rs website. An implementation of which is hosted at https://iced-website.pages.dev/.

Motivation

The current Website system, which consists of Bulma and Zola, allows for bad practices that degrade the user experience. For example, the current website does not define the width and height of images, does not define the alt or href of a link, and uses a deprecated API.

Also, Bulma and Zola are not performant. Bulma results in a large amount of unused CSS, and Zola bundles FontAwesome into a single javascript file and Bulma into a single CSS file which results in .56 seconds of render-blocking resources.

Tailwind and SvelteKit will provide a better developer experience and a more performant application.

Guide-level explanation

Tailwind

Tailwind provides a JIT-compiled utility class library, allowing fewer lines of code and helpful guidelines to follow while maintaining the control of pure CSS and small bundle size. For example, when the developer types

<div class="flex"></div>

Tailwind will automatically generate

.flex {
  display: flex;
}

Tailwind also provides media and state queries, like hover, dark mode, and screen size. Some examples are

<div class="hover:text-sky-400"></div>

<div class="dark:text-slate-200"></div>

<div class="lg:hidden"></div>

<div class="dark:hover:bg-slate-700"></div>

Which respectively generate

.hover\:text-sky-400:hover {
  --tw-text-opacity: 1;
  color: rgb(56 189 248 / var(--tw-text-opacity));
}

@media (prefers-color-scheme: dark) {
  .dark\:text-slate-200 {
    --tw-text-opacity: 1;
    color: rgb(226 232 240 / var(--tw-text-opacity));
  }
}

@media (min-width: 1024px) {
  .lg\:hidden {
    display: none;
  }
}

@media (prefers-color-scheme: dark) {
  .dark\:hover\:bg-slate-700:hover {
    --tw-bg-opacity: 1;
    background-color: rgb(51 65 85 / var(--tw-bg-opacity));
  }
}

Tailwind's guidelines can also be overridden with custom values. For example

<div class="bg-[#50d71e]"></div>

will generate

.bg-\[\#50d71e\] {
  --tw-bg-opacity: 1;
  background-color: rgb(80 215 30 / var(--tw-bg-opacity));
}

This overall allows for faster development, cleaner code, the control of pure CSS, and a minimal CSS bundle.

SvelteKit

SvelteKit includes many different components that each improve the DX:

  • Svelte is a powerful and lightweight frontend framework (more details below).
  • Vite is frontend tooling with features like Hot Module Reload and optimized builds. Hot module Reload means that Vite can reload just a part of an application's javascript. This allows Vite to automatically load changes without reloading or losing the application's state.
  • TypeScript is a type-safe version of JavaScript. The type declarations also lead to better IDE tooling like autocomplete and better static analysis.
  • ESLint is a static analysis tool. It helps prevent the bad practices in the original website.
  • Prettier is a code formatting tool.
  • A client-side router to make site navigation more responsive.
  • Rendering options such as Prerendering, SSR, and CSR. Prerendering or SSR allows for better SEO and faster page loads.

The most influential part of SvelteKit is Svelte as a frontend framework. Svelte is a language that is like a reactive version of javascript and transpiles into vanilla javascript. For example, a counter in Svelte looks like

<script>
  let count = 0;

  function handleClick() {
    count += 1;
  }
</script>

<button on:click="{handleClick}">
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

and transpiles into 56 lines of vanilla javascript. As a transpiler, it has a much simpler syntax than DOM libraries and is lightweight and fast because it ships no unnecessary javascript.

As a result, the implantation at https://iced-website.pages.dev/ has a fast development time, fantastic LightScore score, and a (subjectively) solid UI.

Implementation strategy

The code for the implementation is at https://github.com/AlistairKeiller/iced-website.

The main code is at /src/routes/+layout.svelte and /src/routes/+page.svelte, while the rest of the project is mostly configuration and assets. +layout is served at the top of every page and currently contains the navigation bar, while +page.svelte is served as the index.html and is the main page's content. Most of the code is just Tailwind/HTML, with some Svelte for the dropdown navbar that appears on mobile.

I only have two noteworthy remarks about the current implementation. First, the SVG icons are manually inlined from Google Material Symbols for performance and flexibility at the cost of long lines of code. Second, the code example is manually syntax highlighted for performance and accuracy, at the cost of requiring a lot of Tailwind/HTML.

The plan for this implementation would be to finish up the main page by adding suggestions in this RFC, then add the other pages discussed in the GitHub conversation, like a Demo page, a Quickstart page, and a Contributors page.

The only edge case I can think of is whether the iced demo page would work with SvelteKit. If iced_web does not play nice with SvelteKit, for some reason, we can host the demo at a subdomain with a system that does play nice with iced.

Drawbacks

SvelteKit has not hit 1.0; it is in the release candidate phase. There are "no more planned breaking API changes," but according to SvelteKit's GitHub page, "expect bugs." Nevertheless, I have found it to be incredibly stable.

Svelte and SvelteKit are both relatively new, so developers may not be familiar with them. However, Svelte's syntax is very similar to HTML and JavaScript, so it should feel approachable and familiar to most web developers.

Rationale and alternatives

Web Framework

There are an endless number of alternatives. The major categories of alternatives to SvelteKit are web frameworks in a non-web language, static site generators, and Javascript web frameworks.

Web frameworks in a different language

Web frameworks in a non-web language, like Elm, Ruby on Rails, Yew, and Phoenix, will probably be less familiar than something closer to JS, HTML, or CSS. Even if that is not the case for something like Elm or Yew, it will certainly not have the tooling or package library of SvelteKit. So, for example, Markdown rendering and Tailwind would be harder to implement.

Static Site generators

Static Site generators, like Hugo, Jekyll, and Zola, don't have the control or tooling of a full web framework which has the disadvantages listed in the motivation section above.

Javascript web frameworks

These are probably the more compelling alternatives. The Javascript frameworks I compared against are Angular, Vue, NextJS, Fresh, Qwik, SolidJS, and Astro ( with Svelte ).

One of the most significant components of these frameworks is the frontend. We are comparing the frontends Angular, Vue, React, and Svelte. Svelte is a compiler, while the others are Virtual DOMs. This allows Svelte to be the closest to plain Javascript and have the simplest syntax for reactivity. The most significant disadvantage to Svelte is that it is new and, therefore, less popular than the other three. Overall, I think React, Vue, and Svelte will take an iced developer a similar amount of time to get to a good level of productivity, while Angular is probably worse than the other three. But Svelte's simplicity means it providesa better developer experience and higher productivity ceiling. So overall, Svelte as a frontend is better than the alternatives.

However, the React frameworks have some other compelling features. Fresh is based on Deno instead of Node, so it has first-class typescript support, no build step, and is based on the island's architecture for providing javascript only to the components that need it. A disadvantage of being based on Deno is that it is not compatible with npm packages, which leaves much less flexibility. SolidJS has excellent DOM performance. However, that is not a limiting factor for a small website. Qwik lazily loads javascript on the fly to minimize page load times. However, that is at the cost of requiring an async version of React that makes for a worse developer experience. Finally, NextJS has a massive ecosystem. However, that is not a significant advantage for a small and simple project. So none of the React frameworks have benefits that outweigh Svelte's and SvelteKit's benefits.

Finally, Astro uses the island architecture for only providing javascript to components that need it. This would significantly help the iced website's performance, mostly time to interactive. However, time to interactive is not an issue with the SvelteKit website, and Astro with Svelte also has many disadvantages. Astro is not built for Svelte, which shows in the Developer experience; it does not have the same level of tooling for Svelte as SvelteKit. Also, Astro does not provide a client-side router for fast site navigation.

So overall, SvelteKit is the best web framework for building the iced.rs website.

CSS management solution

The alternative CSS management solutions categories are CSS component libraries, CSS frameworks, CSS in JS, and CSS Utility class libraries.

CSS component libraries

A CSS component library for Svelte, like SvelteMaterialUI or Smelte takes a lot of the work and control away from the developer. They are heavily opinionated, so creating custom designs with them is extremely difficult. I think control over the website is worth more than the time a component library could save.

CSS frameworks

A CSS framework like Bootstrap or Bulma provides utility classes that are very opinionated and prebuilt. This has less design inflexibility than a component library but still makes it difficult to leave their design system and restrictions, which is not ideal. Also, Bootstrap and Bulma are inefficient because they bundle the entire library, including dead code, to the browser.

CSS Utility class libraries

A CSS utility class library like Tailwind or Windi is about as high a level as one can go without losing control. They seem intercompatible, and I only choose Tailwind because it is much more popular and has excellent documentation.

Some other alternatives are not mentioned, like SCSS and Stylized Components, but they do not solve the problem of confusing and wordy CSS.

So overall, Tailwind provides the control of pure CSS with a much faster development time and a much better developer experience.

Unresolved questions

I expect that there will be a lot of discussion about the design language of the website, some implementation details, and possibly the addition of more tools and libraries.

@13r0ck
Copy link

13r0ck commented Oct 14, 2022

Looks good!

Just a few ideas

  • because iced can render to wasm, if we are going to make a full iced webpage, I would like to see iced itself embedded on the page not just a gif at least.
  • Do we want to use a toolkit that's architecture is completely different from the iced toolkit itself?
  • Adding onto that, would we just want to look into using iced itself to build the webpage?
  • I'm not sure SEO matters much for iced at this point in time. A website that provides useful resources for devs is more important. If we can also get SEO then that is a nice bonus.

In the discord Hecrj mentioned that he doesn't want to see a lot of JavaScript on the page. I may be missing something, but i respectfuly disagree. Whatever is the easiest way to make a webpage that is actually useful for devs should take priority.

@VIEWVIEWVIEW
Copy link

Make the code box bigger. I need to scroll too much. (Only 9 out of 40+ lines are visible)

I agree with @13r0ck that the widget should be actually an iced element.

@AlistairKeiller
Copy link
Author

Thank you @13r0ck for the feedback!

  • Great idea to embed iced_web for the demo instead of a gif. I will work on integrating that.
  • I agree that it would be ideal to use a framework similar to iced, like iced_web or Elm. However, iced_web is very experimental, so building a website will be much more complex, and the final result would not be as helpful to devs. Elm is production ready; however, it does not have the tooling, libraries, and library integration that SvelteKit and the javascript ecosystem provides. Given the majority of the website is not reactive, those are extremely important. Additionally, the relatively small amount of reactivity allows that reactivity to be readable even to someone unfamiliar with Svelte's reactivity model.
  • I agree that SEO is not as important as the site's usefulness as a resource for devs. The new setup improves the lighthouse score, which reflects performance, accessibility, best practices, and SEO. The first three of these affect the experience of a dev using the site, and SEO is a bonus.

@cryptoquick
Copy link

I think dogfooding iced is important for the site, otherwise devs might get the wrong idea about what iced is capable of. In a way it almost seems duplicitous to have a site for a UI framework that can compile to wasm, but then build the site for it in something else entirely. Maybe this work can be used as inspiration to work towards. Ideally Iced will get to the same place Svelte and others are at one day. But the site doesn't have to be perfect and have all features. It should serve as a demonstration of what Rust and Iced are capable of, even if it doesn't yet have all the bells and whistles of JS frameworks.

@AlistairKeiller
Copy link
Author

AlistairKeiller commented Oct 16, 2022

@VIEWVIEWVIEW, good point on the size of the code editor. I increased it to 16 lines; how does that look?

@13r0ck and @VIEWVIEWVIEW, I added a real iced demo at https://c1c4e21a.iced-website.pages.dev/. Is that better than the gif?

Edit: I just found out that having the iced demo on the main page results in search engine indexing being entirely disabled. The iced demo also breaks after navigation to and back from another page because it is not resumable and therefore gets broken by SvelteKit's client-side router. I suggest that we have the gif on the main page as well as a link to a separate iced demo page.

@cryptoquick, iced is not designed for the web, so using iced_web for the website should not be considered akin to dogfooding. I think that iced_web would require some significant changes before it is ready for a test website; I can not find a way to load an image ( the image in the tour demo, which is designed to be iced_web compatible, does not work either ), I can not find a way to change the canvas size based on the screen size, the loading time on mobile is unusable, and iced_web uses exceptions for control flow ( which does not inherently degrade the user experience but goes to show how experimental it is ).

@cryptoquick
Copy link

@AlistairKeiller Iced works perfectly fine in the web, and always has since I've been following this project since 2019. I think iced_web is something new and different.

@hecrj
Copy link
Member

hecrj commented Oct 17, 2022

The iced website is a static site. There is no need to use technology for building dynamic web applications like Svelte or iced itself.

In the motivation, you seem to imply Zola and Bulma are coupled, but the choice of Bulma can easily be changed if it turns out to not be a good one. Also, Zola is just a static site generator and produces the HTML you want it to produce.

I'm not convinced we are assessing the current approach properly and the motivation seems to have incorrect assumptions.

@AlistairKeiller
Copy link
Author

AlistairKeiller commented Oct 24, 2022

I agree that a framework built for dynamic web applications like SvelteKit may be overkill. However, there are many components that we may want to add to the iced website which would greatly benefit from having a dynamic framework. For example, the SVG scroll animation at the bottom of tokio's website, which they used next.js to achieve. Additionally, it would be beneficial to the user experience to combine the guidebook and the main website. This would help increase the site's coherency, and allow the user to search the documentation from the main page. The majority of other large rust projects I looked at implement their docs and site in the same place. For example, Tokio, Actix, Tauri, and Yew.

Zola could allow for this, however it requires manually implementing many features necessary in a guidebook, which means higher effort and maintenance than mdBook. Also, the difficulty of reactivity in Zola means that even their guidebook is missing some basic markdown functionality, like automatically hiding the headings tag and code block copy.

Given your feedback, an option that we could use instead of SvelteKit is a documentation generator like Vitepress, Vuepress, or Docusarus; they would address all of these problems. They allow the user to embed reactive components ( Vue for Vitepress and Vuepress, and React for Docusarus ) and require very little code to maintain. I made an example website with Vitepress, which is extremely fast and surprisingly easy to create: https://iced-vitepress.pages.dev/, https://iced-vitepress.pages.dev/guide/tutorial/overview, https://github.com/AlistairKeiller/iced-vitepress.

@AlistairKeiller
Copy link
Author

AlistairKeiller commented Oct 27, 2022

Closing because I will create another RFC that can determine what the criteria for the website are.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants