Why does vue-plyr plugin keep loading on server side - vue.js

I have a nuxt app which uses the vue-plyr plugin to play videos. I've registered the plugin like this
import Vue from 'vue'
import VuePlyr from 'vue-plyr/dist/vue-plyr.ssr.js'
import 'vue-plyr/dist/vue-plyr.css'
Vue.use(VuePlyr, {
plyr: {}
})
and added it to nuxt.config.js
plugins: [
{
src: '~/plugins/plyr.client.js',
mode: 'client'
}
],
but when I import it inside a component
import VuePlyr from 'vue-plyr'
I always get an error saying
document is not defined
The component itself is also wrapped in a <client-only></client-only> tag.
Am i missing something with my implementation?
Is there any other way to import the plugin
I'm using node-14.17.6 and nuxt-2.15.6

You don't need plyr.client.js but plyr.js if you already have mode: 'client'.
Also, why do you import it again if you have it as a plugin? It is globally available so you could start using it directly.
<template>
<client-only>
<vue-plyr>
<div class="plyr__video-embed">
<iframe
src="https://www.youtube.com/embed/bTqVqk7FSmY?amp;iv_load_policy=3&modestbranding=1&playsinline=1&showinfo=0&rel=0&enablejsapi=1"
allowfullscreen
allowtransparency
allow="autoplay"
></iframe>
</div>
</vue-plyr>
</client-only>
</template>
Depending on the code you're using below, you may also check that this is not being called server side as shown here: https://stackoverflow.com/a/67751550/8816585
Updated with a more explicit example.

Related

Nuxt local import client only

I'm trying to use VuePlyr in Nuxt 2. Right now I have it working as a plugin /plugins/vue-plyr.js,
import Vue from 'vue'
import VuePlyr from '#skjnldsv/vue-plyr'
import 'vue-plyr/dist/vue-plyr.css'
Vue.use(VuePlyr)
but it is just used in one page, so I would like to remove it from the main bundle and just import it locally when used. I've tried this in my page (the template part was working when using the plugin).
<template>
<client-only>
<vue-plyr>
<div data-plyr-provider="vimeo" :data-plyr-embed-id="id" />
</vue-plyr>
</client-only>
</template>
<script>
import 'vue-plyr/dist/vue-plyr.css'
import Vue from 'vue'
export default {
async mounted () {
const VuePlyr = await import('#skjnldsv/vue-plyr')
Vue.use(VuePlyr)
}
}
</script>
but unfortunately, I'm getting this error
[Vue warn]: Unknown custom element: <vue-plyr> - did you register the component correctly?
Any idea how I could achieve this? Related with How to make a dynamic import in Nuxt?
You could import it like that
export default {
components: {
[process.client && 'VuePlyr']: () => import('#skjnldsv/vue-plyr'),
}
}
As mentioned in a previous answer.
In your nuxt config define the plugin as client only:
plugins: [
{ src: "~/plugins/vue-plyr.js", mode: "client" }
],
Then also make sure there's a client-only tag around the use of the component:
<template>
<client-only>
<vue-plyr>
<div data-plyr-provider="vimeo" :data-plyr-embed-id="id" />
</vue-plyr>
</client-only>
</template>
Edit: importing the component again in the mounted method isn't necessary if you added it as a plugin

Call app.use for plugin in the component itself in vue 3

I'm building a component library that uses the v-tooltip plugin. So I need to install and use the plugin in the component itself instead using it globally with app.use().
I've read so many posts, and what I've tried so far doesn't work for my case.
I know that I can access the app in the Composition API as:
import VTooltip from 'v-tooltip';
import 'v-tooltip/dist/v-tooltip.css';
const App = getCurrentInstance().appContext.app;
App.use(VTooltip);
but that doesn't work, and I get this warning:
[Vue warn]: Component is missing template or render function.
Any help would be greatly appreciated.
to use this plugin in the component itself, you can try to do something like this:
<template>
<button v-tooltip="/* your code */"> Custom button </button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import VTooltip from "v-tooltip";
export default defineComponent({
directives: {
tooltip: VTooltip.VTooltip,
"close-popover": VTooltip.VClosePopover,
"v-popover": VTooltip.VPopover,
},
});
</script>
Thanks #Rago, you gave me an idea with the directives. The solution was really simple in this case... At the moment v-tooltip is undergoing a package rename (to floating-vue), so with the new plugin you can decide if you want to use a component or a directive.
This is the solution:
<template>
...
<span v-tooltip="help" class="form-help">?</span>
...
</template>
<script>
import 'floating-vue/dist/style.css';
import { VTooltip } from 'floating-vue';
export default defineComponent({
directives: {
tooltip: VTooltip,
},
...
});
</script>
And for the Composition API you just import it, and Vue will automatically detect the directive if you follow the naming convention - putting v in front of the directive:
import 'floating-vue/dist/style.css';
import { VTooltip } from 'floating-vue';
const vTooltip = VTooltip;

Vue plugin not loaded on static site generated by nuxt

In my nuxt.js project I am using a component from a Vue library called vue-tailwind.
I import the library as a plugin in this way (as advised by the author):
/plugins/vue-tailwind.js
import Vue from 'vue'
import VueTailwind from 'vue-tailwind'
Vue.use(VueTailwind)
/nuxt.config.js
plugins: ['~plugins/vue-tailwind']
and the component works perfectly in development.
My problem is that the component is not rendered when I serve the app generated with
nuxt generate
I already tried to load the plugin this way:
{ src: '~plugins/vue-tailwind', mode: 'client' }
and also tried to put the component between client-only tag
<client-only>
<t-datepicker
v-model="date"
:max-date="today"
placeholder="Select a date"
date-format="Y-m-d"
user-format="d-M-Y"
/>
</client-only>
After several attempt, I understood that the component has to be registered in the plugin. Vue.use does not work in generated code.
My final working code is the following:
/plugins/vue-tailwind.js
import Vue from 'vue'
import { TDatepicker } from 'vue-tailwind/dist/components';
Vue.component('t-datepicker', TDatepicker)
I've got the same problem and that could be fixed by setting ssr: false in the nuxt.config.js
export default {
ssr: false,
target: 'static'
}

How to make Vue 3 application without CLI / Webpack / Node

I am trying to make Vue 3 application but without CLI and Webpack.
There is no official documentation yet. On CDN are many versions (vue.cjs.js, vue.cjs.prod.js, vue.esm-browser.js, vue.esm-bundler.js, vue.global.js, vue.runtime.global.js...).
Which one to pick? And how to mount application, old way does not work. There are many online examples how works new Composition API but none how to start project without CLI / Webpack.
Link to Vue 3 CDN:
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
In body:
<div id="app">
</div>
<script type="module">
import app from './app.js'
const {createApp} = Vue;
createApp(app).mount('#app');
</script>
In app.js is simple component:
export default {
name: 'Test',
setup() {
const title = "Hello";
return {
title
};
},
template: `
<div>
<h1>{{title}}</h1>
</div>
`,
};
Instead of one component, app.js can be a container for other components.
I made simple Vue 3 QuickStart template so anyone can see how this works.
Template is in SPA-like style and contains 4 sample pages, 4 components, routing and store. It uses only Vue.js from CDN, everything else is hand made ;)
Note: This is not library, it's just demo code so anyone can see how to mount Vue 3 application and use Composition API in simple scenario.
Online demo: http://vue3quickstart.rf.gd/
GitHub: https://github.com/SaleCar/Vue3-QuickStart
Found in docs: https://vuejs.org/guide/quick-start.html#without-build-tools
Without Build Tools
To get started with Vue without a build step, simply copy the following code into an HTML file and open it in your browser:
<script src="https://unpkg.com/vue#3"></script>
<div id="app">{{ message }}</div>
<script>
Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
The above example uses the global build of Vue where all APIs are exposed under the global Vue variable.
While the global build works, we will be primarily using ES modules syntax throughout the rest of the documentation for consistency. In order to use Vue over native ES modules, use the following HTML instead:
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue#3/dist/vue.esm-browser.js"
}
}
</script>
<div id="app">{{ message }}</div>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
Notice how we can import directly from 'vue' in our code - this is made possible by the <script type="importmap"> block, leveraging a native browser feature called Import Maps. Import maps are currently only available in Chromium-based browsers, so we recommend using Chrome or Edge during the learning process. If your preferred browser does not support import maps yet, you can polyfill it with es-module-shims.
You can add entries for other dependencies to the import map - just make sure they point to the ES modules version of the library you intend to use.
Not for production
The import-maps-based setup is meant for learning only - if you intend to use Vue without build tools in production, make sure to check out the Production Deployment Guide.
In addition, as Evan You recommended, Vite(https://madewithvuejs.com/vite) is a good alternative to #vue/cli and webpack. It's still CLI like but more lightweight I think. Fast and supports SFC.

How do I import Three.js into my Nuxt project

I want to import modules in examples folder in THREE.js such as OBJLoader into my Nuxt Project.
I can import main folder of THREE, but error occurs when trying to import modules in examples folder.
Tried these steps in official docs.
https://threejs.org/docs/index.html#manual/en/introduction/Import-via-modules
I'm getting error below
SyntaxError
Unexpected token {
<template>
</template>
<script>
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
export default{
}
</script>
here are my github repository
https://github.com/ksuhara/threejs-test
Finally I could find what was wrong.
Well, it has to do with nuxt building system. When using third parts libs, you should add them into nuxt.config.js bild->transpile array so it can be included as a dependency with Babel.
transpile: [
"three"
]
Ref: https://nuxtjs.org/api/configuration-build#transpile
Threejs must be run on the client side so enclosed the component with <client-only> tag and loaded it dynamically with const MyComponent = () => import('~/path/to/MyComponent.vue'); but now I am getting the error on server side.
Finally I managed to do it like this!
<template>
<div>
<client-only>
<threejs-component />
</client-only>
</div>
</template>
<script>
export default {
components: {
ThreejsComponent: process.browser ? () => import('~/path/to/ThreejsComponent.vue') : null
}
}
</script>
inside ThreejsComponent.vue are all the threejs imports