-
-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contents not rendered at server-side with nuxt. #1917
Comments
Hi, Yes this is expected at this stage, this why the documentation ask to load it on the client side: https://github.com/LeSuisse/vue-dompurify-html/tree/vue-legacy#usage-with-nuxt To make it work, it requires to initialize DOMPurify with JSDOM since there is no DOM to manipulate when running server side. I will take a look to make possible to choose how DOMPurify is initialized so it is possible to get a DOMPurify instance with JSDOM and publish a proper Nuxt module to ease the installation/setup process. That being said I'm not sure to understand the use case of DOMPurify/vue-dompurify-html in a SSG scenario. Do you not control all the inputs in this situation? |
Hey (and thanks for responding so quickly!), here's a simplified way of how I'm using it in a vue component <template>
<article>
<div dompurify-html="item.richtext"></div>
</article>
</template> and of course, following the docs, it's added on {
//...
plugins: [
// ...
{ src: '~/plugins/vue-dompurify-html', mode: 'client' },
],
}
If I understand your question correctly, then yes, I control the input (here I think I'm doing everything the standard way. Please let me know if I should do things differently or if there's a way to fix my issue. Also, let me know if there's any more info that would be helpful. |
OK got it, it makes sense to me now. You are pulling untrusted data at build time.
For now the only solution is to use it client side. |
Understood. Thanks for letting me know. I'll watch this issue in case the feature is added in the future. It's worth sharing here, that many (most?) nuxt users fetch page data from a CMS, which very often contains HMTL (as rich text that non-technical CMS users author on a CMS word-like text editor) that needs to be injected into the page and be present at server-side generation. And of course, given that injected HTML is expected to be everywhere for CMS-driven websites, sanitization on every page is a no-brainer. So I'm impressed this issue hasn't come up before, because it sounds to me that my use case should be the main "target group" of this plugin. I could be wrong of course. Thanks for taking the time to respond! 🙏 |
This make possible for server-side users (e.g. Nuxt) to instantiate DOMPurify with JSDOM. See #1917.
This make possible for server-side users (e.g. Nuxt) to instantiate DOMPurify with JSDOM. See #1917.
This make possible for server-side users (e.g. Nuxt) to instantiate DOMPurify with JSDOM. The README has been update to describe the setup. See #1917.
This make possible for server-side users (e.g. Nuxt) to instantiate DOMPurify with JSDOM. The README has been update to describe the setup. See #1917.
Hi, I did some changes to expose the necessary primitive so the directive can be also used on the server side. You can see the setup here: https://github.com/LeSuisse/vue-dompurify-html/tree/vue-legacy#server-side I will take a look to provide a Nuxt module for the v3 to make the setup easier. |
Hi @LeSuisse, I'm trying to implement this solution with nuxt v2.15.8 and vue v2.6.14. As @maninak I'm using Strapi in my project and I'm using also richText components, so I'm pulling HTML at build time.
import DOMPurify from 'dompurify'
import { buildVueDompurifyHTMLDirective } from 'vue-dompurify-html'
...
render: {
bundleRenderer: {
directives: {
'dompurify-html': (el, dir) => {
const insertHook = buildVueDompurifyHTMLDirective({}, () => {
const window = new JSDOM('').window
return DOMPurify(window)
}).inserted
insertHook(el, dir)
el.data.domProps = { innerHTML: el.innerHTML }
},
},
},
} BTW, I also had to extend nuxt's webpack to load the vue-dompurify-html mjs module due to this error:
I extended webpack config with: (in ...
build: {
extend(config, ctx) {
config.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: 'javascript/auto',
})
},
},
... I'm arrived to this issue looking for a solution of this error:
This error doesn't happen if I don't use the Please, can you tell me what I'm doing wrong? |
The import issue are likely caused by the v3 since we are now also publishing ESM with the package. That being said I'm a bit surprise you are using
I would suggest to try with vue-dompurify-html 2.6.0 to see if you have the same issue.
Anyway something might be broken with Nuxt and Vue 2.7 with |
@LeSuisse thanks a lot for getting back to me. |
@osroca |
Thanks for the PR @serialine! |
@LeSuisse did you already try to get this to run in nuxt 3 when using SSR mode? It looks like the bundleRenderer is not as easily accessible anymore compared to Nuxt 2, though maybe I haven't found the right documentation, yet. I'll fiddle around in the next days, but I'd appreciate any information that you have. Thank you. |
No I did not but it seems it is possible to use https://nuxt.com/docs/guide/directory-structure/plugins#vue-directives |
Nuxt 3 SSR support would be awesome. |
I have used this code to create Nuxt 3 server plugin. import { JSDOM } from "jsdom";
import createDOMPurify from "dompurify";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive("dompurify-html", {
getSSRProps(binding) {
const createDomPurifyInstance = () => {
const window = new JSDOM("").window;
return createDOMPurify(window);
};
const dompurifyInstance = createDomPurifyInstance();
const innerHTML = dompurifyInstance.sanitize(binding.value);
return {
innerHTML,
};
},
});
}); Note: I do not pass config/options/directive args to |
Running into the same issue in Nuxt 3. It would indeed be very nice to get a Nuxt 3 plugin for this. I cannot get the example above by @marcinkozaczyk to work either. Elements using the directive just turn out empty after being server-side rendered, so I'm getting lots of hydration mismatches everywhere. If I add Might be related to this? vuejs/core#8112 |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as spam.
This comment was marked as spam.
I think you are correct. I am not sure what possibilities we have (at least while keeping the directive API approach) to manage the server side rendering if we cannot manipulate the DOM via In the meantime I added a bit of documentation and example to at least cover the client side part: https://github.com/LeSuisse/vue-dompurify-html/tree/main/packages/vue-dompurify-html#usage-with-nuxt-3 |
Thanks, but It not works and show error tips, you can view the nuxt issues: export default defineNuxtPlugin((nuxtApp) => { to solve the problem, It works! but another problem appear, for example I will use highlight.js directive the sametime |
I tried to be creative and solve this by parsing the sanitized HTML and supply it as childNodes in |
Vue 3.4.36 has a fix, see Evan’s comment on vuejs/core#8112 (comment) Can someone test if this works now? |
Nice, I can take a look next week. |
hi there, do you have any update? |
@LeSuisse, sorry for tagging you. Could you please review the linked PR? 😉❤️ |
Hello,
thanks for the great plugin!
It seems that when doing static site generation (SSG) on the server-side (I suspect it also applies for the SSR use case), any HTML injected into the dom via
dompurify-html
will not be present in the pre-rendered HTML.Sure, the content will be added to the DOM after the initial page visit at hydration time, but that causes multiple layout shifts as content come into the page increasing our CLS performance metric massively, not only offering a worse experience to the users but also affecting our SEO ranking. Another (possible) SEO hit comes more directly because the original HTML is missing crucial content.
FYI I've already seen this closed MR #591
Tested with
vue-dompurify-html v2.5.0
The text was updated successfully, but these errors were encountered: