PDFTron is now Apryse. Same great products, new name.

How to Build a PDF Viewer With Vue.js

By Andrey Safonov | 2019 Jul 08

Sanity Image
Read time

4 min

Vue.js is a JavaScript framework used to build web user interfaces. Along with Meta's React (formerly Facebook's React), it is one of the most popular repositories on GitHub.

The article guides you through using Vue.js to display PDFs and to enable signing, review and approval, redaction, and more. We’ll discuss some open-source libraries you can use to build your Vue.js PDF viewer. Then, we’ll explain how to integrate Apryse’s WebViewer with Vue to add these capabilities inside a single secure environment that also manages version control.

The source code for this project is available in our GitHub Repository.


(Feel free to skip ahead if you’re already a Vue expert.)

Open-Source Libraries to Create the PDF Viewer

There are several open-source PDF libraries available for Vue. But two of the most popular are vue-pdf and vue-pdf-embed. Here’s a quick look at each:


With over 28k weekly downloads on npm, vue-pdf is the most popular Vue package for PDFs, as most users find it easy to set up and use.

However, there are a few caveats with this package:

  • There is no support for Vue 3
  • Memory consumption can be very high
  • It may not be under active development
  • There is no existing documentation


The similarly named vue-pdf-embed comes in close behind vue-pdf in popularity, with about 21k weekly downloads, possibly due to support for both Vue 2 and Vue 3. It handles password-protected documents and can be used directly in the browser, among several other features. Perhaps most importantly, it is still in active development, meaning bugs or issues are more likely to be resolved.

There are two disadvantages to this package: there's no support for Vue 1, and it lacks version control.

How to Build a Vue PDF Viewer with Apryse WebViewer

WebViewer comes with a pre-built Vue sample specifically designed for integrating into a Vue project. This gives you a range of customizable options so you can:

  • Create custom annotations
  • Change annotation appearance
  • Customize annotation behavior
  • Provide internationalization through JSON language files
  • Use a rich set of APIs for more advanced customization

Use the following steps to integrate Vue.js with Apryse WebViewer.

Install Vue CLI

Once you’ve installed Node.js, open up your terminal and type in the following to install the Vue CLI globally.

Now navigate to where you want the project to be created. You will then have two options: You can create and configure your project using a terminal, or via the stylish GUI.

npm install -g @vue/cli

If you want to use terminal type in:

vue create webviewer-vue-sample

If you want to use the GUI:

vue ui

Vue will then download all the necessary dependencies and create a project directory. For this example, we stick with the defaults. If you get stuck with any of the steps, please visit the official documentation.

Navigate into your project directory and open it with your preferred code editor.

Vue.JS App Structure

Inside of your project directory, it will be broken down into the following structure:


Assets inside this folder will be simply copied and not bundled by webpack. For example, favicon and index.html of our app live here.


This source directory contains assets and components, the building blocks of our application.

As a rule, most assets should be placed inside of src/assets. This ensures assets are minified and bundled together to eliminate extra network requests and embarrassing 404s, while ensuring old versions will not be cached. Store assets in the public folder only in a few situations, such as when you need a file with a specific name/structure in the build output.

Read more about handling HTML and static assets inside of a Vue app.


This tells the node package manager (npm) which dependencies need to be downloaded.

Adding WebViewer Component

Next, we will modify our Vue project to add WebViewer as a component, to use as our PDF viewer with Vue.js. We’ll go through each file and modification in sequence.


Inside of package.json add two lines that will download WebViewer as a dependency to our project. Find the scripts section inside of package.json and add postinstall, download-webviewer scripts that will download WebViewer:

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "postinstall": "npm run download-webviewer",
    "download-webviewer": "npx @pdftron/webviewer-downloader"

By default, the WebViewer downloader will download and extract all the necessary files to public/lib. This is normally where we want them to be. However, if you would like to change the directory to — for example —public/webviewer/lib, you can do so by adding:

"download-webviewer": "npx @pdftron/webviewer-downloader --webviewerLocation ./public/webviewer/lib"

Note, it has to be inside of the public folder to preserve the folder structure. WebViewer is smart at only requesting the necessary resources when it needs to.


Inside of our index.html we need to add a script tag that points to webviewer.min.js:

<script src="<%= BASE_URL %>lib/webviewer.min.js"></script>

The BASE_URL variable is handled by the html-webpack-plugin and will change whether it is your local dev environment or production.


Create a new component called WebViewer.vue under src/components.

  <div ref='viewer'></div>

/* eslint-disable */
export default {
  name: 'WebViewer',
  props: {
    path: String,
    url: String
  mounted: function () {
            path: this.path,
            initialDoc: this.url, // replace with your own PDF file
          }, this.$refs.viewer).then((instance) => {
            // call apis here

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
div {
  width: 100%; 
  height: 100vh;

Here’s how the above code works:

The template section is responsible for binding the data and rendering the DOM to the Vue instance's data. In this case, we are adding our viewer div so we can mount WebViewer to use as our Vue.js PDF reader.

The script section allows us to declare WebViewer as a Vue component. It also lets us pass in the path to WebViewer’s lib folder location, as well as the initial PDF we want to load.

Next, inside the ‘mounted’ lifecycle method (which gets called when the element is mounted) we call the WebViewer constructor and use the passed-in properties.

When WebViewer is initialized, it returns an instance of WebViewer that can be used to call a number of useful APIs for document creation, manipulation, annotation, collaboration, redaction, and more.

Learn more about WebViewer’s comprehensive functionality by diving into the documentation. For example, WebViewer is capable of loading files from a URL, blob, file system and base64 data.

Lastly, the style section helps us apply custom CSS like width and height on the viewer’s div element which WebViewer gets mounted on.


Here we can add our newly created WebViewer component.

Inside of the template section, let us add our WebViewer component and pass in the path to WebViewer's lib folder and URL to a PDF we want to load.

  <div id="app">
    <WebViewer :path="`${publicPath}lib`" url="https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf"/>

Inside the script section, let’s import the WebViewer component and declare it in the export statement.

import WebViewer from './components/WebViewer.vue'
export default {
  name: 'app',
  components: {
  data () {
    return {
      publicPath: process.env.BASE_URL

Now, back in our terminal we can run npm install to install our dependencies and download WebViewer.

cd webviewer-vue-sample
npm install

After the command finishes, you can start your application by running:

npm run serve

To “vue” your app (pun intended), navigate to http://localhost:8080!


In this blog, we showed you how to create a Vue.js PDF viewer by adding Apryse's WebViewer inside a Vue app using Vue CLI 3.3. The Vue framework is easy and fun to work with. We thank the Vue team for their hard work!

You can download the complete working sample here on GitHub.

To get started with Apryse’s WebViewer download a free trial. If you have any questions about integrating Apryse into your project, feel free to contact us and we'll be more than happy to help!

You can reach out to me here via email.

Sanity Image

Andrey Safonov

Share this post