highlightjs / vue-plugin

Highlight.js Vue Plugin
BSD 3-Clause "New" or "Revised" License
200 stars 28 forks source link

HTML Displays as plain text after build on production server #38

Open 1Map opened 1 year ago

1Map commented 1 year ago

On my local PC (localhost - dev server) the code renders 100%

image image

But on our production server (After build) it shows as plain text.

image image
joshgoebel commented 1 year ago

If there is no error, I would guess that the library is simply not loaded.

1Map commented 1 year ago

If the library is not loaded, how would the text then just magically come in?

PLUGIN

<script>
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'

export default {
    props: ['code'],
    components: {
        highlightjs: hljsVuePlugin.component
    }
}
</script>

<template>
    <div class="hljs-container">
        <highlightjs autodetect :code="code" />
    </div>
</template>

MAIN CODE

<script>
import highlightjs from '@/components/plugins/PluginHighlightjs.vue'
import axios from 'axios'

export default {
    data() {
        return {
            code1: ''
        }
    },
    components: {
        highlightjs: highlightjs,
        ....
    },
    mounted() {
        axios
            .get('/assets/data/widgets/widget-code-1.json')
            .then((response) => {
                this.code1 = response.data
            })
            ....
    }
}
</script>
<template>
    ....
    <highlightjs autodetect :code="code1" />
    ....
</template>

CODE TO LOAD AND DISPLAY (widget-code-1.json)

<card class="text-white p-5px">
  <div style="max-height: 250px" class="overflow-hidden">
    <img src="/assets/img/gallery/widget-cover-1.jpg" alt="" class="card-img" />
  </div>
  <card-img-overlay class="d-flex flex-column bg-gray-600 bg-opacity-75 m-5px" style="z-index: 20">
    <div class="flex-fill">
      <div class="d-flex align-items-center">
        <h6>Youtube</h6>
        <div class="dropdown dropdown-icon ms-auto">
          <a href="#" class="text-white" data-bs-toggle="dropdown"><i class="fal fa-ellipsis-h"></i></a>
          <div class="dropdown-menu dropdown-menu-end">
            <a href="//www.youtube.com/watch?v=_AS5nu4u1ss" class="dropdown-item">View</a>
          </div>
        </div>
      </div>
    </div>
    <div>
      <a href="//www.youtube.com/watch?v=_AS5nu4u1ss" data-lity class="text-white text-decoration-none d-flex align-items-center">
        <div class="bg-red w-50px h-50px rounded-3 d-flex align-items-center justify-content-center">
          <i class="fal fa-play"></i>
        </div>
        <div class="ms-3 flex-1">
          <div class="fw-bold">New Videos - Behind The Forest Tours</div>
          <div class="fs-13px">
            <i class="fal fa-eye"></i> 892 views
            <i class="fal fa-clock ms-3"></i> 39min ago
          </div>
        </div>
      </a>
    </div>
  </card-img-overlay>
</card>
joshgoebel commented 1 year ago

Oh, I wasn't paying attention. This is Vue. In that case, I'm not sure. I'd still guess that the library is not loading perhaps some of your imports are failing in production?

Check the developer console to make sure all the files are loaded and there are no errors?

1Map commented 1 year ago
image
1Map commented 1 year ago

The main problem is that the file loads and gets displayed in both cases (Development and Production). The only problem is on production it displays as just a string and not as tags. See the difference if I inspect it in the Developer Tools:

WORKING LOCAL image

image

NOT WORKING PRODUCTION BUILD image

joshgoebel commented 1 year ago

I understand your description of the problem... as I said:

Check the developer console to make sure all the files are loaded and there are no errors?

This is exactly the behavior one would expect if the library didn't fully load become some of the URLs 404, etc... and I have no idea how you are building or packaging your dependencies, etc.

xiaomaiyun commented 1 year ago

I also encountered the same problem. I think this is a bug. How do you solve it?

joshgoebel commented 1 year ago

Might be, but I have seen no evidence yet that it's a bug. A reproducible example in JSfiddle would go a long way.

1Map commented 1 year ago

You have to load the highlightjs at the main script, example:

main.js or main.ts

import hljs from 'highlight.js/lib/core'
import xml from 'highlight.js/lib/languages/xml'
import hljsVuePlugin from '@highlightjs/vue-plugin'
hljs.registerLanguage('xml', xml)
.....
const app = createApp(App)
....
app.use(hljsVuePlugin)
xiaomaiyun commented 1 year ago

You have to load the highlightjs at the main script, example:

main.js or main.ts

import hljs from 'highlight.js/lib/core'
import xml from 'highlight.js/lib/languages/xml'
import hljsVuePlugin from '@highlightjs/vue-plugin'
hljs.registerLanguage('xml', xml)
.....
const app = createApp(App)
....
app.use(hljsVuePlugin)

I have temporarily solved this problem. The reason is that webpack did not pack the unused code when packing, so quotes it here.

import 'highlight.js/styles/atom-one-dark.css'
import hljsCommon from 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
. . . 
const app = createApp(App)
. . .
// 注意:解决Vue使用highlight.js build打包发布后样式消失问题,原因是webpack在打包的时候没有把未被使用的代码打包进去,因此,在此处引用一下,看似无意义实则有用
hljsCommon.highlightAuto('<h1>Highlight.js has been registered successfully!</h1>').value
app.use(hljsVuePlugin)
. . .
Trinovantes commented 1 year ago

This is expected behavior as webpack will treeshake unused imports out of the bundle in production. If you are not planning on using hljsCommon object in your code (i.e. use the default settings), then you should use a side-effect import:

import 'highlight.js/lib/common'; // side effect import will not be optimized out by webpack
import hljsVuePlugin from "@highlightjs/vue-plugin";

const app = createApp(App)
app.use(hljsVuePlugin)
app.mount('#app')
xiaomaiyun commented 1 year ago

This is expected behavior as webpack will treeshake unused imports out of the bundle in production. If you are not planning on using hljsCommon object in your code (i.e. use the default settings), then you should use a side-effect import:

import 'highlight.js/lib/common'; // side effect import will not be optimized out by webpack
import hljsVuePlugin from "@highlightjs/vue-plugin";

const app = createApp(App)
app.use(hljsVuePlugin)
app.mount('#app')

But,I am planning on using hljsCommon object in my code,how should i set? Following the code sample you provided will not work after packaging to the server!

Trinovantes commented 1 year ago

You need to provide a minimum reproduction repo as there's not enough information