All Projects → wildhaber → Gluebert

wildhaber / Gluebert

Licence: mit
gluebert.js is a tiny helper lazy loading DOM Elements, StyleSheets and JavaScript files using dynamic import and code splitting

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Gluebert

hyperstache
👨‍🦰 Handlebars just got a trim, alternative JS template engine, 2kb gzip
Stars: ✭ 36 (-81.44%)
Mutual labels:  mustache, handlebars
Ramhorns
Fast Mustache template engine implementation in pure Rust.
Stars: ✭ 172 (-11.34%)
Mutual labels:  handlebars, mustache
HandlebarsCookbook
A cookbook of handlebars and mustache, focus on handlebars.js , mustache.js and lightncandy usage
Stars: ✭ 20 (-89.69%)
Mutual labels:  mustache, handlebars
Handlebars
Fullest Handlebars.js templating support for Atom and Sublime Text 2 / 3. Also drives syntax colouring on Github and in Visual Studio Code. Install from: https://atom.io/packages/Handlebars and https://packagecontrol.io/packages/Handlebars.
Stars: ✭ 292 (+50.52%)
Mutual labels:  handlebars, mustache
Mikado
Mikado is the webs fastest template library for building user interfaces.
Stars: ✭ 323 (+66.49%)
Mutual labels:  handlebars, mustache
Handlebars.net
A real .NET Handlebars engine
Stars: ✭ 723 (+272.68%)
Mutual labels:  handlebars, mustache
Lightncandy
An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ),
Stars: ✭ 565 (+191.24%)
Mutual labels:  handlebars, mustache
Scriban
A fast, powerful, safe and lightweight scripting language and engine for .NET
Stars: ✭ 1,360 (+601.03%)
Mutual labels:  handlebars, mustache
Twig Bridge
Provides integration for Twig with various Symfony components.
Stars: ✭ 2,170 (+1018.56%)
Mutual labels:  twig
Lairdubois
L'Air du Bois is a Community Driven Woodworkers Sharing Platform.
Stars: ✭ 184 (-5.15%)
Mutual labels:  twig
Twig Bundle
The Twig Bundle provides configuration for using Twig in your applications.
Stars: ✭ 2,150 (+1008.25%)
Mutual labels:  twig
Inlets Pro
Secure TCP and HTTP tunnels that work anywhere
Stars: ✭ 179 (-7.73%)
Mutual labels:  mustache
Bolt
The Bolt Design System provides robust Twig and Web Component-powered UI components, reusable visual styles, and powerful tooling to help developers, designers, and content authors build, maintain, and scale best of class digital experiences.
Stars: ✭ 186 (-4.12%)
Mutual labels:  twig
Apacheexpress
Reliable Server Side Swift ✭ Make Apache great again!
Stars: ✭ 170 (-12.37%)
Mutual labels:  mustache
React Lazy Hydration
Lazy Hydration for Server Rendered React Components
Stars: ✭ 187 (-3.61%)
Mutual labels:  lazy-loading
Baumeister
👷 The aim of this project is to help you to build your things. From Bootstrap themes over static websites to single page applications.
Stars: ✭ 171 (-11.86%)
Mutual labels:  handlebars
Milk
Milk is Mustache in CoffeeScript -- great with your browser or NodeJS!
Stars: ✭ 192 (-1.03%)
Mutual labels:  mustache
Micromustache
Ⓜ An extremely fast and small sub-implementation of the {{mustache}} template engine for JavaScript
Stars: ✭ 186 (-4.12%)
Mutual labels:  mustache
Gulp Site Generator
A static site generator using Gulp
Stars: ✭ 183 (-5.67%)
Mutual labels:  handlebars
Newman Reporter Htmlextra
A HTML reporter for Postman's Command Line Runner, Newman. Includes Non Aggregated Runs broken down by Iterations, Skipped Tests, Console Logs and the handlebars helpers module for better custom templates.
Stars: ✭ 183 (-5.67%)
Mutual labels:  handlebars

gluebert.js

CircleCI Code Climate Test Coverage License MIT npm

gluebert.js === lazy load *

gluebert.js is a helper lazy loading DOM elements, StyleSheets and JavaScript files using dynamic import and code splitting.

tl;dr

  • ✂ Code Splitting and dynamic import
  • 🔭 Mutation- and IntersectionObserver
  • 📯 Observable streams by RxJS
  • 🗑 No payload and computation waste
  • 🐲 Legacy Browser Support back to IE11
  • 📚 Here is a documentation

Lazy Loading Concept

installation by package managers

via npm

npm install gluebert --save

via yarn

yarn add gluebert

Getting started by examples

git clone [email protected]:wildhaber/gluebert-getting-started.git
cd gluebert-getting-started
npm install
npm run build
npm run serve

Gluebert CLI

Build modules directly from the terminal:

npm install gluebert-cli -g

See documentation to gluebert-cli here: https://github.com/wildhaber/gluebert-cli


Get familiar with underlaying concepts

Webpack's code-splitting and dynamic import

Webpack is a module bundler that bundles your scripts and assets into one big bundle - or with some configurations it creates little code-chunks working perfectly together. Code Splitting and dynamic import are following the best practices for the HTTP/2-Standard.

An excerpt of the abstract from HTTP/2:

This specification describes an optimized expression of the semantics of the Hypertext Transfer Protocol (HTTP), referred to as HTTP version 2 (HTTP/2). HTTP/2 enables a more efficient use of network resources and a reduced perception of latency by introducing header field compression and allowing multiple concurrent exchanges on the same connection. ...

While the dynamic import concept follows a proposal from tc39 that basically allows importing ressources on runtime by import(), which returns a promise. This way you can avoid the high payload, when imports are just at the top of the file like import { SomeThing} from './some-thing', but basically, dynamic imports are a Promise translation of them.

MutationObserver and IntersectionObserver

MutationObserver are tracking changes in your DOM and lazy binding module signatures and executes them, when an element appears in the viewport using IntersectionObservers.

Observable streams by RxJS

To organize, sending and receiving Data through your application there are observable streams available provided by RxJS.

Related Concepts

Related Resource Documentation
Webpack webpack.js.org
Webpack Code Splitting webpack.js.org/guides/code-splitting/
Dynamic Import Proposal by TC39 tc39/proposal-dynamic-import
HTTP/2 RFC http2.github.io
MutationObserver developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer
IntersectionObserver developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

Installation and QuickStart

We recommend following the installation guide or if you are in a hurry,

git clone [email protected]:wildhaber/gluebert-getting-started.git
cd gluebert-getting-started
npm install
npm run build
npm run serve

Gluebert instance

Starting a gluebert instance can look like this:

import { Gluebert } from 'gluebert';

const MODULES = []; // list of module signatures to watch
const DATA = []; // list of data signatures to watch

const gluebert = new Gluebert(MODULES, DATA);

gluebert.start(); // Bootstrap your gluebert application

Module Signature

A module signature prepares loaders for everything (basically Controller and Styles) used for a certain module.

// lazy-img.module.js

import { ModuleSignature } from 'gluebert/module';

/**
 * ModuleSignature for lazy image loader
 * @type {ModuleSignature}
 */
const LAZY_IMG_MODULE = new ModuleSignature(`lazy-img`, `.c-lazy-img`)

    // Prepared controller that will be imported, as soon as a selector (e.g. '.c-lazy-img') appears
    .setImportController(
        () => import('./lazy-img.controller').then((controller) => controller.LazyImgController)
    )

    // Prepared stylesheets that will be imported, as soon as a certain element appears
    .setImportStyles(() => import('./lazy-img.styles.scss'));

export {
    LAZY_IMG_MODULE,
};

Module Controller

A module controller will be instaciated every time an actual element appears in the viewport. For the above example with a lazy loaded image, this could look like:

// lazy-img.controller.js

import { ControllerAbstract } from 'gluebert/controller';

/**
 * Class represents LazyImgController
 * @extends ControllerAbstract
 */
class LazyImgController extends ControllerAbstract {

    /**
     * creates a new LazyImgController instance
     * @param {HTMLElement} element
     * @param {DataObserver} data
     * @param {ElementBuilder} elements
     */
    constructor(element = null, data, elements, dependencies) {
        super(element, data, elements, dependencies);
        
        this._src = (typeof element.dataset.src === 'string')
            ? element.dataset.src
            : null;

        if(this._src) {
            this._lazyLoad();
        }
    }

    _lazyLoad() {
        this._element.setAttribute('src', this._src);
        this._element.addEventListener('load', () => {
            this._element.classList.add('loaded');
        });

        this._element.addEventListener('error', () => {
            this._element.parentNode.removeChild(this._element);
        });
    }

}

export {
    LazyImgController,
};

The styling example

For the sake of completion, following an example of the lazy loaded image. So it will be blurry, while not loaded:

// lazy-img.styles.scss

.c-lazy-img {

    transition: filter 0.4s;
    will-change: filter;

    &:not(.loaded) {
        filter: blur(10px);
    }
}

Inject the modules in the gluebert instance

Remember, the gluebert instance above had an empty array passed to the gluebert-instance. Let's inject the lazy-img-Module.

import { Gluebert } from 'gluebert';
import { LAZY_IMG_MODULE } from './modules/lazy-img.module';

const MODULES = [
    LAZY_IMG_MODULE,
];
const DATA = []; // list of data signatures to watch

const gluebert = new Gluebert(MODULES, DATA);

gluebert.start(); // Bootstrap your gluebert application

Assume, you have an index.html like:

<html>
    <head>
        <title>Shortcut HTML, just for Example</title>
    </head>
    <body>

        ...a lot of content...

        <img class='c-lazy-img'
            src='/a-really-micro-placeholder-image-with-ultra-low-quality.jpg'
            data-src='/the-one-and-only-lazy-loaded-image.png'>

        ...even more content...

        <script src='/app.js' async></script>
    </body>
</html>

And your image will load smoothly and lazy now. All necessary assets like styling and controller in our example will only load and execute, when the user scrolls to the image. Otherwise - no payload or computation except for the minimal signature will happen.

Cool, isn't it?

Prevent FOUC

To avoid a Flash of Unstyled Content (FOUC), there are techniques like the Critical Path CSS.

Reduce Network Requests and Offline Support

And to cache the import request, even when a user is offline - read more about Offline First ServiceWorkers.

This is just the core peak of gluebert.js

Learn more about Topics like:

Contribute

Everyone is very welcome to contribute, either reporting issues (Bugs, Feature-Requests, Questions etc.) or develop own features, improvements or bugfixes.

For everything you do, assume positive intent behind anything. Don't blame anyone for anything. We are one big family of developers that wants to improve ourselve as well as the way we deal with technologies.

Reporting issues

Please be as discriptive as possible, include a brief description of what your topic is about and include as much details as possible so anyone can understand your concern.

Ideal content:

  • Description
  • Including Screenshots
  • Providing links to similar examples
  • Add code examples / even pseudo code will help
  • Add environment and browser details if you report bugs

Development

First, create your own fork of this repository and develop within your fork, from there you can make pull requests against the main repostiory.

Documentation, how to fork a repository: https://help.github.com/articles/fork-a-repo/#fork-an-example-repository

# cloning your fork
git clone [email protected]:<your-github-username>/gluebert.git

Create branches for every feature or bugfix and keep separation of concerns, so don't develop 5 different features in one branch. Use a separate branch for every feature.

# crate a branch like this
git checkout -b feature/<my-initials>-description-of-your-feature

Next, do an npm install on the root folder. So you have all necessary dependencies installed.

In the main src/-folder are all necessary files that runs gluebert. You can run npm run build or npm run build:watch to generate the necessary files in the dist-folder.

To have an environment ready where everything is prepared, you can explore the content under documentation, its the actual website that is rendered from this folder. Running and building the documentation needs to have hugo installed. Hugo is a static site generator that runs with go. You can install it by brew:

brew install hugo

After you have hugo installed, head to /documentation/themes/gluebert/ and do an npm install there. So you have a proper development environment.

There you have the commands like npm run build:dev-command to build, or even more convenient npm run build:watch watching and rebuilding on changes.

in a separate terminal window you can head to documentation/ and run hugo server --watch --disableLiveReload and you get your server up and running at http://localhost:1313.

In a short (expecting you have installed hugo already):

# install dependencies
# cd gluebert/
npm install
cd documentation/themes/gluebert/
npm install
npm run build:watch

# open a separate terminal window
cd documentation/
hugo server --watch --disableLiveReload

It's clearly not a perfect development environment yet. You are more than welcome to give us any feedback :-)

Happy coding, and thanks for any contribution 👍

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].