npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

esbelto

v2.1.4

Published

View engine for Express with a svelte-like syntax

Downloads

8

Readme

esbeltoJS

A simple view engine for Express with a Svelte-like syntax

How to use

npm install esbelto
const express = require('express');
const esbelto = require('esbelto');

const app = express();

/*You can use 'svelte', 'esb', or any other extension
 *just make sure to configure your editor to treat it as a .svelte file
 */
app.engine('svelte', esbelto.express);
app.set('view engine', 'svelte');

Passing values

app.get('/', (req, res) => {
  res.render('index', { user: { name: "John" } });
});

index.svelte:

<script id="esbelto">
  let { user } = getVariables();
</script>

<head>
  <title>Esbelto</title>
</head>

<body>
  <h1>Welcome {user.name}!</h1>
</body>

Welcome John


{#if}, {:else} and {:else if}

app.get('/if', (req, res) => {
  res.render('if', { 
    user: {
      isOwner: false,
      isAdmin: true
    }
  });
});

if.svelte:

{#if user.isOwner}
  <button>Owner dashboard</button>
{:else if user.isAdmin}
  <button>Admin dashboard</button>
{:else}
  <button>User dashboard</button>
{/if}

If example


{#each}

app.get('/each', (req, res) => {
  res.render('each', {
    books: [
      "The Hitchhiker's Guide to the Galaxy",
      "The Restaurant at the End of the Universe",
      "Life, the Universe and Everything",
      "So Long, and Thanks for All the Fish",
      "Mostly Harmless"
    ]
  });
});

each.svelte:

{#each books as book}
  <h2>{book}</h2>
{/each}
<br>
{#each books as book, idx}
  <h2>{idx+1}° -> {book}</h2>
{/each}

Each example


Escaping {@html}

Just as in Svelte, Esbelto also escapes HTML by default, if you do not want to escape it, just add a @html after the {

app.get('/escaping', function (req, res) {
  res.render('escaping', {
    title: '<b>This is the title</b>'
  });
});

escaping.svelte:

<p>{title}</p>
<p>{@html title}</p>

Escaping example


include and includeScript

Most editors for .svelte files (like Svelte's extension for VSCode) will warn you if you have more than one <script> tag in your code. This isn't a problem for Esbelto, but, if you want to avoid that warning, you can use the includeScript method(You can use either an string with the script's src or an object with each desired property of the <script> tag)

include.svelte:

<script id="esbelto">
  let include = getInclude();
</script>

<head>
  {include('./head.svelte', {title: "Testing include", scripts: ['js/main.js']})}
</head>

<body>
  <span class='text-success ms-1'>Hello World!</span>
</body>  

head.svelte:

<script id="esbelto">
  let includeScript = getIncludeScript();
  let { title, scripts } = getVariables();
</script>

<title>{title}</title>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">

{includeScript({
  src: "https://code.jquery.com/jquery-3.6.0.min.js",
  integrity: "sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=",
  crossorigin: "anonymous"
})}

{#if scripts}
  {#each scripts as script}
    {includeScript(script)}
  {/each}
{/if}

Include example


config

You can tweak some settings by using the esbelto.config() method, although it's not required

const esbelto = require('./esbelto');
const express = require('express');

const app = express();

//These are the defaults
esbelto.config({
  htmlStartTag: '<!DOCTYPE html>\n<html>\n',
  htmlEndTag: '\n</html>',
  cacheCompileds: true,
  cacheSettings: {
    storeOnDisk: false,
    recompileOnChange: true
});

app.engine('svelte', esbelto.express);
app.set('view engine', 'svelte');
  • cacheCompiled -> makes every render after the 1st faster, as it does not have to recompile the template every request
  • storeOnDisk -> setting this to true will make esbelto store the compiled template in a file in the same folder as the template, as opposed to in memory, in my tests, this option was actually slower than cacheCompiled: false, but it could be useful when working with some really big templates
  • recompileOnChange -> checks the last modified date of the template, and recompiles it if it was changed, really useful during development, but I recommend setting this to false in production, as it makes the render a bit slower, this option is always true when using storeOnDisk: true, and, therefore, ignored

Cache settings performance comparisons

This was the template used for these tests: user-dashboard.svelte:

<script id="esbelto">
  let include = getInclude();
  let { user } = getVariables();
</script>

<head>
  {include('./partials/head.svelte', {title: "User Dashboard"})}
</head>

<body>
  <h1>{user.name}</h1>
  <h3>Age: {user.age}</h3>
  <h4>Children:</h4>
  <ul>
  {#each user.children as child}
    <li class="{child.gender == 'M' ? 'blue' : 'pink'}">{child.name} - {child.age}</li>
  {/each}
  </ul>
  {#if user.isAdmin || user.isOwner}
    <span>Some administrative data</span>
    <br>
    {#if user.isOwner}
      <button>Go to owner panel</button>
    {:else if user.isAdmin}
      <button>Go to admin panel</button>
    {/if}
  {/if}
</body>

/partials/head.svelte:

<script id="esbelto">
  let { title } = getVariables();
</script>

<title>{title}</title>
<link rel="stylesheet" href="/css/style.css">

Data used:

{ 
  "user": {
    "name": "John Doe",
    "age": 42,
    "gender": "M",
    "isAdmin": true,
    "children": [
      {
        "name": "John Doe Jr",
        "gender": "M",
        "age": 11
      },
      {
        "name": "Jane Doe",
        "gender": "F",
        "age": 19
      }
    ]
  }
}
Results:
Settings:  { cacheCompileds: false }

Rendering 1000 times:

First render: 2.3007ms
Average of all renders but the first: 0.2948488488488488ms
Total time elapsed 296.8547ms

--------------------------
Settings:  { cacheCompileds: true } //Default

Rendering 1000 times:

First render: 3.2604ms
Average of all renders but the first: 0.17305155155155155ms
Total time elapsed 176.1389ms

--------------------------
Settings:  { cacheCompileds: true, cacheSettings: { recompileOnChange: false } }

Rendering 1000 times:

First render: 1.8947ms
Average of all renders but the first: 0.008698698698698699ms
Total time elapsed 10.5847ms

--------------------------
Settings:  { cacheCompileds: true, cacheSettings: { storeOnDisk: true } }

Rendering 1000 times:

First render: 1.7583ms
Average of all renders but the first: 0.6899459459459459ms
Total time elapsed 691.0143ms

Beware that the difference between caching and not caching will be greatly bigger with more complex templates


Benchmark with other view engines

This is not by any means official, just a quick test I made forking baryshev's benchmark and adding esbelto to it, full results available at Levyks/template-benchmark

Rendering 100000 templates:

esbeltoJS
 Escaped   : 1334ms
 Unescaped : 39ms
 Total     : 1373ms

EJS
 Escaped   : 3090ms
 Unescaped : 1443ms
 Total     : 4533ms

EJS without `with`
 Escaped   : 1288ms
 Unescaped : 50ms
 Total     : 1338ms

Pug
 Escaped   : 4063ms
 Unescaped : 47ms
 Total     : 4110ms

Pug without `with`
 Escaped   : 3594ms
 Unescaped : 27ms
 Total     : 3621ms
 ...