javascriptvue.jsvitefabricjs

How to properly import Fabric.js in Vite (Vue 3 + Fabric 6.7) — Canvas is undefined


I’m building a Vue 3 project with Vite, and trying to integrate fabric.js (v6.7.0) to allow drawing on a PDF rendered using pdf.js.

Here’s the problem: I installed fabric via:

npm install fabric 

Then I tried to import and use it like this:

import { fabric } from 'fabric' const canvas = new fabric.Canvas(...) 

But I get the following error in the browser:

Uncaught SyntaxError: The requested module 'fabric' does not provide an export named 'fabric' 

Then I tried other approaches like:

import fabric from 'fabric' 

But that gives me:

Uncaught SyntaxError: The requested module 'fabric' does not provide a default export 

Lastly, I tried:

import * as fabric from 'fabric' 

But then fabric.Canvas is undefined (console.log(fabric) just gives a plain object with some utility properties — no Canvas constructor).

My environment:

What I’m trying to do: I want to:

  1. Render the first page of a PDF using pdf.js
  2. Use fabric.js to allow the user to draw/sign on top of the canvas
  3. Export the result as an image or PDF

What’s not working: Importing fabric.js in any of the standard ways doesn’t seem to give me access to fabric.Canvas, and I can’t find clear docs for usage with Vite.

Question:

  1. Has anyone successfully used fabric.js v6+ with Vite + Vue 3?
  2. What is the correct way to import and use fabric.Canvas in this setup?
  3. Do I need to use dynamic import() or configure Vite to handle CommonJS/ESM compatibility?

Any working examples or suggestions would be greatly appreciated!

this my full code:

import * as fabric from 'fabric'
import { jsPDF } from 'jspdf'
import html2canvas from 'html2canvas'
import * as pdfjsLib from 'pdfjs-dist'
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.mjs?worker'
pdfjsLib.GlobalWorkerOptions.workerPort = new pdfjsWorker()
pdfjsLib.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`

const signDialog = ref(false)
const pdfCanvas = ref(null)
let fabricCanvas = null


const openSignDialog = async (path) => {
  try {
    signDialog.value = true

    const response = await api.get(`/api/doc/download/${path}`, { responseType: 'blob' })
    const blob = new Blob([response.data], { type: 'application/pdf' })
    const pdfData = await blob.arrayBuffer()

    const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise
    const page = await pdf.getPage(1)
    const viewport = page.getViewport({ scale: 1.5 })
    const canvas = pdfCanvas.value
    const context = canvas.getContext('2d')
    canvas.height = viewport.height
    canvas.width = viewport.width

    await page.render({ canvasContext: context, viewport }).promise

    fabricCanvas = new fabric.fabric.Canvas(canvas, { isDrawingMode: true })
    

  } catch (err) {
    console.error('load pdf error:', err)
  }
}

const exportSignedPDF = async () => {
  const canvasEl = pdfCanvas.value
  const image = await html2canvas(canvasEl)
  const imgData = image.toDataURL('image/png')
  const pdf = new jsPDF({
    orientation: 'portrait',
    unit: 'px',
    format: [canvasEl.width, canvasEl.height]
  })

  pdf.addImage(imgData, 'PNG', 0, 0, canvasEl.width, canvasEl.height)
  pdf.save('signed.pdf')
}


Solution

  • According to the fabric.js Quick Start guide, it should be as simple as:

    import { Canvas } from 'fabric';
    
    (...)
    
    const canvas = pdfCanvas.value;
    const fabricCanvas = new Canvas(...);