Coder Social home page Coder Social logo

esbeltojs's Introduction

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
 ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.