Skip to content
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

Build fails due to custom directive missing an SSR Transform #92

Closed
VinceG opened this issue Sep 21, 2020 · 22 comments
Closed

Build fails due to custom directive missing an SSR Transform #92

VinceG opened this issue Sep 21, 2020 · 22 comments
Labels
docs Improvements or additions to documentation

Comments

@VinceG
Copy link

VinceG commented Sep 21, 2020

Describe the bug

Adding a simple directive inside a markdown file or an SFC throws an error during the build. Seems like ClientOnly component does not exist yet in VitePress.

Custom directive is missing corresponding SSR transform and will be ignored.

To Reproduce

<div v-test>test</div>


<script>
export default {
  directives: {
    test: {
      mounted(el, binding) {
        console.log(el)
      }
    }
  }
}
</script>

Expected behavior
Build should work even though an SSR implementation for the custom directive doesn't exist.

System Info

  • vitepress version: 0.6.0
  • vite version: v1.0.0-rc.4
  • Node version: 12.18.3
  • OS version: Catalina 10.15.6

Additional context
None.

@VinceG VinceG added the bug: pending triage Maybe a bug, waiting for confirmation label Sep 21, 2020
@kiaking
Copy link
Member

kiaking commented Nov 5, 2020

Hi could you elaborate a bit more on this use case? Why would you paste such code into md file?

@VinceG
Copy link
Author

VinceG commented Nov 5, 2020

@kiaking Of Course. I have the following component written in Vue 3
https://github.com/VinceG/vue-click-away

As part of the component i wrote the documentation in vitepress, if you look at the Gif you'll see the example usage and demo within vitepress. I am trying to deploy it into gh-pages (or anything else really) and while running the production build it fails with the above error message.

The markdown file for the demo looks like this:

https://raw.githubusercontent.com/VinceG/vue-click-away/master/docs/index.md

But the actual code that is failing is located here:
https://github.com/VinceG/vue-click-away/blob/master/index.js

I don't think the markdown file has anything to do with it, vitepress is not able to build for production when there are directives in the codebase. I gave a simple reproduction case above to replicate this issue with a new vitepress setup.

I hope this helps.

EDIT: in Vuepress we have component that probably solves this issue, vitepress however, does not have it.

@kiaking
Copy link
Member

kiaking commented Nov 10, 2020

Oh I see. I haven't checked, but does VuePress support this feature...!? I think you should register that component, and then use it inside the markdown.

// .vitepress/theme/index.js

import DefaultTheme from 'vitepress/dist/client/theme-default'
import VueClickAwayExample from './components/VueClickAwayExample.vue'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('VueClickAwayExample', VueClickAwayExample)
  }
}
<!-- index.md -->

# Vue Click Away

<VueClickAwayExample />

@VinceG
Copy link
Author

VinceG commented Nov 10, 2020

@kiaking Hmm, well using it isn't the problem. it's building for production. once i run yarn build it throws the above error

@kiaking
Copy link
Member

kiaking commented Nov 11, 2020

Thanks for the answer! I've confirmed. Yap, it is failing on build time due to the error you described.

I'm not too familiar with the SSR with directives so I have to learn things before we can fix this 😅

@kiaking kiaking added bug Something isn't working and removed bug: pending triage Maybe a bug, waiting for confirmation labels Nov 11, 2020
@yyx990803
Copy link
Member

This is not really a bug, since you do need to provide the corresponding directive transforms to ensure you are rendering correct HTML during SSR. However some directives like click away don't really render any props, so it makes sense to change this to a warning instead of an error in @vue/compiler-ssr.

That said, a client only wrapper component is fairly simple:

import { ref, onMounted } from 'vue'
const ClientOnly = {
  setup(_, { slots }) {
    const show = ref(false)
    onMounted(() => { show.value = true })
    return () => show.value && slots.default ? slots.default() : null
  }
}

@yyx990803 yyx990803 removed the bug Something isn't working label Dec 5, 2020
@VinceG
Copy link
Author

VinceG commented Dec 5, 2020

This is not really a bug, since you do need to provide the corresponding directive transforms to ensure you are rendering correct HTML during SSR. However some directives like click away don't really render any props, so it makes sense to change this to a warning instead of an error in @vue/compiler-ssr.

That said, a client only wrapper component is fairly simple:

import { ref, onMounted } from 'vue'
const ClientOnly = {
  setup(_, { slots }) {
    const show = ref(false)
    onMounted(() => { show.value = true })
    return () => show.value && slots.default ? slots.default() : null
  }
}

@yyx990803 thank you. Any idea how to write those directive transforms? I wasn’t able to find any documentation regarding this.

Also, are there plans to add client only component for vitepress like the equivalent in vuepress?

@yyx990803
Copy link
Member

v3 SSR docs are not fully complete yet, so for now you'll have to read the types here: https://github.com/vuejs/vue-next/blob/master/packages/compiler-core/src/transform.ts#L56

ClientOnly is implemented in 8809d2d and will be available in the next release.

@kiaking
Copy link
Member

kiaking commented Jan 22, 2021

OK cool, since ClientOnly component is here, maybe we should just document to use it when you have component that uses directive option.

@kiaking kiaking added the docs Improvements or additions to documentation label Jan 22, 2021
@Tahul
Copy link

Tahul commented Jan 29, 2021

If anyone lands here by looking on how to update his directive to make it SSR compatible (which is my case), I advise you to take a look at the native directives code from vue-next repository.

Starting at v-show, which is here:
https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/src/directives/vShow.ts

@Tahul
Copy link

Tahul commented Jan 30, 2021

Update:

Even after implementing the getSSRProps on my own directive, I can't get the directive to work with VitePress.

I still get the Custom directive is missing corresponding SSR transform and will be ignored. error.

The same happens when wrapping my directive with a <ClientOnly /> component, which makes me think this might be a bug ?

Even when trying to add an absolute return value in the getSSRProps hook, Vitepress does not seem to handle it.

I tried it this way, so I could debug when the hook is called, and it doesn't seem to be the case.

getSSRProps({ value }) {
  return { style: { backgroundColor: 'blue' } }
}

Maybe this is a wrong implementation on my side, but I think this is closely related to this issue.

If you want me to open another issue for this discussion, please let me know.

Otherwise we might want to switch this back to a bug because the <ClientOnly /> workaround should stay a workaround and not the encouraged method to fix this when you have access to the directive code.

@daief
Copy link

daief commented Feb 18, 2021

Update:

Even after implementing the getSSRProps on my own directive, I can't get the directive to work with VitePress.

I still get the Custom directive is missing corresponding SSR transform and will be ignored. error.

The same happens when wrapping my directive with a <ClientOnly /> component, which makes me think this might be a bug ?

Even when trying to add an absolute return value in the getSSRProps hook, Vitepress does not seem to handle it.

I tried it this way, so I could debug when the hook is called, and it doesn't seem to be the case.

getSSRProps({ value }) {
  return { style: { backgroundColor: 'blue' } }
}

Maybe this is a wrong implementation on my side, but I think this is closely related to this issue.

If you want me to open another issue for this discussion, please let me know.

Otherwise we might want to switch this back to a bug because the <ClientOnly /> workaround should stay a workaround and not the encouraged method to fix this when you have access to the directive code.

Because there should be a directive transforms.

According to this, I find the way to provide the directive transforms to resolve this error.

We can pass directiveTransforms option via vue-loader.

// webpack config
module.exports = {
  module: {
    // ...
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: "vue-loader",
            options: {
              compilerOptions: {
                directiveTransforms: {
                  // <div v-custom-directive />
                  "custom-directive": () => ({
                    props: [],
                  }),
                },
              },
            },
          },
        ],
      },
      // ...
    ],
  },
  plugins: [new VueLoaderPlugin()],
};

Or pass it via compile function.

import { compile } from "@vue/compiler-dom";

const { code } = compile(`<p v-custom-directive></p>`, {
  // ...
  directiveTransforms: {
    "custom-directive": () => ({
      props: [],
    }),
  }, 
});

I got the same error when I use renderToString of @vue/server-renderer with a custom directive and I am not familiar with vitepress.

Hope this helps you. @Tahul

@maxerbox
Copy link

For vite, see vuejs/core#3298 (comment)

@emerxom
Copy link

emerxom commented Jul 10, 2021

I don't know what I am doing wrong but using the ClientOnly don't fix the build problem for me.
I had to remove all custom directives for it to build

@antfu
Copy link
Member

antfu commented Jul 10, 2021

A temporary fix:

https://github.com/vueuse/patch-vue-directive-ssr

@emerxom
Copy link

emerxom commented Jul 12, 2021

A temporary fix:

https://github.com/vueuse/patch-vue-directive-ssr

thanks @antfu
It worked... It was a mistake I made that prevent it from working before.

@murilolivorato
Copy link

I cant understand how vue directives works in VUE 3 . It has 3 weeks that I am trying a solution for that .
@yyx990803 help us =),

I didn't found a documentation about that .
A SPA DIRECTIVE IS LIKE THAT -

  app.directive('color', {
    mounted (el, binding) {
      el.style.color = 'purple'
    }
  })

HOW COULD I DO IT IN SSR ? -

export default (dir) => {
  return {
    props: []
  }
}

I don't understand how can I access this props

@productdevbook
Copy link

A temporary fix:

https://github.com/vueuse/patch-vue-directive-ssr

thank you fixed. I hope there is a permanent solution.

@drewcook
Copy link

drewcook commented Apr 19, 2022

This is still an annoying bug. For reference, this is a bug in vuepress@2.0.0-beta.27 as well, which isn't the latest version at time of posting this, but is definitely newer than these comments and original post here. As in a lot of front end development, we have to install a separate patch package as a workaround, which is great, but is not ideal.

Is this issue going to be fixed or on the roadmap at all?

@brc-dd
Copy link
Member

brc-dd commented Jun 4, 2022

This is not reproducible in VitePress alpha with the below code:

# Hello World

<div v-test>test</div>

<script setup>
const vTest = {
  mounted: (el) => {
    console.log(el)
  }
}
</script>

I am closing this issue for now. If you think that there is still an issue, please let us know.

@mrweiner
Copy link

mrweiner commented Sep 9, 2022

I'm aware that this is closed, but does https://github.com/vueuse/patch-vue-directive-ssr still work for anybody? I've run into this error a few times with userland packages (such as https://github.com/PNKBizz/vue-mutation-observer) and it doesn't seem to help.

@brc-dd
Copy link
Member

brc-dd commented Sep 10, 2022

@mrweiner I don't think that mutation-observer package supports vue@3

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
docs Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests