JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.5/fabric.min.js"></script>
<canvas id="c" width="400" height="400"></canvas>

JavaScript

var canvas = window._canvas = new fabric.Canvas('c');

fabric.ImagePlaceholder = fabric.util.createClass(fabric.Text, {
	type: 'imagePlaceholder',

	initialize: function(text, options) {

		options || (options = { });
		console.log('imagePlaceholder', text, options);
		this.callSuper('initialize', text, options);

		this.set('imageId', options.imageId || '');
		this.set('text', 'Loading ' + text || 'Loading...');
		this.set('type', 'imagePlaceholder');
	},

	toObject: function() {
		return fabric.util.object.extend(this.callSuper('toObject'), {
			imageId: this.get('imageId'),
			type: this.get('type'),
		});
	},

	_render: function(ctx) {
    this.callSuper('_render', ctx);
    ctx.font = '20px Arial';
    ctx.fillStyle = '#333';
    ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
	},
});

fabric.ImagePlaceholder.fromObject = function (object, callback) {
	
    var _enlivenedObjects;
    fabric.util.enlivenedObjects(object.objects, function (enlivenedObjects) {
        delete object.objects;
        _enlivenedObjects = enlivenedObjects;
    });
    return new fabric.imagePlaceholder(_enlivenedObjects, object);
};
// Added or not it doesn't work :(
fabric.ImagePlaceholder.async = true;

newObject = new fabric.ImagePlaceholder('cat_image.jpg', {imageId:Date.now()});
canvas.add(newObject);

var json = window._json = canvas.toJSON();
console.log(json);

//Comment out the following to see the 'undefined' object being created..
//canvas.clear();
//canvas.loadFromJSON(json);