Giter Site home page Giter Site logo

ibm / pwa-lit-template Goto Github PK

View Code? Open in Web Editor NEW
177.0 19.0 27.0 7.64 MB

A template for building Progressive Web Applications using Lit and Vaadin Router.

Home Page: https://pwa-lit-template.mybluemix.net

License: MIT License

HTML 11.78% TypeScript 68.08% JavaScript 20.15%
pwa-lit-template web-components lit-element lit-html progressive-web-app pwa typescript lit

pwa-lit-template's Introduction

CI Built with pwa-lit-template

pwa-lit-template

Getting started | Build for production | Create a new page | Environment configuration | Service worker | Browser support

This project helps you to build Progressive Web Applications following the modern web standards, best practices and providing you with tools for that purpose. Out of the box, provides you with the following features:

  • Simple way to create Web Components with Lit.
  • Small and powerful client-side router for Web Components with Vaadin Router.
  • All the benefits from a PWA (manifest, service worker, offline UI) thanks to Workbox and pwa-helpers.
  • SEO friendly thanks to the PageElement custom element and the html-meta-manager.
  • A development server with auto-reload to serve the application without bundling with @web/dev-server.
  • Simple build flow thanks to Rollup and @open-wc/building-rollup initial configuration.
  • Easy deployment over to prpl-server or any static hosting.

Check out our roadmap to get informed of the latest features released and the upcoming ones.

Getting started

Prerequisites

Furthermore, this project is built on TypeScript with the intention of improving the developer experience.

Install the dependencies

npm install

Start the development server

This command serves the app at http://localhost:8000:

npm start

Project structure

├─ images/
├─ patches/
├─ server/
├─ src/
│  ├─ components/
│  │  ├─ app-index.ts
│  │  └─ ···
│  ├─ helpers/
│  │  ├─ page-element.ts
│  │  └─ ···
│  ├─ pages/
│  │  ├─ page-home.ts
│  │  └─ ···
│  ├─ router/
│  │  └─ routes.ts
│  └─ config.ts
├─ index.html
├─ manifest.webmanifest
├─ package.json
├─ robots.txt
├─ rollup.config.js
└─ tsconfig.json
  • images: is use to store the static resourced used by your application.
  • patches: contains the patches to apply in the different packages mentioned here. It will be removed at some point.
  • server: contains the logic to serve the application. And is where you are going to create your dist/ folder containing the bundle of your application.
  • src
    • components: contains your custom Web Components. Inside this folder you will find the app-index.ts file, main root of your application following the PRPL patern.
    • helpers: contains two interesting features: PageElement and html-meta-manager. Go more in-depth with them here.
    • pages: where you create the pages for your application.
    • router: where you create the routes for your application.
    • config.ts: stores the application configuration variables. Go more in-depth with it here.
  • index.html: the application entry point.

Guides

Build for production

This command use Rollup to build an optimized version of the application for production:

npm run build

It has two outputs: in addition to outputting a regular build, it outputs a legacy build which is compatible with older browsers down to IE11.

At runtime it is determined which version should be loaded, so that legacy browsers don't force to ship more and slower code to most users on modern browsers.

Note: If you need to add static files to the build, like the images folder or the manifest.webmanifest, you should register them in the copy() plugin of the rollup.config.js.

Create a new page

  1. Create the new page component (extending from PageElement helper) in the pages folder. For example a page-explore.ts.

    import { html } from 'lit';
    import { customElement } from 'lit/decorators.js';
    
    import { PageElement } from '../helpers/page-element.js';
    
    @customElement('page-explore')
    export class PageExplore extends PageElement {
      render() {
        return html`
          <h1>Explore</h1>
          <p>My new explore page!</p>
        `;
      }
    
      meta() {
        return {
          title: 'Explore',
          description: 'Explore page description',
        };
      }
    }
  2. Register the new route in the routes.ts:

    {
      path: '/explore',
      name: 'explore',
      component: 'page-explore',
      action: async () => {
        await import('../pages/page-explore.js');
      }
    },

With SEO in mind, this project offers you the PageElement base class to help you to deal with it; it has a meta() method that edits the HTML meta tags of the specific page. You must override that method to provide the data.

Environment configuration

This project allows different configurations per environment. The file that manages that configuration is src/config.ts. If you are interested in overwrite any of the configuration variables depending of the environment, you can create a file following the rule src/config.{NODE_ENV}.ts. Take into account that you don't need to replicate all the variables, just change the variable that you need to be different this way:

import config from './config.js';

export default {
  ...config,
  environment: 'staging',
};

In the build process the references in the project (but not in the configuration files) of ./config will be replaced to ./config.{NODE_ENV} loading the expected configuration file for the target environment.

Lastly, the way to use that configuration is quite simple. You only need to import it:

import config from '../config.js';

And use it where you need it:

render() {
  return html`
    <footer>
      <span>Environment: ${config.environment}</span>
    </footer>
  `;
}

Service worker

This project has configured the generation and injection of a service worker in the build process. But it is disabled by default. To enable it you just need to change the variable GENERATE_SERVICE_WORKER in the rollup.config.js to true.

Also you can change the Workbox configuration too modifying the variable workboxConfig in that same file.

Browser support

  • Chrome
  • Edge
  • Firefox
  • Safari

To run on other browsers, you need to use a combination of polyfills and transpilation. This step is automated by the build for production command.

pwa-lit-template's People

Contributors

abdonrd avatar dependabot[bot] avatar jesusprubio avatar piotrblachnio avatar renovate-bot avatar renovate[bot] avatar ruanxianzhi avatar stephenwade avatar tansito avatar web-padawan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pwa-lit-template's Issues

Keep the Service Worker disabled by default

Is your feature request related to a problem? Please describe.

Keeping track of Service Worker can be tricky, so we could make it opt-in.

Describe the solution you'd like

Keep the Service Worker disabled by default.
Allowing the user to activate / uncomment it in a simple way.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Remove the pwa-helper-components warnings

Right now the lit-analyzer found two problems (warnings) about the pwa-helper-components. You can the npm run typescript:type-checking to see it.

> lit-analyzer "src/{components,pages}/**/*.ts" --strict

Analyzing 4 files...

./src/components/app-index.ts

    Unknown tag <pwa-install-button>.
    63:  <pwa-install-button>
    no-unknown-tag-name


    Unknown tag <pwa-update-available>.
    67:  <pwa-update-available>
    no-unknown-tag-name


  ✖ 2 problems in 1 file (0 errors, 2 warnings)

Related issues:

Use the absoluteBaseUrl property from @web/rollup-plugin-html

The new version v1.3.0 of @web/rollup-plugin-html introduce the absoluteBaseUrl.

With this, it change the og:image meta tag with the full URL.

<link rel="canonical" href="http://localhost:8000" />
<meta property="og:title" content="MyApplication" />
<meta property="og:description" content="MyApplication description" />
<meta
property="og:image"
content="http://localhost:8000/images/open-graph/cover.png"
/>
<meta property="og:image:alt" content="MyApplication logo" />
<meta property="og:image:width" content="512" />
<meta property="og:image:height" content="512" />
<meta property="og:url" content="http://localhost:8000" />

Add one simple test

For example, something like navigate to each route and get the expected title & description

Expected router outlet to be a valid DOM Node

On Firefox Ubuntu

I use npm start and then the content doesn't appear, only the menu.

Uncaught (in promise) TypeError: [Vaadin.Router] Expected router outlet to be a valid DOM Node (but got undefined)
__ensureOutlet router.js:752
__addAppearingContent router.js:786
ready router.js:498
promise callback*render router.js:469
attachRouter index.ts:29
firstUpdated app-index.ts:103
_$didUpdate reactive-element.ts:1350
performUpdate reactive-element.ts:1317
scheduleUpdate reactive-element.ts:1235
__enqueueUpdate reactive-element.ts:1207
requestUpdate reactive-element.ts:1182
_initialize reactive-element.ts:924
ReactiveElement reactive-element.ts:907
LitElement lit-element.js:82
AppIndex app-index.ts:18
legacyCustomElement custom-element.ts:21
customElement custom-element.ts:64
__decorateClass app-index.ts:7
app-index.ts:18
router.js:752:12
GEThttp://192.168.1.108:8000/src/pages/page-about.ts
[HTTP/1.1 304 Not Modified 1ms]

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • Lock file maintenance

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • Update dependency @web/dev-server-esbuild to ~0.3.6

Pending Branch Automerge

These updates await pending status checks before automerging. Click on a checkbox to abort the branch automerge, and create a PR instead.

  • Update dependency @web/dev-server to ~0.1.38

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/verify.yml
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
npm
package.json
  • @vaadin/router ^1.7.5
  • lit ^2.7.1
  • pwa-helper-components ~0.2.10
  • tslib ^2.5.0
  • @open-wc/building-rollup ^2.2.2
  • @rollup/plugin-replace ^4.0.0
  • @rollup/plugin-typescript ^8.5.0
  • @typescript-eslint/eslint-plugin ^5.57.1
  • @typescript-eslint/parser ^5.57.1
  • @web/dev-server ~0.1.37
  • @web/dev-server-esbuild ~0.3.5
  • @web/dev-server-rollup ~0.3.21
  • @web/rollup-plugin-copy ~0.3.0
  • deepmerge ^4.3.1
  • eslint ^8.37.0
  • eslint-config-ibmresearch ~0.25.1
  • eslint-plugin-lit ^1.8.2
  • eslint-plugin-lit-a11y ^2.4.0
  • eslint-plugin-wc ^1.4.0
  • lit-analyzer ^1.2.1
  • nano-staged ^0.8.0
  • npm-run-all ^4.1.5
  • picocolors ^1.0.0
  • postcss-html ^1.5.0
  • postcss-lit ^1.1.0
  • prettier ~2.8.7
  • prettier-plugin-package ^1.3.0
  • rimraf ^4.4.1
  • rollup ^2.79.1
  • simple-git-hooks ^2.8.1
  • stylelint ^14.16.1
  • stylelint-config-ibmresearch ~0.16.0
  • typescript ~4.9.5
server/package.json
  • prpl-server ^1.4.2

  • Check this box to trigger a request for Renovate to run again on this repository

The Lit decorators doesn't work after the build step

Describe the bug

Right now, when build the project (npm run build), the output doesn't work.

Screenshot 2021-06-01 at 15 25 43

Seems like the this.main is undefined:

firstUpdated() {
attachRouter(this.main);
}

From the @query decorator:

@query('main')
private main!: HTMLElement;

To reproduce

Just build and run the project.

Expected behavior

Working as always.

Setup Renovate to test and merge minor and patch releases without PR

We want to try setup Renovate to test and merge minor and patch releases without PR.

Current config:

{
"extends": [
"config:base",
":separateMultipleMajorReleases",
":maintainLockFilesWeekly"
],
"rangeStrategy": "bump",
"packageRules": [
{
"matchDepTypes": ["engines"],
"enabled": false
},
{
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true
}
],
"lockFileMaintenance": {
"automerge": true
}
}

Whats a good way to pass data to the page-elements?

Because the vaadin-router dynamically replaces the page-elements shown inside the <main> tag, there is no chance for the app-index to pass some properties down to the page-elements.

Whats the best way to achieve this?

When running npm run build I get errors

Describe the bug

[!] Error: ENOENT: no such file or directory, lstat 'C:\Users\saadon\AppData\Local\Temp\6'

To reproduce

Type npm run build

Expected behavior

I am interested to build for different env (CI, QA, EA and PRD), and each build should use the relevant config file (config.ci.ts, config.qa.ts etc.).

Thank you

Document the SEO related stuff

  • The page-not-found.ts add the render:status_code

  • The page-element.ts update the HTML meta tags based on the route metatada property. Also the user can override the metadata() method to use dynamic data.

  • The renderPageNotFound helper. The user can use this helper in the render() method in a page. For example, in a user route when the user doesn't exists. We will know that the user does not exist after making the request to the API.

    Related Vaadin Router issue: vaadin/router#408

Research the router export

Right now we lazy import and initialize the router here:

private async initializeRouter() {
const router = await import('../router/index');
router.init(this.main);
}
firstUpdated() {
this.initializeRouter();
}

This router.init() function doesn't export anything:

export const init = (outlet: HTMLElement) => {
const router = new Router(outlet, { baseUrl: config.routerBaseUrl });
router.setRoutes([
// Redirect to URL without trailing slash
{
path: '(.*)/',
action: (context, commands) => {
const newPath = context.pathname.slice(0, -1);
return commands.redirect(newPath);
}
},
...routes
]);
};

Doing it this way, we found a problem:
We can't import the router instance to use the router helpers.

For example, we want to replace the hardcoded link in the not found page to use the router name. From this:

<a href="/">Back to home</a>

To something like this:

<a href="${router.urlForName('home')}">Back to home</a> 

And the same for the navigation links:

<nav>
<a href="/">Home</a>
<span>-</span>
<a href="/about">About</a>
</nav>

Styling the navigation links based on active route

I think it would be good to include an example of styling the active navigation links based on the current route as this probably a pretty common ask, its basically one of the first things I tried to get working and the right approach is not immediately obvious.

To be complete it would be good to have an example of styling a link that has child routes e.g.
if the link was to /items which displayed a list of items.
Then navigating to /items/item1 should still consider the link as active as it is a child route of items.

Not sure how best to do this, seems vaadin router passes route information down to the routed elements, e.g. location.params.id.

However since the navigation links are in app-index.ts where the router itself is attached it won't have access to that .

So one option would be to move the navigation links into one of the routed components (maybe an overall parent layout component that matches all routes, which handles the navigation bar itself with a slot for the content - then have child routes to '/' and '/about' for the home and about content.

Or another option would be to add an event listener in the app-index.ts that updates some state containing the current routing information (bit like this: vaadin/router#483).

window.addEventListener('vaadin-router-location-changed', this.handleRouteChange)

Maybe there is a better way, any thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.