Melody Documentation
  • Why Melody?
  • Quickstart
    • What is Melody?
    • Tutorial
    • Installation
  • Templates
    • Twig
    • Mounting Components
    • Keys and Loops
    • Attributes
    • CSS Classes
    • Inline Styles
    • Refs
    • CSS Modules
  • Melody-Streams
    • Basic concept
    • A Step-by-Step Walkthrough
  • MELODY-STREAMS API
    • createComponent
    • The component function
  • melody-hooks
    • Overview
    • Rules of Hooks
    • Event Handling
    • Separation of Concerns
  • melody-hooks API
    • useState
    • useAtom
    • useEffect
    • useRef
    • useCallback
    • useMemo
    • useReducer
    • usePrevious
  • melody-component
    • Overview
  • melody-hoc
    • Overview
Powered by GitBook
On this page
  • Syntax overview
  • Variable Components
  • Loading Components on Demand
  • Dynamic paths

Was this helpful?

  1. Templates

Mounting Components

The mount statement uses a very similar syntax to the standard Twig include statement.

Syntax overview

{% mount "./Foo" as "foo" with props %}

Let's take a look at the individual parts that make up the mount statement.

Here, "./Foo" represents a path to the component you want to mount. Any path is valid, provided that it can be resolved by Webpack or similar tools to a JavaScript module that exports a Melody component as its default export.

"foo" is the key of the component. Providing a key is usually optional but strongly recommended if your component is mounted close to a conditional expression or within a loop. Keys must be unique in the parent DOM node. Melody limits the format of the key to be a string but you can use embedded literals to include expressions in it. For example "foo_#{ index }" would also be a valid key.

Finally, props should be an object that is made available to the mounted component. If you're using the melody-hooks API, this object will be the argument to the state hook function.

Variable Components

In addition to accepting a plain path the mount statement also allows you to specify a component directly. Note, however, that due to limitations Melody can't resolve dynamic paths for immediately mounted components. If you are looking for a way to achieve that, please look at dynamic paths.

<div class="home">
    <h1 class="title">
        {{ message }}
    </h1>
    {% mount Counter with { count: 5 } %}
</div>
import { createComponent } from 'melody-hooks';
import template from './index.twig';
import Counter from '../counter';

function useAppState(props) {
    return {
        message: props.message,
        Counter
    };
}

export default createComponent(useAppState, template);

While useful, this feature should be used with care. Melody works best if you manage to split state and UI logic from each other.

Loading Components on Demand

This is feature will be available starting with Melody 1.2.0.

When building complex applications, it is often helpful to be able to load parts of them asynchronously as they are needed. Melody supports this use case through async component mounts.

<div>
    {% mount async './counter'
            as "counter"
            with { count: 5 }
            delay placeholder by 100ms
    %}
        <div class="placeholder">
            We're loading the counter, please stay patient...
        </div>
    {% catch error %}
        An error occured while loading the Counter component.
        <pre style="error">{{ error }}</pre>
    {% endmount %}
</div>

The above example will asynchronously load the counter component as the template is rendered. It'll show nothing for 100 milliseconds (delay placeholder by 100ms) and then, if the Counter component has still not finished loading, it'll show the placeholder content ("We're loading the counter..."). In case the Counter component finished loading before the 100 milliseconds are over, it will be displayed immediately and the placeholder will never show. The delay placeholder by $time part is optional and, when not specified, Melody will decide when to show the placeholder. At the moment that is configured to be immediately; however, we reserve the right to modify that behaviour and you should assume that it'll be shown whenever Melody thinks is best.

For readability reasons the delay is specified explicitly as either milliseconds or seconds. You must specify the unit. Values such as 100ms, 200ms, 1s, 2s are all valid.

If an error occurs while loading the component, the content after the {% catch error %} will be rendered. error is a variable name that becomes available within that block. You are free to choose whatever name you like best. The catch clause is optional and you don't have to specify it - even though we strongly recommend that you do.

Melody requires you to specify placeholder content that can be shown during the loading of the actual component.

Why should I delay the placeholder?

User experience research indicates that users will perceive a response time of up to 100 milliseconds to be instantaneous. So if your users have a lot of bandwidth and processing power or the chunk containing your async component is really small, then there's a good chance that you could offer your users a feeling of instantaneous performance by not showing a loading animation.

Source: https://www.nngroup.com/articles/response-times-3-important-limits/

Why is a delay of 100 milliseconds not hardcoded?

Because Melody doesn't know your user base nor the size of the chunk of the component you're loading. There's a chance that all of your chunks will be huge and that you really want to display the placeholder immediately because you know it'll take a while to load things. The perception of users might also change over time or even across markets or the type of application you're building. At the moment, we don't think a hardcoded value would be valuable.

What about prefetching?

You might wonder about options to improve the performance of components that are loaded on demand and Melody - with the help of Webpack - has you covered. Melody embeds the necessary comments so that Webpack will use the browsers native prefetching logic to preload asynchronous components when the browser has sufficient bandwidth and processing capabilities available.

Thanks to that, you won't have to think too much about performance implications of loading components asynchronously, but can instead focus on building amazing applications.

Dynamic paths

When using asynchronously mounted components, Melody allows you to use dynamic paths.

<section class="item__details">
    {% for part in parts %}
        {% mount async "./parts/#{part}" as "part-#{part}" %}
            {% include "./loading/part.twig" %}
        {% catch error %}
            {% include "./loading/error.twig" %}
        {% endmount %}
    {% endfor %}
</section>

This way you won't have to know the entire name of the component.

When bundling with Webpack this will force Webpack to create chunks for all possible imports. i.e. if you would try to load "#{part}" Webpack would need to use every possible path on your computer as an entry point to another chunk. Your build time would explode.

Therefore, you need to make sure that you keep the dynamic part of the file path as small as possible.

Please be careful and please observe your build time to ensure you're not making accidental mistakes here.

PreviousTwigNextKeys and Loops

Last updated 5 years ago

Was this helpful?