Lighthouse Scanner: Frontend Development with PlainJS

Lighthouse Webpage Requirements

  • 202 Job is starting
  • 400 No URL or invalid URL is given
  • 429 No workers available
  • 200 job is finished and successful
  • 202 job is running
  • 404 job id is unknown
  • 409 job is finished but failed
  • Request different backend endpoints
  • Show messages (success, errors)
  • Periodically request job status
  • During scanning, disable scan button and scan bar
  • When the job is finished: enable scan button and scan bar
  • When the job is successful: render download link

PlainJS Basics

DOM Manipulation

<form class="form" id="search-form">
<label for="URL">URL</label>
<input type="text" id="search-form-input" placeholder="">
<input type="button" value="scan" id="search-form-button"></div>
<div id="search-form-msg-box"></div>
function setMsg(msg) {
const msg_box = document.getElementById('search-form-msg-box');
msg_box.innerHTML = `<span class="text-green-500 font-medium">${msg}</span>`
function removeMsg() {
msg_box.innerHTML = '';

Event Listeners

  • Event: The name of the event for which the trigger is defined, see this list of event triggers
  • Function: The functions that gets executed
.addEventListener('click', setMsg('Scan started'));
.onsubmit = setMsg('Scan started'));

API Requests with Fetch

fetch('/api', {
method: 'POST',
headers: {
"Content-type": "application/json"
body: '{"url":""}'
  • Using .then chains to process the results, and .catch for error cases.
  • Using await to get the results, and wrap the function call in a try ... catch block
async function requestScan(event) {
try {
const targetUrl = input.value;
const response = await fetch(`${backend_server}/scan?url=${targetUrl}`);
const body = await response.json();
if ([400, 429].includes(response.status)) {
if ([202].includes(response.status)) {
} catch (e) {

Code Structure

const form = document.getElementById(...)
const input = document.getElementById(...)
const button = document.getElementById(...)
const msg_box = document.getElementById(...)
//...function setMsg(msg, success = false) { ... }
function removeMsg() { ... }
function enableSearchBar() { ... }
function disableSearchBar() { ... }
//...function pollJobStatus { ... }
async function pollUntilReportDone { ... }
//...function init() { ... }
window.onload = init;



  1. Read this great article to understand why it’s not possible to pinpoint the JavaScript version that you are using in your browser.
  2. See how different JavaScript frameworks impact the loading and CPU processing time in this report.
  3. You can use other selectors, including tag names or CSS as well.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store