Using Typescript and Webpack with Fabric.js: Error - Canvas is not a constructor

I'm currently experimenting with integrating fabric.js into a Laravel 5.4 application using Typescript and Webpack, alongside other modules that are functioning properly in the browser. Although @types/fabric is installed and Typescript is behaving correctly, I have encountered some challenges due to my lack of experience with Typescript and Webpack.

The Issue

result.js:198 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_fabric___default.a.Canvas is not a constructor

Approach A

code.ts

import fabric from "fabric";
const canvas = new fabric.Canvas('my-canvas');

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__default.a.Canvas('my-canvas');

The usage of WEBPACK_IMPORTED_MODULE_1_fabric__default refers to an object where 'fabric' serves as the key.

const canvas = new fabric.fabric.Canvas('my-canvas');

This configuration would function within Webpack, yet it does not adhere to type inspections.

Approach B

code.ts

import * as fabric from "fabric";
const canvas = new fabric.Canvas('my-canvas');

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__["Canvas"]('my-canvas');

In this case, WEBPACK_IMPORTED_MODULE_1_fabric contains an object where 'fabric' is the key, mirroring the situation in Approach A.

Approach C

code.ts

import {Canvas} from "fabric";
const canvas = new Canvas('my-canvas');

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__["Canvas"]('my-canvas');

Ultimately, this approach aligns closely with Approach B.

excerpt of webpack.mix.js

   .webpackConfig({
    module: {
        rules: [
            // Webpack configuration rules here...
        ]
    },
    plugins: [
        // Plugin configurations here...
    ],
    resolve: {
        // Resolve configurations here...
    }

It appears that the issue lies within Webpack or perhaps the babel-loader not recognizing the fabric namespace appropriately.

Hence, the main question at hand pertains to whether there exists a method to instruct Webpack on how to handle this import in a manner that directly references fabric (or a similar imported library) or if there's a way to import it into Typescript in a manner that satisfies Webpack as well?

Answer №1

Here is the solution that worked for me:

import 'fabric' ;
declare let fabric: any;

let canvas = new fabric.Canvas('myCanvas') ;

For my project, I am utilizing @types/fabric version 1.5.26 along with TypeScript 2.5.3 and webpack 3.5.1.

Answer №2

The key to solving the issue was found within the webpack.mix.js configuration file. To address the problem with fabric, the exports-loader needed to be included. The following rules were implemented:

            rules: [
            ...
            {
                test: /fabric(\.min)?\.js$/,
                use: 'exports-loader?fabric',
            },
        ]

With these changes, fabric can now be utilized as shown below:

        import fabric from "fabric";
        const canvas = new fabric.Canvas('my-canvas');

It is important to ensure that the exports-loader is properly installed. Additional information on this solution can be found here: https://github.com/OfficeDev/office-ui-fabric-js/issues/258

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for optimizing data loading in Angular by pre-loading data to prevent unnecessary Firebase reads

Issue: One specific part of my web application is responsible for fetching a large amount of data from Firebase Firestore whenever a user visits that section. This results in hundreds of thousands of unnecessary reads to my Firestore database. Inquiry: Ho ...

How do I showcase the array value on top of a form using Javascript?

My current form displays errors using alerts, but I want to update it so that the errors are printed above the input fields for easy reference by users. This is the existing code for displaying errors: function showErrors() { if (errList.length >= ...

AngularJS redirection to a different state by utilizing a URL

When I need to direct a user to a specific state, typically I would use the following code: $state.go('state_name'); $state.transitionTo('state_name'); This method usually takes users to /state_name. However, there is one particular s ...

Tips for changing the visibility of a div within table rows upon clicking

Struggling to solve this jQuery issue with a table that displays numbers on each row. I want to be able to click on one of the numbers, which is a href link, and toggle only the corresponding div called "test" instead of toggling all rows at once. How can ...

Joining Two Texts in HTML with a Link Embedded within

Within my HTML code, I have two specific strings: "Forgotten your password?" and "Please" 'HPERLINK' "to change your password". To manage these strings efficiently in different languages, I utilize a messageBundle file to store constants. This f ...

Slideshow elements removed

I attempted to remove my links individually from the div id="wrapper", but unfortunately have encountered an issue while doing so: window.onload = function () { setInterval(function () { var wrapper = document.getElementById("wrapper"); var my_l ...

The array is producing accurate results, however it is displaying as undefined in the HTML output

I have encountered a problem while working on my project. I am utilizing an API to fetch an array of platforms where a video game is available. Although the array is returning the correct data, I am facing difficulty in displaying these values in my HTML a ...

Guidance on navigating a JSON object containing an array with backslashes using Jquery or Javascript after receiving it from an AJAX request

I am facing a challenge with looping through an array inside JSON data to display it in a table based on nationalities. The issue arises from the presence of backslashes in the array data, making it difficult to iterate through. This data is fetched using ...

The Power of Combining Promise All with GET Requests

I am currently struggling to understand the necessary steps to accomplish a task. My goal is to retrieve all users' "watchlists" for crypto coins (which I have done), and then return updated data from the coinmarketcap api based on what is saved in th ...

Creating a nx workspace for vanilla JavaScript (Error: module 'typescript' not found) - Step-by-step guide

Looking to set up a new workspace for plain React applications. How can I do it? Create Workspace npx create-nx-workspace@latest # version 15.2.1 # style: package-based # distributed caching: NO Installing the react-package npm install -D @nrwl/react Cr ...

Angular ng.IComponentOptions binding directive list

I'm currently utilizing the ng.IComponentOptions to construct my component class which houses both my controller and view template: export class LCAConfiguratiePersonenDetailComponent implements ng.IComponentOptions { public templateUrl: string; ...

Performing calculations using the xor variable

When I calculate, I follow this method: 117^196 The result is: 177 Now I want to revert back to 117 so I need to perform a replacement (replace)^196 = 117 What is the reverse operation of the xor operator? ...

Is it possible to extract data from a null value when trying to access the 'password' property?

const express = require("express"); const mongoose = require("mongoose"); const bodyparser = require("body-parser"); const path = require("path"); const router = express.Router(); const db = mongoose.connection; con ...

Having trouble parsing multiple JSON rows in JavaScript

I tried using the twitterapi to fetch my friends list in php and encoded the result as a json array. However, I'm facing difficulty parsing the json array in javascript. I have confirmed that the json array generated by the php code is valid. Below is ...

The data is not appearing in the Vuetify data table

I have encountered an issue with the Vuetify data table where it is not displaying any data. Even though it shows that there is 1 row out of 1 displayed, the table body remains empty. Below is my component code: <template> <v-data-table :hea ...

The data structure '{ one: string; two: string; three: string; }' cannot be directly assigned to a 'ReactNode'

Here is the Array of Items I need to utilize const prices = [ { name: "Standard", price: "149EGP", features: [ { one: "Add 2500 Orders Monthly", two: "Add Unlimited Products And Categories", three: "Add 20 other ...

I want to learn how to iterate through an API response object in React and extract the 'urls' link for images

I'm currently facing an issue while attempting to iterate over an Object in React that is received from an API. My goal is to extract the 'regular' URL link from the object. I have a state variable called 'searchImages' which store ...

Angular module delayed initialization

After defining my angular module in a routine following window.onload, I've noticed that angular seems to look for the module before the window is fully loaded. However, I want to make sure all assets are loaded before triggering the angular module. ...

Is it considered acceptable to employ an endless loop to continually monitor the connection to a server?

Today marks the beginning of my journey in creating an Angular App. My goal is to establish a connection to a server and display a message on screen if the connection is offline, prompting the user to check their network settings. I currently have a JavaSc ...

having difficulty interpreting the information from angular's httpclient json request

After creating an Angular function in typescript to make an http request for JSON data and save it to an object, I noticed that the function requires two clicks of the associated button to work properly. Although the connection and data parsing are success ...