Rob Kendal Freelance Shopify Developer

Article hero image including title Babel and Parcel using proposal class properties

Continuing on from the recent posts on using Parcel as a Webpack alternative and using React with Parcel JS, I've been thinking a lot about using modern JavaScript development approaches. One such approach is using the shiny new class properties proposal, specifically the public fields declaration part.

Using the new proposal class properties syntax is almost second nature if you've been using React lately, especially via the super useful Create React App which has them installed and turned on by default.

The beauty of class properties

There are a lot of good reasons to start using these new class properties and the new initialiser syntax, but the main two are to simplify class properties (methods and fields) and the binding of this

As an example, this is currently how you could create a JS class:

class MyClass {
    someFunction() {
    constructor() {
        this.someFunction = this.someFunction.bind(this); // bind our method to 'this'
    	this.bigNumber = 123456789; // a property

Not a fancy class, not particularly hard on the eyes or difficult to read. However, imagine that you've got a ton of methods and properties like this. The class soon becomes difficult to read with lots of clunky this binding in the constructor.

However, by switching it up with the new declaration syntax, you get this:

class MyClass {
    bigNumber = 123456789;

    someFunction = () => {

    constructor() {
	// other constructor stuff

There's not much in it at this point, but the class is now much more self-documenting and, in this example alone, we've removed the need for the constructor altogether.

Let's start using the proposal class properties now!

If you've discovered the previous article on using Parcel bundler as a Webpack alternative, then we're almost there in terms of setup for this to work. You can fork the codebase here and implement your own solution using the Babel plugin we'll get to in a moment.

Because the new class properties are in the proposal stage, we need a bit of help from Babel JS magic to start using them now.

If you head over to the official Babel JS plugin page you can read all about it. With that in mind, let's get a new project going.

The initial set up

I've created a fully-working solution using Parcel and the Babel plugin-proposal-class-properties plugin on CodeSandbox.

It's a simple project that involves 3 files of interest:

  1. index.js the main project file that kicks everything off
  2. listmaker.js that is our JS class with the new class properties being used
  3. .babelrc the Babel JS config file that enables Babel core functionality as well as configures the class properties transform function

Note: we're using's vanilla template which includes Parcel by default. You may need to add your own Babel Core dependencies if you're setting things up from scratch on your local machine.

If we run the project, we encounter this rather egregious error:

Syntax error showing because Babel JS is not configured correctly


First, we'll need to install the Babel plugin @babel/plugin-proposal-class-properties, let's do that now:

yarn add @babel/plugin-proposal-class-properties --dev

Next, we'll need to add a .babelrc file (if you haven't one already) in the project root and add the following to it:

  "presets": [
  "plugins": [

The line with the '@babel/plugin-proposal-class-properties' part is the key here, it's where we enable the Babel plugin.

Working through the files

Starting with index.js:

import "./styles.css";
import ListMaker from "./listmaker";

// let's make some silly lists
const myLists = {
  vegetables: ["cucumber", "turnip", "potato", "carrot", "spinach"],
  dogsNames: ["Rover", "Bosley", "Finn", "Digby", "Doggy McDogface"]

// instantiate our ListMaker class
const listMaker = new ListMaker(myLists);

// kick off the list html generation

// output the html to the browser
document.getElementById("app").innerHTML = `
<h1>Let's make lists!</h1>

Nothing too scary or unfamiliar here. We import our class listmaker.js create a list object that holds some arrays, before instantiating the List Maker class and generating our lists. We add the lists' output into the final HTML on the page using the JavaScript string notation syntax.

Next, inside listmaker.js:

class ListMaker {
  listHtml = "<div><ul>{0}</ul></div>";
  listItemHtml = "<li>{0}</li>";
  lists = {};
  listsOutput = "";
  constructor(listsObj = {}) {
    this.lists = listsObj;
  makeList = list => {
    let listItemsOutput = "";

      listItem =>
        (listItemsOutput += this.listItemHtml.replace("{0}", listItem))

    return this.listHtml.replace("{0}", listItemsOutput);

  generateLists = () => {
    // loop through our list arrays from our initial lists object
    // passed in via props
    Object.entries(this.lists).forEach(([key, value]) => {
      if (Array.isArray(value) && value.length) {
        this.listsOutput += this.makeList(value);

export default ListMaker;

Right away, at the top of the class, we're defining a few class variables such as the output HTML and default lists object.

When the constructor is called, we're updating one of the class variables using the supplied list object.

Back in index.js we call our instantiated List Maker class' generateLists() function which is where we use another nice JS feature, the Object.entries() method. Within here we loop through the objects within the class lists properties, grabbing each object's array of strings, before stuffing their string values into the final HTML string that will be returned to the function caller.

As you can see, the output with Babel proposal class properties transform enabled looks like this:

Final list output from out listmaker.js class. It shows two lists built from our arrays

And there you have it! Nothing fancy on the back, nothing fancy on the front, but it illustrates how simple and self-documenting your classes can become.

Rummaging in the final project

If you'd like to take a look at the finished project for reference, you can jump to the project over on my CodeSandbox account.

I've also included it here:

Rob Kendal

About Rob Kendal

Rob Kendal is an award-winning freelance front-end developer and marketer who likes simple, organised thinking and making clever things. You can find him working on some things on GitHub and recording podcasts, such as The Front End. Say hi and follow me on twitter

Webmentions for this article

Be one of the first to mention this article on twitter.


Read more

How to fix 'Property does not exist on type Window in TypeScript' error

How to fix 'Property does not exist on type Window in TypeScript' error

If you've been asking 'How do I fix the "Property does not exist on type Window in TypeScript" error?' then this is the article for you. We'll fix the property does not exist on type Window error once and for all.


read the full article

How to build a multi-image carousel in React and Tailwind

How to build a multi-image carousel in React and Tailwind

Ever wanted to learn how to build a multi-item carousel in React? Well, in this article we'll do just that by building a multi-item or multi-image carousel in vanilla React using Vite.js and some Tailwind CSS


read the full article

React, Angular and Vue compared, which should you learn in 2021?

React, Angular and Vue compared, which should you learn in 2021?

Learn which of the most popular JavaScript frameworks should you spend your time learning in 2021. We compare Angular, React, and Vue.


read the full article