Svelte Razor Views
darren
0 reactions 2022-04-02
Hi and welcome.
This article is about adding a nice UI experience to an ASP.NET Core MVC app using Svelte components.
What’s the problem?
An ASP.NET Core MVC Web app runs on a server. It combines data from a Model with an HTML template language (Razor View) to generate pages to deliver to the user’s browser.
Once the web page lands in the user’s browser, it’s up to front-end technologies to give a rich experience to the user. Design and interactivity are achieved through the combination of HTML, CSS, and JavaScript.
ASP.NET Core web app templates have JQuery and Bootstrap installed by default to help with this. These are “battle-tested” technologies, but there are advancements in front-end frameworks that can provide a better experience for developers and end-users.
Svelte
Svelte is newer amongst the JavaScript technologies but is currently my pick.
Svelte components are compiled to JavaScript and then can be included in Razor Views. While it is still JavaScript at the end that is running in the user’s browser, Svelte’s abstractions make it easier to craft interactive and animated components.
Check out svelte.dev for many great examples
In this example, we are building Custom Elements with Svelte to allow the components to be added to our Razor page. This is using Web Components technology which does have some drawbacks, see links below for some issues and workarounds.
Svelte docs for custom elements
Custom elements in svelte Geoff Rich for CSS Tricks
Common pitfalls and workarounds, Kyohei on dev.to
The Project
- Begin with a bare-bones default ASP.NET Core MVC project.
- Add Node packages for the capability to build Svelte components into JavaScript files.
- Add the Rollup config file to configure how your Svelte Components are built
- Add the rollup build command to package.json
- Add a command to the
.csproj
file to compile the Svelte components into JavaScript each time the ASP.NET Core project is built. - Create some Svelte components
- Reference the components in Razor Views by including a
<script>
tag that links to the compiled JavaScript file.
This project is based on code by Khalid Abuhakmeh. Here is his original article
Quick Setup
The fastest way to see this code running on your machine is to download my project from GitHub, install the dependencies and run the project.
Browse in your terminal to a folder you’d like to install this project and execute the following commands:
npx degit darrengrafton/svelterazorviews wise-reader-svelte-razor-views
cd wise-reader-svelte-razor-views/svelterazorviews
npm install
dotnet run
to run these commands, you need degit, Node JS, and .NET 6.0 SDK installed
Full Step by Step
If you want to replicate this setup, here are the steps to follow.
1. Begin with a bare-bones default ASP.NET Core MVC project.
Navigate in your terminal to the folder you want to set up this project in and run:
dotnet new mvc -n my-svelte-razor-view
.NET 6.0 SDK is required
2. Add Node packages for the capability to build Svelte components into JavaScript files.
cd my-svelte-razor-view
npm install @rollup/plugin-node-resolve@11.2.0 rollup@2.39.0 rollup-plugin-svelte@7.1.0 svelte@3.46.6
I have version numbers specified in the command above because I’ve tested with these versions
3. Add the Rollup config file to configure how your Svelte Components are built
In the project folder, add a file named “rollup.config.js” with the content below:
import svelte from "rollup-plugin-svelte";
import resolve from "@rollup/plugin-node-resolve";
export default {
// The site js file where we will reference our svelte components
input: "wwwroot/js/site.js",
output: {
// The destination for our bundled JavaScript
file: "wwwroot/js/build/bundle.js",
// Our bundle will be an Immediately-Invoked Function Expression
format: "iife",
// The IIFE return value will be assigned into a variable called `app`
name: "app",
},
plugins: [
svelte({
// Tell the svelte plugin where our svelte files are located
include: "wwwroot/**/*.svelte",
emitCss: false,
compilerOptions: {
customElement: true,
},
}),
// Tell any third-party plugins that we're building for the browser
resolve({ browser: true }),
],
};
Your folder structure should look like this:
4. Add the rollup build command to package.json
Add this scripts section to the package.json so that “npm run build” will run the following command
"scripts": {
"build": "rollup -c rollup.config.js"
},
5. Add a command to the my-svelte-mvc.csproj
file to compile the Svelte components into JavaScript each time the ASP.NET Core project is built.
<Target Name="Rollup" BeforeTargets="Build">
<Exec Command="npm run build" />
</Target>
6. Create a Svelte component
Let’s use a Svelte Hello World example:
in the wwwroot/js folder, create a file named “Hello.svelte” with the following content:
<svelte:options tag="svelte-hello" />
<script>
export let name = 'world';
</script>
<h1>Hello {name}!</h1>
Note two small changes from the example on Svelte’s website.
- We added the svelte:options tab to specify the tag name to reference the component in the Razor View.
- We added
export
before let name so that we can pass a name into the component
Modify the site.js file to reference our Svelte component:
import Hello from "./Hello.svelte";
7. Reference the component in a Razor Views by including a <script>
tag that links to the compiled JavaScript file.
Open the “Index.cshtml” file in the View/Home folder. Add the following to this file:
<svelte-hello name="Svelte"></svelte-hello>
<script src="~/js/build/bundle.js" asp-append-version="true"></script>
Note: I’m running into an issue with having two svelte components setup with this system side by side. So far wrapping them in divs if side by side works fine
In a full solution, you’ll want to move the script tag into a section of the page with your other script imports
8. That’s it. Now run the project
Run this command to run your project and see your svelte component in action!
dotnet run watch
Your browser should open and look something like this:
Congratulations! Now I suggest grabbing some fun examples from Svelte’s website to try out some of the interactivity and animation.
Next Steps and Questions
This is a simple proof of concept that raises a lot of questions for me
- What are the limits of using Svelte Web Components? Is there a way to include the Svelte in Razor without web components?
- Can I set up Visual Studio to rebuild the svelte components and hot reload the site when the svelte or razor files are saved? This is a killer feature in new front-end frameworks and it’s much less fun to code without it.
- Any unexpected behavior when posting to or fetching from an ASP.NET Core Controller from a svelte component?
- Any benefit to using Vite instead of Rollup?
- When is it worth it to try to split the svelte components into separate JavaScript files to limit file size?
- What bits of Razor will stop working if I drop the JQuery entirely?
I’m planning to write some follow-up posts as I investigate further.
Resources
- As mentioned above, a similar article by Khalid Abuhakmeh
- Log rocket blog on svelte web components coverting drawbacks
- A more complete template for integrating Svelte with Razor
- Adding svelte to an existing website, without web components
- Mozilla tutorial on setting up svelte
- ThisDot article about web components with Svelte