DEV Community

Cover image for Ready to use Progressive Web App template
{Gene}
{Gene}

Posted on • Updated on • Originally published at glabs.it

 

Ready to use Progressive Web App template


Though the topic covered on this post might still be actual, this content referrers to an older version of zuix.js library. See zuix.js website for up-to-date documentation.


It was supposed to be just part of a series of examples and tutorials, but it turned out to be something good to share as a new open-source product.
So, if you did read my previous posts you can see the pattern that brought me to the creation of this Progressive Web App template:

GitHub logo zuixjs / zuix-html-pwa

Progressive Web App template with a responsive, touch-first layout.

zuix-html-pwa

A Progressive Web App template with a responsive layout and mobile app look & feel.

This template is built with just HTML, JavaScript and CSS so that it can be eventually integrated with your favourite development environment and build tools.

Features

  • Progressive Web App
  • Responsive touch-first layout with
    • collapsing header/footer
    • drawer layout (side menu panel)
    • example news list adapter with lazy-loaded items
  • Modular and component-based structure using zUIx.js
  • In-browser bundler: can pack all resources in a single file and boost-up loading speed
  • PWA LightHouse score 98/100

LightHouse Report

Demo Website

https://zuixjs.github.io/zuix-html-pwa

How to use this template

The ./source folder contains the development version of the website, while the ./docs folder the production bundled version.

Basic usage

If you have Node.js installed, for a quick setup you can use the integrated web server which will serve files from the ./source folder.
Install the development dependencies with npm install and…

Looks like a real mobile app with the plus of a responsive layout that works well both on a small screen (phone) or a desktop/tablet screen.

Those familiar with Android and Material design will definitely notice some similarities with Google products:

  • DrawerLayout for the side menu panel
  • Collapsing header/footer bars synchronized with page scrolling
  • Tabs with ViewPager used for navigating through sections of the home page
  • Context Menu used for displaying news item options

These components only implement the interaction logic and the visual feedback (animations), so the developer can fill in the structure with content using any UI framework or just with plain HTML and CSS.

Usually my approach is the latter as I think that simple HTML and CSS nowadays already offer all is needed to create beautiful design and express in freedom your own creativity and taste.

Also this template doesn't require any build tool. Just HTML, CSS, JavaScript and your favorite editor, but nevertheless it is a Progressive Web App with a rather good score:

LightHouse report

You can see it live here: HTML-PWA.

About the Context Menu component

While setting up this template I also had a chance to write a new component and add it to the zKit collection, which is the Context Menu.

Context Menu

Like all other companions in the zKit collection, the context menu is a framework-agnostic component that can be integrated easily in any project.

I had no chance to add the documentation yet, but I'll briefly show here how to use it.

1. Add the following line, preferably inside the head section of the HTML document:

<script src="https://cdn.jsdelivr.net/npm/zuix-dist@1.0.0/js/zuix.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

2. Load the context_menu component and put inside the <div data-ui-field="menu"> the HTML code of your menu items.

<div data-ui-load="@lib/components/context_menu"
     data-ui-context="options-menu">
    <div data-ui-field="menu">

    <!-- place here the menu items -->

    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

3. Get a reference to the contextMenu object in JavaScript code

var contextMenu;
zuix.context('options-menu', function(){ contextMenu = this; });
Enter fullscreen mode Exit fullscreen mode

or if you prefer arrow functions

var contextMenu;
zuix.context('options-menu', ctx => contextMenu = ctx );
Enter fullscreen mode Exit fullscreen mode

4. Show/hide the menu programmatically as needed

// show
contextMenu.show();
// hide
contextMenu.hide()
Enter fullscreen mode Exit fullscreen mode

You can already try this with the HTML-PWA website.

  • open the website
  • press F12 (open the browser console)
  • type zuix.context('news-options-menu').show() ... or drawerLayout.open() ... or viewPager.page(2)

Easy-peasy when everything is a component =)

Ok, so it's now time to take a break and possibly go for a swim later. Talk to you soon.

Sea Time

Top comments (22)

Collapse
 
sompylasar profile image
Ivan Babak

With all these "data-ui-load", "data-ui-context", "data-ui-field" the statement that it's "framework-agnostic" means "offers you a yet another component framework with a few built-in components".

Collapse
 
genejams profile image
{Gene}

No, it's just a small library (13kB) for component-based and modular development. I wouldn't ever dare to call it framework =)

There's no built-in components. These directive attributes are telling the library where to load components from and options to use, nothing more.

Framework agnostic also means that it's not a UI thing (eg. BootStrap and such), it does not require transpilers and build tools.

See my very first post which is an introduction to zuix.js:

And also, what's wrong with "yet another"?
Do you prefer using mainstream frameworks and missing the possibility of something better, which I am not saying it is zuix.js, but it could be somewhere out there... =)

Collapse
 
sompylasar profile image
Ivan Babak

Of course, this comes down to "what are we thinking a framework is". A framework is something that is assumed/implied to be around when you build an application. For example, assuming the DOM API is around when writing the app code means you use the Web Browser framework; assuming require is around when writing your app code means you use the CommonJS Module System framework (which can be provided by Node or Webpack or something else); assuming something will pick up some data attributes and will do something about them means you use some framework that understands them, etc.

"a small library for component-based and modular development" decides how to make and use components and modules, so it's kinda framework.

There's no built-in components. These directive attributes are telling the library where to load components from and options to use, nothing more.

"directive attributes [on an HTML tag]" decide how to load and inject components into the DOM, so it's kinda framework.

Framework agnostic also means that it's not a UI thing (eg. BootStrap and such), it does not require transpilers and build tools.

HTML/DOM components are UI. I don't see any substantial difference between data-ui-load="@lib/button" and class="button". Both assume some context (which is what a framework provides).

Not every framework or library requires transpilers and build tools, and most use them for the benefits of maintainable source code regardless of the framework in use; truly, some require using more languages than JavaScript, e.g. Handlebars; "prefer arrow functions" even with your library may require a transpiler because this JS syntax wasn't there since the beginning of JS.

And also, what's wrong with "yet another"? Do you prefer using mainstream frameworks and missing the possibility of something better, which I am not saying it is zuix.js, but it could be somewhere out there... =)

I prefer contributing and improving the mainstream frameworks first, invent something new second, when other options to fulfill the quantifiable requirements like UI performance or bundle size have been exhausted.

I won't stop people from inventing their own bicycles, I've invented some, too, when existing ones did not fulfill my requirements. But I'll try to encourage them to look around and pay attention to the vast experience shared out there about the problems or parts of them that have been already solved very well. Some pieces are missing that need to be filled, but there's much foundation has been built and tested by millions in real life scenarios over many years.

Thread Thread
 
genejams profile image
{Gene}

So what do you suggest here? I am open to critics and suggestions.
Otherwise to me this seems like an attack/hate thing =) for no apparent reason.

I just wanted to share something and it does what I said, nothing more, nothing less. Perhaps someone else appreciated it.

The "Framework / Library" debate is a old thing. In my opinion this is a library.

But if you want to call it framework, I am glad you did, I just thought that zuix does not deserve this title because of a question of humility.

Thread Thread
 
sompylasar profile image
Ivan Babak

No attack nor hate. I'm aware that nowadays people are not welcomed to share negative feedback, only positive. My suggestion: improve and contribite to and on top of existing stuff that solves similar problems first, make brand new stuff second. The brand new stuff may be appreciated more because of social bias, this doesn't mean the brand new is more valuable. I appreciate your effort to improve the world on a problem, but argue the solution of making a brand new thing from scratch. This as well applies to certain projects of mine, too, I here admit my mistakes of trying to make new stuff without reusing a lot of foundation.

Thread Thread
 
genejams profile image
{Gene}

I welcome negative feedback. I always ask if there's something I can do to improve. See the other message in this thread. See also my other posts. =) Negative feedback helps you learn and make things better for you and for others.

You should have asked why I created this library. It was explained in the post I linked to you. And it started in 2012! There was no other similar thing at the time.

GitHub is partially witness of such thing:

HomeGenie core widgets

HomeGenie users widgets

The oldest shows "4 years ago", but just because the source code was previously hosted on SourceForge.

Whenever I look for a solution to a project requirement I search over and over again to pick the best one. If I don't find any, I write my own solution as best as I can. And I iterate the search process even later because I prefer to renew any renewable solution if there's a better one.

Also, in your previous message mentioned something about arrow functions. What did you mean?

Thread Thread
 
sompylasar profile image
Ivan Babak

Okay, if it started in 2012 (the architectural, design decisions were from that time), then the solution may be no longer relevant now when you present it to a broader audience. Frontend tech changes very rapidly, solutions improve and become obsolete constantly, and it's really hard to keep up.

About arrow functions, it's from your post:

Get a reference to the contextMenu object in JavaScript code
...
or if you prefer arrow functions
...

It is irrelevant to your library (unless it really is) which version of JS syntax your library users are using, so stick with one (e.g. the most modern or the most stable).

Thread Thread
 
genejams profile image
{Gene}

Frontend tech changes very rapidly, solutions improve and become obsolete constantly.

In fact I keep it constantly up to date. Otherwise I wouldn't have "revamped" it as a separate product. I understand that you haven't had a look it, you're not interested, but if you have a look at it you might start noticing that perhaps things are different than what you thought.

It is irrelevant to your library (unless it really is) which version of JS syntax your library users are using, so stick with one (e.g. the most modern or the most stable).

Instead it is relevant because with zuix you can use both notations. The this keyword has different meaning for 'standard' functions and arrow functions. Older JavaScript code will not work if a method callback was only designed to be used with the context this. With zuix there's no such problem.

With zuix you also have a TypeScript definition file. So if you like transpiling you can use modern classes and all other TypeScript comforts.

I personally still prefer the old way of 'simulating' classes (closures and prototypes) because I believe that beginners and old school developers can have a better understanding.

This should at least make you understand how much care and effort I put in my work. =)

Thread Thread
 
sompylasar profile image
Ivan Babak • Edited

It's the architecture and design decisions that are likely kept from 2012. It's not necessarily bad because the underlying platform didn't change much, but because the surrounding ecosystem changed noticeably.

I know how JS functions work, but thanks for the brief reminder. The this context difference is only relevant for the user of your framework library if the library passes something to the user via this (I'm sure you know and had in mind how jQuery does that with event handlers and forEach callbacks).

Thread Thread
 
genejams profile image
{Gene} • Edited

It's the architecture and design decisions that are likely kept from 2012.

How can you assert that? And why aren't you providing any tangible example with your statements? =) Otherwise it's just stalking =P

Enlighten me please.

Thread Thread
 
sompylasar profile image
Ivan Babak

I'm observing, not asserting. Using DOM markup attributes and imperatively attaching JavaScript behavior to them via attribute selectors is an old practice, circa about when JS and the DOM appeared. It has its pros and cons. We could go deep into those. Google homepage still uses that, so it's viable given certain constraints and having certain resources to maintain. Since then the paradigm has shifted towards more declarative UIs to address some of the cons like the lack of composability; this of course introduced some cons, too, like what you mentioned previously: bundle size, transpilation.

Thread Thread
 
sompylasar profile image
Ivan Babak

I've just scanned this code github.com/genielabs/zuix-html-pwa... front to back, and I've only confirmed my initial observations: the code is great and beautiful, but its architecture and design decisions are obsolete. It's an in-house framework which blends jQuery, Angular, and a few built-in components, Logger, Async primitives, an XHR wrapper. It even explicitly borrows pieces of jQuery code. I wrote similar in-house framework at about the same time (2012-2014), but I instead included jQuery as a dependency; at about 2015-2016 I've upgraded all the code to the modern dependency management and bundling tools (npm, CommonJS, Webpack), and later introduced React; now the UI is mostly React, app structure and older components still use that in-house framework.

Thread Thread
 
genejams profile image
{Gene}

more declarative UIs to address some of the cons like the lack of composability

Respecting current standards is a choice, not an obsolete practice. There's no lack of composability here.

It even explicitly borrows pieces of jQuery code.

Are you kidding me? =) Where did you saw that? Still attacking without knowing what are you talking about?

Can you provide a practical example? This is what I was asking before. I mean, show a small piece of code.

at about 2015-2016 I've upgraded all the code to the modern dependency management and bundling tools (npm, CommonJS, Webpack), and later introduced React;

Why would one add complexity over complexity when you can reach the same goal without those tools? Most of times these tools are misused and abused.

Have you read my post about in-browser bundling? Have you tried a simple "View Source" on

HTML-PWA

there you will see an app.bundle.js:

app.bundle.js

and guess what? It didn't came out of any build tool.

So are you sure that what you stated is always (if at all) true?

As I never would dare a comparison between a 13kB library with a 100kB framework, still again, I beg you, provide some piece of code to show evidence that, for instance, a small component written with React is way better of any other framework (because is this what you are trying to do since the beginning of this thread, it seems).

This is now a very long thread that could have been solved with just few lines of code.

I must say I liked the name ThePracticalDev and I like DEV.TO. So since we are here, let's be practical.

Show how beautiful is writing code with React (since you mentioned it). I'll show how you can do the same in most of cases with this small "old-fashioned" library which might surprise you in term of performance and elegance.

So this will probably start to be a decent and constructive conversation. Otherwise still looks like trolling.

We're practical developers not marketing puppeteers.

Thread Thread
 
sompylasar profile image
Ivan Babak

Of course, using standards is a choice, and it's good for up to certain scale of an app.

That's the paradox: small pieces of code that can be shared online will actually look more complex. To get an example, you'd have to open-source a large app: basically what you did by sharing the in-house framework, but every app is different, and looks like you there did not reach the scalability and UI state management problems with its DOM manipulation approach. It's not marketing, it's just solving bigger engineering problems that only surface after a few years of app code evolution.

As I won't be able to share in a snippet a few years of the app code evolution and problems we've solved with React, I think it's impractical to continue this discussion. We have different experiences, so let's agree to disagree, and move on.

Thread Thread
 
sompylasar profile image
Ivan Babak • Edited

P.S. Here's the snippet from your library source, is it not?

/**
 * ZxQuery, a very lite subset of jQuery-like functions
 * internally used in Zuix for DOM operations.
 *
 * The constructor takes one optional argument that can be
 * a DOM element, a node list or a valid DOM query selector string expression.
 * If no parameter is given, the resulting ZxQuery object will wrap the
 * root *document* element.
 *
 * @class ZxQuery
 * @param {Object|ZxQuery|Array<Node>|Node|NodeList|string|undefined} [element] Element or list of elements to include in the ZxQuery object.
 * @return {ZxQuery} The *ZxQuery* object containing the given element(s).
 * @constructor
 */
function ZxQuery(element) {

Maybe you did not copy and paste jQuery source as is, but you definitely did copy its API and design decisions (e.g. having a new object which represents collection of selected elements that you pass around). jQuery latest does that in a more performant way, btw, borrows some standard functions like push from Array and uses for index loops instead of for in and Object.keys and hasOwnProperty to iterate in each. Have a look: unpkg.com/jquery@3.3.1/dist/jquery.js

I'm sorry, but it's true. Their code evolved, but your library's code snapshotted an older, less performant version.

EDIT: here's the each loop snippet:

z$.each = function(items, iterationCallback) {
    const len = (items == null ? 0 : Object.keys(items).length);
    if (len > 0) {
        let count = 0;
        for (let i in items) {
            if (items.hasOwnProperty(i)) {
                let item = items[i];
                if (item instanceof Element) {
                    item = z$(item);
                }
                if (iterationCallback.call(item, i, items[i]) === false) {
                    break;
                }
                count++;
                if (count >= len) {
                    break;
                }
            }
        }
    }
    return this;
};
// jquery@3.3.1
    each: function( obj, callback ) {
        var length, i = 0;

        if ( isArrayLike( obj ) ) {
            length = obj.length;
            for ( ; i < length; i++ ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        } else {
            for ( i in obj ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        }

        return obj;
    },
Thread Thread
 
genejams profile image
{Gene} • Edited

Maybe you did not copy and paste jQuery source as is, but you definitely did copy its API and design decisions

I'm sorry, but it's true. Their code evolved, but your library's code snapshotted an older, less performant version.

Back to attack? =) I did not copy at all.
Using method chaining and fluent API is a design pattern and choice, and anyway that's not a jQuery only prerogative.

Picking up similar methods name to jQuery is because I liked it and because it could also be familiar to many others, also names are similar all over many different APIs.

But I did avoid to implement methods that are already present in modern JavaScript/DOM API.
It's all explained in zUIx.js website. No secret.

Anyway thank you for pointing to this each issue, if you want you can make a pull request =) I will be glad to merge it.

Also if you want to talk about performance you are still invited to a code challenge. I will be glad to learn whenever there's something good to learn. And you? =))

Thread Thread
 
sompylasar profile image
Ivan Babak

But I did avoid to implement methods that are already present in modern JavaScript/DOM API.

Like Array.prototype.forEach over an Array of DOM elements for example?

Anyway, I wish you the best of luck with your framework, hopefully you'll get appreciated by the DEV.TO and Glitch communities. Try A-Frame, it's similar in nature with respect to quickly snapping together low-fi prototypes, it may be the next big thing and our modern approaches to functional and declarative data flow and UI state management will be obsoleted by agent-like components that interact with each other.

I have to sign off to get back to software engineering.

Thread Thread
 
genejams profile image
{Gene}

Oh, I understand =) and I guess they do pay you for things like this too ;) perhaps you're better at this arguing than coding and engineering =P

Thread Thread
 
sompylasar profile image
Ivan Babak

You might find this enlightening: fibers-effects-react-rally.surge.s...

Collapse
 
neavilag profile image
neavilag • Edited

thanks Gene, great work !!!, I am more a Back end that front end, and as you stated I try to do most of the things without frameworks if can be done with vanilla and is understandable. even my exercise was to make a weather app without using JQ.

I made my first PWA with MDL html5 template, how zUIx.js compares to this? and hints or idea, based on the sample app I think will like to try my weather app with your template. Will let you know how it works. Thanks again.

Collapse
 
christiankaindl profile image
Christian Kaindl

This is the best thing I have ever seen. Thank you!

Collapse
 
genejams profile image
{Gene}

Thank you very much =)
If you have any suggestion to improve this feel free to ask.