Generating/Scanning QRCode on Web with Express and VueJS

In this lab, we are going the talk about how to generate and scan QRCode on Web NodeJS and VueJS. We will use the library qrcode to generate the QRCode and html5-qrcode to scan the QRCode.

Introducing QRCode

QRCode is a two-dimensional barcode that can be read by a camera. It is used to store information such as text, URL, phone number, email address, etc. It is widely used in the field of logistics, transportation, and retail. The acmount of data carrying by a single QRCode symbol depends on the encoding mode and the version of the QRCode. The maximum amount of data that can be stored in a QRCode symbol is 7089 characters.

The drawback for storing more data is that the QRCode will be more difficult to scan. The QRCode can be scanned by a camera or a QRCode scanner. The QRCode scanner is a device that can read the QRCode and convert it into a digital signal. The QRCode scanner can be used to scan the QRCode on the product packaging, the QRCode on the ticket, the QRCode on the business card, etc.

Let’s take a look to these examples:

Version 1 (21×21). Content: "Ver1"

Version 4 (33×33). Content: "Version 4 QR Code, up to 50 char"

Version 10 (57×57). Content: "VERSION 10 QR CODE, UP TO 174 CHAR AT H LEVEL, WITH 57X57 MODULES AND PLENTY OF ERROR CORRECTION TO GO AROUND. NOTE THAT THERE ARE ADDITIONAL TRACKING BOXES"

The QRCode symbol version is from 1 to 40. Version 1 is the smallest while version 40 is the largest. The version 1 has 21×21 modules and the version 40 has 177×177 modules. Version 1 can store 25 characters and the version 40 can store 7089 characters. Many QRCode generator implementations define 4 different levels of error correction: L (7%), M (15%), Q (25%), and H (30%). Raising error correction level means raising density level of the QRCode symbol, which also means the QRCode will be more difficult to scan.

Starbucks qrcode

It’s quite common to put graphics on QRCode by making use of the error correction feature.

Generating QRCode

To generate the QRCode, we will use the library qrcode. This library work on server-side with NodeJS and also in browser.

Generate QRCode image in express route

Let’s create an express project to try it out.

npx express-generator --no-view --git lab4
cd lab4
npm install
npm install --save qrcode

Constrcut a route handle to produce QRCode image

Let’s create a route handler in index.js for generating a QRCode image.

const QRCode = require('qrcode');

router.get('/api/code.png', function(req, res, next) {
    return QRCode.toFileStream(res, 'data in code', {
        color: {
            dark: '#0000FF',  // Blue dots
            light: '#0000' // Transparent background
        }
    });
});

The qrcode library provides a function toFileStream to generate the QRCode image. The first parameter is the stream to write the QRCode image. The second parameter is the data to be encoded in the QRCode. The third parameter is the options for the QRCode. The color option is used to set the color of the QRCode. The dark option is used to set the color of the dark modules. The light option is used to set the color of the light modules.

Test the route handler

Let’s start the server and test the route handler.

npm start

Open the browser and go to http://localhost:3000/api/code.png. You should see the QRCode image.

QRCode image

Generate QRCode image in VueJS

In the other hand, QRCode could also be genereated in frontend. Let’s create a VueJS project to try it out. The Vue cli is become deprecated and suggest to use create-vue for creating new Vue project. Either invoke it with npx create-vue or npm create vue@3 are fine. --router tells it to include vue-router component in project.

npx create-vue --router lab4-vue
cd lab4-vue
npm install
npm install --save qrcode
npm run dev

Create a component to generate QRCode image

Let’s create a component QrCode.vue to generate the QRCode image. The following example is in latest Composition API syntax to show you the beauty of it.

<script setup>
import { defineProps, onMounted, ref } from 'vue'
import QRCode from 'qrcode'

const props = defineProps({
    data: {
        type: String,
        required: true
    }
});

const src = ref("");

onMounted(async () => {
    src.value = await QRCode.toDataURL(props.data, {
        color: {
            dark: '#0000FF',  // Blue dots
            light: '#0000' // Transparent background
        }
    });
});
</script>

<template>
  <img :src="src" />
</template>

Adding QrCode to a view

Let’s add the newly created component to src/views/HomeView.vue as follows:

<script setup>
import TheWelcome from '../components/TheWelcome.vue'
import QrCode from '../components/QrCode.vue'
</script>

<template>
  <main>
    <TheWelcome />
    <QrCode data="test" />
  </main>
</template>

Scanning QRCode

To scan QRCode in front-end we will use the library html5-qrcode.

npm install html5-qrcode --save

Create QrCodeScanner component

<script setup>
import { defineEmits, defineProps, onMounted, ref } from 'vue'
import {Html5QrcodeScanner} from "html5-qrcode"

const props = defineProps({
  qrbox: {
    type: Number,
    default: 250
  },
  fps: {
    type: Number,
    default: 10
  }, 
});

const emit = defineEmits(['result']);

const onScanSuccess = (decodedText, decodedResult) => {
  emit('result', decodedText, decodedResult);
}

onMounted(() => {
  const html5QrcodeScanner = new Html5QrcodeScanner('qr-code-full-region', props);
  html5QrcodeScanner.render(onScanSuccess);
});
</script>

<template>
<div id="qr-code-full-region"></div>
</template>

Adding scanner component to HomeView.vue

<script setup>
import TheWelcome from '../components/TheWelcome.vue'
import QrCodeScanner from '../components/QrCodeScanner.vue';

const onScan = (decodedText, decodedResult) => {
  alert(decodedText);
  console.log(decodedText, decodedResult)
}
</script>

<template>
  <main>
    <TheWelcome />
    <QrCodeScanner :qrbox="250" :fps="10" style="width: 500px;" @result="onScan" />
  </main>
</template>

Test is on mobile device with ngrok tunnel

ngrok http 5173