Comparing Svelte with Nuxt and Vue

Ryan Weal
Published 2021-04-13

Now that I have moved this blog to Svelte (currently generated using Sapper) I am feeling pretty good about using Svelte for future projects. There are a few things I really enjoy about Svelte that I initially struggled to learn in Vue.

First, some background: I have been a developer for many years now but I was mostly doing PHP until a few years ago. I have been exposed to JavaScript for decades. I just wasn't very good at JavaScript for most of that time and for most of that time I have been calling myself a back-end programmer, but lately obviously I am working on the front-end again.

So with that being said... I dove back into JavaScript at a very complex time. The time when moment.js was in every project. When webpack was preferred for everything. When ES modules were just becoming a thing. I didn't even know how to include files beyond the classical script tag technique. I learned a lot when I was getting into Vue. Learning Svelte has been like a top-up to my knowledge of current JavaScript practices.

No window.*

In Vue.js and therefore also Nuxt, you do not always have access to the window object, or any objects outside of Vue, during parts of the Vue lifecycle.

This leads to many situations where you have to architect around the framework, or to simply defer those actions until mounted() which is when you will have access to the outside world. This can get quite complex when you are trying to statically render and have very specific requirements about when you want things to load.

In Svelte, it seems you just do the things you want. Framework doesn't care. Whether that is good or bad is up for you to decide.

There's a module for that

In the Nuxt community there seems to be a trend to solve the above issue (and other issues) by creating wrapper modules.

Wrapper modules distance you from the task at hand. What if you decided to re-implement some Vue code in Svelte? Do you know the API or just the wrapper module?

For the years I was working with Drupal I thought that modules were a good thing, and in many cases they are, but I think wrapper modules are another story. A wrapper module is when some random person (generally speaking) picks up a popular project and makes a wrapper module so it is "easier" to install or to use within your project.

I find that wrapper modules often get WAY out of date. For this reason they can be a huge security risk because it is usually not the original author doing the packaging, but some random person who may or may not care to keep up with the upstream/original maintainers.

This isn't really a Vue or Nuxt-specific problem but I see this issue creeping into many of my Nuxt projects. You can avoid this issue if you resist the urge to give preference to a community module simply because it exists (this is a very common policy when doing Drupal projects).

For similar reasons it is important not to choose a framework "because" it has so many modules. Saying that there are lots of modules does not address how many of them are actually useful for what you are trying to do. It could make things harder. I am of the belief that less is more when it comes to modules.

My experience of doing more JavaScript at work caused me to reject most wrapper modules in favor of working directly with a library. I suspect it has saved me countless hours in debugging time. I have applied the same philosophy to my legacy projects in other languages as well. Use what is fresh. Easily be able to re-implement the same concepts and code when switching frameworks without relying on quirky and/or stale wrappers. It will make your life as a developer better.

Loading things in the right order

What happens if you write code for, let's say, Google Maps. Let's say you do lots of custom code.

Your code runs fast, sometimes so fast that Google Maps hasn't loaded yet! What happens then? You could use a wrapper module for Google Maps, but why when you already have the latest version running?

I found out that in Svelte there is an on:load parameter you can use when adding any script tag, which will trigger a custom function. This function can do whatever you want! What a dream!

It got me to thinking, this problem has got to be trivial in Nuxt also, but why have I not found the solution yet?

The solution, of course, was easy: use vue-meta's callback option when adding a script tag. In Nuxt, vue-meta is implemented as the head() method. It works pretty much the same as Svelte and it does have access to the component's this object so you can use it to make changes to data(). Wonderful.

This particular thing made me realize that learning different frameworks is a really great way to increase your knowledge of the frameworks you already know. Seeing how other people do things really sheds light on how you can improve your applications with very simple adjustments.

Statically generating pages: what is going on?

Nuxt likes to abstract away a lot of the API-related business that you want to do with the site. It is a Good Thing™ but I find it confusing at times.

When I started using Svelte it all became painfully obvious to me. The generate process starts up a webserver, which serves dynamic pages, and then it literally downloads the output from that temporary website. I should have understood this when using Nuxt... and I did to a certain extent... but Sapper's bundling process made it painfully obvious as I had to write code for both of the contexts. It forced me to better acknowledge the separation of build-time vs. run-time code.

This helped me overcome a lot of weird bugs and mysteries that I never fully understood until working with Svelte.

These days Nuxt has a wonderful static generation system that allows for different API URLs for build-time and for run-time (in static mode). This is a huge help for static sites and for building within Docker, when you may not have the same API URL as in production. Svelte helped me to understand the build context better so I'm much less confused when I don't get what I expect out of Nuxt's generate process.

Running in "SSR" mode vs. Nginx webserver config

Having come from the world of content management systems I generally dislike the idea that the front-end code should be running on the server for every page request. I would much rather do a build and not have the back-end exposed to the public at all. For smaller sites it makes maintenance much easier.

Many people like to run Nuxt on the server rather than generate static pages. I find this a bit shocking honestly, but to each their own!

Nuxt handles both SSR and static cases well but some modules and/or plugins may only work in the SSR context, so that is something to be aware of.

Most of the modules that will not run in SSR mode are for doing things that you could handle on the webserver level. I have had to brush-up my skills on doing advanced Nginx configuration alongside my JavaScript adventures. I have been using Nginx for a long time and it has proven itself to be capable of some crazy configurations that I never would have ever thought possible.

Svelte proved to me that Nuxt's wide variety of configuration options is great for doing static-only sites but also having support for mixed-mode sites that try to hydrate after pre-rendering is a great option. Knowing that SSR is available as a fallback means I know I can adapt to any situation if/when things need to scale in ways I had not initially planned for.

Conclusion

Reading this you might think I am now all-in with Svelte and that Nuxt (and Vue) are therefore dead to me but that is not the case at all!

Learning Svelte has reaffirmed why I started using Nuxt and Vue in the first place. It also has me thinking about how I can better architect apps using Nuxt. I now have a better system for evaluating modules and more knowledge on how to keep things organized for long-term maintenance. Overall it was a great learning experience.

I will continue to use both Svelte and Nuxt in the future. I will decide which to use on a per-project basis and I will have some well-informed opinions on both when going into a project evaluation.

Thanks for Reading!
Ryan Weal (LinkedIn)
🍪 ☕
Send a comment 💬
Published by Kafei Interactive