How to use Prism.js with Vue

This is a bit of a short post, but it took me longer than anticipated to realise where I was going wrong with getting Prism.js to work with Vue, so I thought I'd share.

My content often contains code snippets that need to look nice, and I tried using the only two Prism.js Vue components that I could find but for whatever reasons, they weren't playing nice with content that was being loaded in via Contentful. I spent a bit of time researching and seeing what wasn't working.

Turns out, it's actually quite easy.

First, install Prism.js:

npm install prismjs --save-dev

In your component, import the Prism Javascript and CSS:

<template>
  <div>
    // component...
  </div>
</template>

<script>
import Prism from 'prismjs'
import 'prismjs/themes/prism.css'

export default {}
</script>

At this point, Prism.js has been added successfully, but you may notice that nothing is happening - this is because when you import Prism you have to initiate it manually using the API by adding a single line within mounted(). There are many options for Prism, but the easiest way to get up and running is to just use highlightAll():

mounted() {
  Prism.highlightAll()
}

Great! Prism is now being utlised. At this point, not much more has happened visually. Your code might be formatted, but it'll lack syntax highlighting. The last thing that you need to add language support by importing each required language individually. I don't think that this is really stated anywhere, but you can get an idea of the names of files you have to import by checking out a Prisms listing on a CDN website.

import Prism from 'prismjs'

import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-liquid'
import 'prismjs/components/prism-markdown'
import 'prismjs/components/prism-markup-templating'
import 'prismjs/components/prism-php'
import 'prismjs/components/prism-scss'

The same applies for any additional themes, just check out the CDN listing and import the themes as required. In my case, I used a nice additional theme from the Prism Theme GitHub Repo and added the CSS directly to my SCSS partials.

Part of me feels that this is wildly inefficient, given the amount of bundling we're doing given that most blog posts would include only 2-3 different language snippets.

If I were to extend this, it would be cool to parse the blog post for any language-x classes and dynamically import Prism.js language support based on whatever is actually being used on that post.

That's it! That's how you add Prism.js syntax highlighting to a Vue project.

The full code sample for the copy & pasters:

<template>
  <div>
    // My amazing component
  </div>
</template>

<script>
import Prism from 'prismjs'

import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-liquid'
import 'prismjs/components/prism-markdown'
import 'prismjs/components/prism-markup-templating'
import 'prismjs/components/prism-php'
import 'prismjs/components/prism-scss'

import 'prismjs/themes/prism.css'

export default {
  // code ...
  mounted() {
    Prism.highlightAll()
  }
}
</script>