🇬🇧 LitElement - First steps

updated on 2019-01-13 with LitElement 2.0.0-rc.2

What!? Another JavaScript Framework?

From time to time, the chance is my worst enemy. Unless unconsciously, this is my brain that is my worst enemy. I have many projects started that I must finish, and this Sunday while doing my "technological watch," "by chance," I came across this little project that seems to be the future of Polymer: LitElement (all started here: https://lit-element.polymer-project.org/).

... And, it was already too late for me. So the summarize to describe LitElement is what you can read on its homepage: "A simple base class for creating fast, lightweight web components".

Is it true? Yes but ... Except (perhaps) for the first steps of installing the various tools to get started, because, it's young, things change, sometimes faster than the documentation. So today I will explain how to start a LitElement project, but keep in mind that "things change". And tomorrow we'll dig deeper with components.

Here we go!

First, your minimal requirements are:

  • NodeJS
  • Yarn

Btw, you can use npm instead yarn, but I had some issues when installing polymer CLI with npm, and all was fine with yarn.

Type these commands:

# first (only once)
yarn global add polymer-cli
# Then
yarn install

You just installed the polymer CLI globally.

If you use VS Code, install this: lit-html. It's an addon to get syntax highlighting for html inside of template strings.

Prepare the project

Now create a directory (eg: bootstrapping-a-litelement-project or something shorter) with these elements:

.
├── index.html
├── package.json
├── polymer.json
├── src
│   └── main-application.js

you can notice that, right now, the inheritance with Polymer keeps strong

Now, we have to fill all these files:

package.json

This file allows yarn (or npm) to download the required dependencies.

{
  "dependencies": {
    "@webcomponents/webcomponentsjs": "^2.2.3",
    "lit-element": "^2.0.0-rc.2"
  }
}

polymer.json

In development mode, you don't need this file. It allows the CLI to build a production distribution of your work. But I think it's a good practice to update this file all along the project life (sometimes it works in development mode, it builds, but does not work. So, I advise you to test it constantly).

{
  "shell": "src/main-application.js",
  "entrypoint": "index.html",
  "fragments": [],
  "npm": true,
  "moduleResolution": "node",
  "sources": ["src/main-application.js", "package.json"],
  "extraDependencies": [
    "node_modules/@webcomponents/webcomponentsjs/**"
  ],
  "builds": [{
    "bundle": true,
    "js": { 
      "minify": false,
      "compile": "es5",
      "transformModulesToAmd": true
    },
    "addServiceWorker": true,
    "addPushManifest": true
  }]
}

I'm not totally fluent right now with the polymer CLI, but the most important fields of the polymer.json file are:

  • "shell": "src/main-application.js": this is the starting component of your web application
  • "entrypoint": "index.html": this is the main html page of the web application
  • "fragments": []: here we'll define the list of the components of the web application (*you will have to wait for tomorrow for this part *)
  • "sources": ["src/main-application.js", "package.json"]: you need to explain to the polymer CLI where are the files to build

index.html

Of course, this is the "foundation" of your web application (that file and main-application.js.

<!doctype html>
<html lang="en">
<head>  
  <title>LitElement 1st Steps</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta charset="utf-8">
  
  <!-- Load polyfills -->
  <script 
    src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
    defer>
  </script> 

  <!-- Load components via WebComponents.waitFor -->
  <script type="module">
    window.WebComponents = window.WebComponents || { 
      waitFor(cb){ addEventListener('WebComponentsReady', cb) }
    } 
    WebComponents.waitFor(async () => { 
      import('./src/main-application.js');
    });
  </script>
</head>
  <body>  
    <main-application>
      Loading...
    </main-application>
  </body>
</html>

So, some explanations:

We need webcomponents polyfills right now to "run" LitElement:

<script 
  src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
  defer>
</script> 

Then, whe have to load the web components:

<script type="module">
  window.WebComponents = window.WebComponents || { 
    waitFor(cb){ addEventListener('WebComponentsReady', cb) }
  } 
  WebComponents.waitFor(async () => { 
    import('./src/main-application.js');
  });
</script>

And, finally, the browser can load our wonderful web component <main-application>

<main-application>
  Loading...
</main-application>

So now, let's write this component!

src/main-application.js

This is the main component of the web application (the starting component). So, a LitElement component typically looks like this:

import { LitElement, html } from 'lit-element';

export class MainApplication extends LitElement {

  constructor() {
    super()
  }

  render() {
    return html`
      <h1>I'm the main application!!!</h1>
    `
  }
}

customElements.define('main-application', MainApplication);
  • So, a LitElement is "only" an ES6 classe that extends LitElement
  • With a render() method using the html helper function
  • Templates are only JavaScript template strings, all the clever things are the html helper function
  • And you need to register your component with customElements.define('main-application', MainApplication)

html helper function comes from the lit-html project

👋 You can retrieve this part here https://gitlab.com/bots-garden/training-materials/bootstrapping-a-litelement-project/tree/00-setup

the 00-setup branch of the bootstrapping-a-litelement-project, and master reflects the last current step/progress of the project.

Serve it!!!

It's the simple part, inside your directory, type this command:

polymer serve

And go to http://127.0.0.1:8081/ and you are going to get a fantastic "I'm the main application!!!"

If you want to test the build part (to deploy in production), use this command:

polymer build
polymer serve build/default

And go again to http://127.0.0.1:8081/

Today, we made the most tedious part, tomorrow (if I find the time), we'll see how to add components, and how to start playing with. I'm starting to fall in love with this framework (I do not know why right now). Some will say that I am "fickle in JavaScript love", but we must try 😘

See you tomorrow 👋

Last Articles

Last Updated: 1/13/2019, 6:46:18 AM