Getting Started with lit

So I've been wanted to try for sometime but what put me off was the lack of a comprehensive documentation from scratch assuming a little knowledge of TypeScript and build tools by the learner. Because that's where I was coming from. Had it been JavaScript it would've been easier but I want to start using TypeScript since it has been starting to be more appealing for development.

Let's look at this example : https://lit.dev/tutorials/intro-to-lit/ in TypeScript. The option to choose TypeScript is the toggle button on the right hand side.

There are 2 files included in the example - you can see the 2 tabs - my-element.ts and index.html. Create these 2 files with ditto code in some directory, say, getting-started. Added here incase the tutorial has the code changed later on.

my-element.ts

import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';

@customElement('my-element')
export class MyElement extends LitElement {
  @property()
  version = 'STARTING';

  render() {
    return html`
    <p>Welcome to the Lit tutorial!</p>
    <p>This is the ${this.version} code.</p>
    `;
  }
}

index.html

<!DOCTYPE html>
<html>
  <head>
    <script type="module" src="my-elements.js"></script>
    <style>
      body {
        font-family: 'Open Sans', sans-serif;
        font-size: 1.5em;
        padding-left: 0.5em;
      }
    </style>
  </head>
  <body>
    <my-element></my-element>
  </body>
</html>

The tutorial example assumes you know TypeScript configuration if working on TypeScript and some knowledge about build tools - obviously - since it is a lit tutorial exclusively and not the entire web stack.

https://lit.dev/docs/tools/requirements/ says "Lit is published as ES2021." but let's specify ES2022 in tsconfig.json in the same getting-started directory, which is as below :

{
    "compilerOptions": {
      "module": "ES2022",
      "moduleResolution": "node",
      "experimentalDecorators": true,
      "useDefineForClassFields": false,
      "lib": ["ES2022", "dom"],
      "target": "ES2022",
      "outDir": "./dist",
      "baseUrl": "./",
      "declaration": true,
      "declarationMap": true,
      "sourceMap": true,
    }
  }

There are some npm packages to be installed (assuming you have NodeJS, I have 21.7.3) - instead of installing them one by one - just add this package.json file in getting-started directory.

{
  "dependencies": {
    "lit": "^3.1.4",
    "rollup": "^4.20.0",
    "typescript": "^5.5.4"
  },
  "devDependencies": {
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-terser": "^0.4.4",
    "@web/dev-server": "^0.4.6",
    "@web/rollup-plugin-copy": "^0.5.1",
    "@web/rollup-plugin-html": "^2.3.0",
    "rollup-plugin-summary": "^2.0.1"
  },
  "type": "module"
}

lit is the main package for lit, typescript is for the language used and rollup is used for building for production which will be explained at the end. The devDependencies are for mainly for rollup except for a web dev server (line having version 0.4.6) and terser for minifying the code (terser replaces the once widely used uglify-js during it's time)

npm i should install everything without any errors creating a node_modules sub-directory in the directory getting-started.

Now in the terminal in the getting-started directory, run tsc which will convert my-elements.ts to my-elements.js. In case tsc doesn't work enter sudo npm i -g typescript in terminal. This installed TypeScript 5.5.4 on my macOS. Or on Windows, open PowerShell in Administrator mode and run npm i -g typescript and close the administrator PowerShell terminal and open a new non-admin PowerShell terminal and cd into the directory getting-started.

tsc will compile all .ts files to .js files into a folder called dist (which we specified in tsconfg.json as "outDir": "./dist",). tsc my-element.ts will compile to JavaScript with but will neglet the tsconfig.json configuration file which is of no good because then it'll spit out all sorts of TypeScript compilation.

Now run npx web-dev-server --node-resolve --watch --open - this will open localhost:8000 but will throw an error saying my-elements.js is not found (404).

If we edit the index.html file to specify the my-elements.js file in dist folder it'll work :

<script type="module" src="dist/my-elements.js"></script>

Ideally this shouldn't be done while development and there should be a way to specify the target folder containing the js files. I'll update this portion when I get some clarity on this.

Now your localhost:8000 should show this :

Now to build it for production. lit recommends and explains the use of rollup which is new to me too. But there are several mismatches in their documentation at https://lit.dev/docs/tools/production/ for the rollup.config.js file. Here's my version :

// Import rollup plugins

import { rollupPluginHTML as html } from "@web/rollup-plugin-html";
import {copy} from '@web/rollup-plugin-copy';
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
// import minifyHTML from 'rollup-plugin-minify-html-literals';
import summary from 'rollup-plugin-summary';

export default {

  plugins: [
    // Entry point for application build; can specify a glob to build multiple
    // HTML files for non-SPA app
    html({
      input: 'index.html',
    }),

    // Resolve bare module specifiers to relative paths
    resolve(),
    // Minify HTML template literals
    // minifyHTML(),
    // Minify JS
    terser({
      ecma: 2021,
      module: true,
      warnings: true,
    }),

    // Print bundle summary

    summary(),
    // Optional: copy any static assets to build directory
    copy({
      patterns: ['images/**/*'],
    }),
  ],

  output: {
    dir: 'build',
  },

  preserveEntrySignatures: 'strict',

};

I couldn't install rollup-plugin-minify-html-literals on my macOS and Windows machines.

But I realised that rollup-plugin-minify-html-literals was used only for minifying HTML here. So I commented out the minifyHTML() call in rollup.config.js file - and also it's import.

Now run rollup -c - I had to do sudo npm i -g rollup before running rollup -c again. It would've created a build in the build folder.

Now goto the build folder and you'll there are 2 files - index.html and my-elements.js - to run index.html run a simple webserver in the build folder like

npx web-dev-server --node-resolve --watch --open

or

php -S localhost:8000 if you have PHP installed.

and you'll be able to see the text on your localhost:8000 webpage.

Happy litting.

0
Subscribe to my newsletter

Read articles from Anjanesh Lekshminarayanan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anjanesh Lekshminarayanan
Anjanesh Lekshminarayanan

I am a web developer from Navi Mumbai working as a consultant for cloudxchange.io. Mainly dealt with LAMP stack, now into Django and trying to learn Laravel and Google Cloud. TensorFlow in the near future. Founder of nerul.in