Fun with Svelte and uibuilder

After a recent announcement about the use of Svelte, it looked interesting enough to see how easy it might be to use with uibuilder.

As it happens - pretty easy :grin:

  1. Create a new uibuilder instance and change the url to svelte (or whatever you want). Click on Deploy.

  2. Install the default svelte template to ~/.node-red/uibuilder/svelte with the command npx degit sveltejs/template ~/.node-red/uibuilder/svelte

  3. Make some very minor changes to the rollup config: Just change lines 42 and 72 to point to the dist folder instead of public.

  4. Rename the public folder to dist and remove the build sub-folder (it gets recreated).

Note that you will need to restart node-red at some point now - sorry about that, it is the way that uibuilder currently decides whether to serve up the src or dist folder. I'll fix that in the future.

  1. Change the build/index.html - noting the leading . or .. added to the various resources:
<!DOCTYPE html><html lang="en"><head>
	<meta charset='utf-8'>
	<meta name='viewport' content='width=device-width,initial-scale=1'>

	<title>Svelte app</title>

	<link rel='icon' type='image/png' href='./favicon.png'>
	<link rel='stylesheet' href='./global.css'>
	<link rel='stylesheet' href='./build/bundle.css'>

    <script defer src="../uibuilder/vendor/socket.io/socket.io.js"></script>
    <script defer src="./uibuilderfe.js"></script> <!-- dev version -->
	<script defer src='./build/bundle.js'></script>
</head><body>
</body></html>

And in App.svelte:

<script>

    import { onMount } from 'svelte';
    onMount(() => {
        uibuilder.start()

        uibuilder.onChange('msg', function(msg){
            console.info('msg received from Node-RED server:', msg)
            nrMsg = msg.payload
        })

    })

    let myGreeting = 'Hello there!'
    let nrMsg = ''
</script>

<h1>Svelte + uibuilder</h1>
<p>{myGreeting}</p>
<button on:click={uibuilder.eventSend} data-greeting="{myGreeting}" data-something="this is something">
	Click Me
</button>
<pre>{nrMsg}</pre>
  1. cd ~/.node-red/uibuilder/svelte && npm install && npm run dev

    Note that the dev process creates its own web server but you should ignore that.

  2. Now load the uibuilder page with http://127.0.0.1:1880/svelte/ (or wherever yours ends up)

    Marvel at the amazing dynamic, data-driven web app you just made!


OK, so not the most amazing thing. But lets note a couple of important points.

  • Make a change to the text in the App.svelte page and save it - notice anything on your web page?

    Yup, it changed without you having to reload it! Just like Svelte's own dev server :grin:

  • Attach a debug node to the output of your uibuilder node. Make sure it is set to show the whole msg object. Now click on the button on your page. Notice that you get a message just by clicking the button, no code required (other than the HTML for the button itself).

    That uses the new eventSend function in uibuilder v3.2

    Note how the data-xxxx attributes are sent back to node-red in the payload, one of which is dynamic thanks to Svelte. Also note that the msg.uibDomEvent.sourceId in node-red contains the text of the button. Try adding an id attribute to the button to see what difference it makes.

  • Send a msg to the uibuilder node and note how the payload appears on the page

    5 lines of code in total to do that :grin:

19 lines of actual code for a simple, data-driven web page. Not too bad I think.


When I get a chance, I will create a GitHub repository with a uibuilder-specific Svelte template to get rid of some of the above steps.

I will also be adding some features to uibuilder in a future release that will make installing your own (or anyone elses) templates to a uibuilder instance. Also, there will be an install and a build button. So that most of the above steps will be reduced to a couple of clicks. These changes will help anyone who needs a build step for their web app, not just for Svelte users.

3 Likes