It's been a while since I touched this site. Since it acts as my portfolio and I'm nearing graduation, I figured I should revisit it and give it a touch up. I haven't described how it works and it did take a while for me to remember, so if at least for myself, I'm writing about how the site is setup.
At it's core, the site depends on only a few pieces:
However, there are quite a few packages used for optimization and a significant amount of homemade library code.
SvelteKit was chosen de facto by the choice of Svelte. It shows great care for optimization and tries to keep itself invisible. The features this site notably and extensively uses are:
- single page app
- SPA
- If the client supports JS and navigates to another page, the current page is rewritten to avoid a full-page repaint. The repaint can be seen as the loading circle in a browser tab and the subsequent flash as the page renders.
- prefetching
- Extending from SPA, if the mouse hovers over a link to another page, the content is fetched before the mouse is clicked. This reduces the apparent page load time for a better user-experience. You can see the requests happen in your web browser's developer tools, under the networking tab. McMaster-Carr is a notably-large company which does this.
- server-side rendering
- SSR
- The grand majority of JS on this site is run before serving a page to the client. This site is almost entirely useable without JS, but naturally the SPA features are disabled.
- prerendering
- Extending from SSR, the server-side JS need only be run once to generate the files served to the user.
Prerendering is possible for this site since there is no backend, and it reduces the resources needed to run the site.
This is done using
@sveltejs/adapter-static. - image optimization
- As part of prerendering, images are re-rendered into many formats with differing sizes and qualities to minimize the size of the image sent to the client.
This may be possible without SvelteKit as the functionality is actually afforded by a Vite plugin
(
@sveltejs/enhanced-img), but the plugin is part of the SvelteKit monorepo. - precompression
- The files resulting from prerendering are subject to GZIP and Brotli compression. This further reduces the resources needed to run the site.
Svelte
2
Svelte was chosen largely because I had a class which required that we use it, to visualize data using D3.js. I looked at some others but did not go with them:
React: I did not like the JSX syntax.
Angular: I liked that the syntax was HTML-dominant, but I still found some parts odd.
Vue: I did not look too hard, but it looked similar to Svelte. However, I already had experience with Svelte.
Worth noting is that I
PostCSS
3
PostCSS was chosen rather late into site development; for most of the site's development and still now, I was hand-write the CSS.
I considered Tailwind because it was all the rage in my circles, but I don't like that 1) it causes element class attributes to become very long and 2) it encourages the use of components over native HTML elements.
My current use of PostCSS is very minimal but admittedly contains:
-
$<name>: <value>; forloops:@for $<name> from <low> to <high> (by <step>)? { <body> }-
@each $<name> in (<arg>),+ { <body> } -
@define-mixin <name> ($<arg>(: <default>)?),+ { <body> /** can use `@mixin-content;` to use an object passed as last argument of mix-in */ } Preset Env , which converts new or unstable CSS into CSS+JS which works on all modern browsers.
A few “small” packages are also used by this site for the sake of optimization. They are:
cssnanoto reduce size of CSS sent to clients, layers atop PostCSS.vite-plugin-image-optimizerusingsvgoto strip unneeded data from SVGs. I like keeping my SVGs in Inkscape format, which is naturally unnecessary data for a website.
The rest of the site is made by me. I have particular design visions so, even though there are component libraries, I did not choose to use them.
You may have noticed the table of contents to the right.
Similarly, when you click on a heading or figure, the URL obtains a hash of expected name.
Both features are automatically supplied by a tree which is initialized at the beginning of each page, and to which components may
In the site gallery, you can click on images to provide their descriptions and a link to the full-sized image.
I wanted the main focus to be the image, but to have some ability to convey image meaning and context.
The implementation entails a checkbox which spans the full image size with the modal as a child.
Upon the checkbox becoming checked, the checkbox becomes “visible” (blurs the background).
Further, the modal transitions from display: none, allowing the user to highlight text and click the full-size link.
If the modal weren't display: none, the user would be clicking on the invisible modal rather than the checkbox,
leading to a frusterating or impossible website use.
I've written this feature as a component, so very little overhead needed per-image in source code to facilitate it.
Further, with SvelteKit prerendering and the checkbox implementation, this works even if the client has JS disabled.