A step-by-step guide on integrating PDF.js with Vue 3 and accessing the distribution folder locally

I must clarify that I am restricted from using any vue libraries to preview PDFs; only pure pdf.js and vue 3 are permitted.

  • Utilizing pdf.js for presenting PDF files within my vue 3 project.
  • Inquiring about the ideal folder structure for the project to ensure functionality.
  • Currently relying on a cdnjs link for pdf.js; looking to switch to the distribution folder instead.

View distribution folder here

Planning to replace the usage of cdnjs link with the distribution folder mentioned above.

  • Showcasing my current implementation along with examples provided on the official website of pdf.js.

pdf-view.vue

<template>
  <canvas :id="`the-canvas${index}`" style="border: 1px solid"></canvas>
</template>

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

const { file, index } = defineProps(['file', 'index'])

onMounted(() => {
  import('https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.mjs').then((pdfjsLib) => {
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.mjs'

    if (!file) return

    const fileReader = new FileReader()
    fileReader.onload = () => {
      const array = new Uint8Array(fileReader.result)
      const loadingTask = pdfjsLib.getDocument(array)
      loadingTask.promise.then(
        (pdf) => {
          const pageNumber = 1
          pdf.getPage(pageNumber).then((page) => {
            const scale = 1.5
            const viewport = page.getViewport({ scale })

            const canvas = document.getElementById(`the-canvas${index}`)
            const context = canvas.getContext('2d')
            canvas.height = viewport.height
            canvas.width = viewport.width

            // Render PDF page into canvas context
            const renderContext = {
              canvasContext: context,
              viewport: viewport
            }
            page.render(renderContext)
          })
        },
        (reason) => {
          // PDF loading error
          console.error(reason)
        }
      )
    }
    fileReader.readAsArrayBuffer(file)
  })
})
</script>

<style>

</style>

parent.vue

<template v-for="(file, index) in pdfFiles" :key="file">
            <pdfview :file="file.file" :index="index" />
</template>
<script setup>
import pdfview from '@/components/pdf-view/pdf-view.vue'
</script>

Current directory setup

--Project
  -public
  -src
  --components
  ---pdf-view
  ----pdf-view.vue [component]
  ---views
  ----parent.vue [component]

Answer №1

My Solution Steps

  • Download and install pdfjs-dist.

  • npm install pdfjs-dist

  • If you encounter the following error, follow these steps:

Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)

  • To address this issue, modify your vite.config.js file.
  • I discovered a solution from this post. Add the code snippet below to your vite.config.js file.
build: {
    target: "es2022"
  },
  esbuild: {
    target: "es2022"
  },
  optimizeDeps:{
    esbuildOptions: {
      target: "es2022",
    }
  }
  • Next, import the files like this:
import * as pdfjsLib from "pdfjs-dist";
import * as pdfWorker from "pdfjs-dist/build/pdf.worker.mjs";

If you omit the second import, you may encounter the error below.

pdfWorker is not defined

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

Steps for creating a jQuery function that responds to changes in a text box value

Currently, I have a text box containing certain values and a submit button alongside a slider. When I click the submit button, the slider changes. However, I would like to achieve the functionality where instead of clicking the submit button, changing the ...

The Vue.js application appears to be functioning properly with no error messages, however

Currently, I am in the process of learning Vue. Recently, I came across a helpful tutorial that I've been trying to implement using the standard vue-cli webpack template by splitting it into single file components. Despite not encountering any errors ...

Default parameter in Node.js is set when the callback function is the last parameter

Here's a simplified version of the function I'm working with: doSmthg (name, age, callback) { callback(name, age); } I want to set a default value for age if it's not provided. In ES6, I could do doSmthg(name, callback, age=42) {...}, b ...

External function does not support jQuery types

In my theme.js file, I currently have the following code: jQuery(function ($) { accordion($) }) const accordion = ($) => ... By placing the accordion function directly into the jQuery function, Typescript is able to assist with the installed jquery ...

A guide to utilizing asynchandler within a class in Node.js

I'm currently in the process of converting my routers into a class structure, but I'm facing a challenge when trying to wrap the asyncHandler function inside the class. Can anyone provide guidance on how to achieve this? userController.js const ...

React: the value of this.props.item has not been defined

When attempting to pass an array from one component to another and then to a third component, the item is showing up as undefined. In my App.js file, I am trying to pass this.state.searchResults to the SearchResults component. import React from 'rea ...

Utilizing ES6 imports with module names instead of paths

Is there a way to import modules using just their name without the full path? For instance, can I simply use: import ViewportChecker from 'viewport-checker'; instead of import ViewportChecker from '../ViewportChecker'; I'd ...

The Webix component is experiencing a lack of refreshment

function refresh_group_items(){ //console.log("calling1"); window.setTimeout(function(){ $$("cfg").reconstruct() }, 3000); } $.ajax({ type: "POST", xhrFields:{ withCredentials: true }, beforeSend: function(reque ...

I am having trouble getting the unix timestamp to work with Meteor's API, pickadate.js

Based on the information from the API at , I have implemented the following code to retrieve a Unix timestamp based on a selected date. Initially, I configured: $('.startDate').pickadate({ selectMonths: true, selectYears: 15 ...

Incorporate React Components into a traditional HTML, CSS, and JavaScript project

Can I incorporate a React Native Component (https://www.npmjs.com/package/react-native-gifted-chat) into my vanilla JavaScript project? Is it feasible to embed a React Native component within a vanilla JavaScript project? If yes, then what is the process ...

Maintain the value of `this` using a recursive setImmediate() function

Hey there! I'm working on a node.js app where I need to utilize setImmediate() to recursively call a function while maintaining its context for the next iteration. Let's take a look at an example: var i=3; function myFunc(){ console.log(i ...

Implement a transition effect for the onClick event of a div element

I am looking to create a smoother transition effect when clicking on the section, causing it to expand and display the text underneath. I want to make this transition slower and more seamless. My current attempt at adding a transition to the "active" clas ...

Encountering an unexpected error: receiving a void element tag as input in React

Any ideas on how to resolve the following error message: input is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML` Check out my code snippet below: import "./styles.css"; export default function App() { re ...

Guide on inserting a new column into an array of objects in Vue

Below is the fetch method I have defined to retrieve recordings from the database. However, I need assistance in adding a new column to each record specifically for frontend purposes. Can someone help me with this problem? <script> export default { ...

Combining the redux toolkit function createAsyncThunk with Angular's HttpClient by leveraging the ApiService

Currently, I am working on incorporating @reduxjs/toolkit into an Angular project. Is there a way to pass an Angular service as a parameter to the callback of createAsyncThunk instead of utilizing fetch directly? I referenced the documentation for an exa ...

In TypeScript, use a Record<string, any> to convert to {name: string}

I have developed a custom react hook to handle API calls: const useFetch: (string) => Record<string, any> | null = (path: string) => { const [data, setData] = useState<Record<string, any> | null>(null); var requestOptions: Requ ...

The TypeScript Promise error codes TS2304 and TS2529 are causing confusion among

I came across the code below: function asyncTask(): Promise<string> { return new Promise<string>(resolve => resolve); } This code resulted in the following error: TS2304: cannot find name 'Promise' To address this issue, ...

Using VueJS for reactive binding效果

I am attempting to assign a class using the following syntax: :class="{active: favs.medium_title.fontWeight === 'bold'}" However, the fontWeight attribute is not yet defined when the component loads. This is an excerpt from my object: favs: { ...

What could be causing the issue of HTML Button not functioning properly with jQuery Webpack?

I'm currently using webpack to build my HTML and javascript files. I have a function defined in index.js and I've attempted the solutions mentioned here, but none of them seem to work for calling the function onclick button. Here is the HTML cod ...

Display an image in an Angular application using a secure URL

I am trying to return an image using a blob request in Angular and display it in the HTML. I have implemented the following code: <img [src]="ImageUrl"/> This is the TypeScript code I am using: private src$ = new BehaviorSubject(this.Url); data ...