Can't build Gridsome website with Vue2 Smooth Scroll - vue.js

It works in develop mode but it does not build: 'ReferenceError: window is not defined'
I do understand it is a problem with SSR support, although it says it has support to it
I have tryed to implement some similar approaches of integration as seen here:
https://gridsome.org/docs/assets-scripts/#without-ssr-support
Import Vue-Navigation-Bar in Gridsome
I've tryed a lot of approaches in main.js and my template.vue files, but I'm failing to understand the logic for adapting the solution perfectly.
My last approach which worked on develop:
On my template.vue file:
<section id="cover"></section>
<ClientOnly><p class="text-light">Text <a :href="href" class="text-light under" v-smooth-scroll="{ duration: 1000, updateHistory: false }">click here</a></p></ClientOnly>
<script>
import Vue from 'vue'
import vueSmoothScroll from 'vue2-smooth-scroll'
Vue.use(vueSmoothScroll)
</script>
Also have tryed to set 'container' option to '#app' or '#body' added to the body, but it didn't work not even in develop.

OK, I could find it here:
https://github.com/gridsome/gridsome/issues/180#issuecomment-513550238
It doesn't need <ClientOnly></ClienteOnly> tags in template.vue file
In main.js, I have made this changes:
//import vueSmoothScroll from 'vue2-smooth-scroll'
//Vue.use(vueSmoothScroll);
export default function (Vue, { router, head, isClient }) {
...
if (process.isClient) {
const vueSmoothScroll = require('vue2-smooth-scroll').default;
Vue.use(vueSmoothScroll);
}
}

Related

Vue2Editor not working in Nuxt app when accessing page directly

I'm using Vue2Editor in my Nuxt app on a single page. Whenever I test the app and navigate to the page from another page on the app, it loads fine without any issues. But when I test and try to open that page directly, the app fails with the following error. I've tried to dynamically import the vue-editor package but that hasn't worked so far. Any ideas how I can make this import work on the page when trying to directly access it?
nuxt.config.js
plugins: [{src: './plugins/vue2-editor', ssr: true}]
plugins/vue2-editor.js
import Vue from 'vue'
if (process.BROWSER_BUILD) {
const VueEditor = require('vue2-editor')
Vue.use(VueEditor)
}
my_page.vue
<template><div><vue-editor></vue-editor></div></template>
<script>
...
import { VueEditor } from 'vue2-editor';
components: {
VueEditor
}
...
</script>
Can you try it wrapping the component to be client side only?
Problem comes that when you access directly to the page you are Server Side Rendering and document doesn't exists on server.
<client-only><vue-editor/></client-only>
If not working try setting the plugin as ssr: false
plugins: [{src: './plugins/vue2-editor', ssr: false}]
You can import locally, on the client with the following
export default {
components: {
[process.browser && 'VueEditor']: () => import('vue2-editor'),
}
}
Rather than having it defined globally (especially if you use it only in a few pages).
Otherwise, wrapping it in between <client-only> tags could be a good idea too.
More detailed answer available here.

How to make a dynamic import in Nuxt?

In my nuxt component I want to use the ace editor:
import Ace from "ace-builds/src-noconflict/ace"
when the component is mounted I am doing the following:
this.editor = Ace.edit...
Obviously the window is not defined on the server on page reload. But unfortunately I just can't find a solution to fix this issue.
Is there a way to import a package on the mounted() hook?
I already tried
const Ace = require("ace-builds/src-noconflict/ace")
But that doesn't quite seem to work. Do you have any ideas to solve this issue?
I already tried to register a plugin plugins/ace.js:
import Vue from "vue"
import Ace from "ace-builds/src-noconflict/ace"
Vue.use(Ace)
registered it in nuxt.config.js:
plugins: [
{ src: "~/plugins/ace", mode: "client" }
],
But how do I use Ace in my component now? It is still undefined...
Since the error was thrown during the import statement, I'd recommended using dynamic imports as explained in my other answer here.
async mounted() {
if (process.client) {
const Ace = await import('ace-builds/src-noconflict/ace')
Ace.edit...
}
},
From the official documentation: https://nuxtjs.org/docs/2.x/internals-glossary/context
EDIT: I'm not sure about Ace and it's maybe a drastic change but you may also give a look to vue-monaco which is elbow-to-elbow popularity wise (vanilla Monaco editor).
EDIT2: mounted actually only runs on the client so you could strip the process.client conditional. Meanwhile, I do let it here in case you want to run some logic in other hooks like created (which are run on both server + client). More info here.
EDIT3: not directly related to the question, but some packages expose a component which is only available on the client-side (no SSR support), in those cases you could import the component only on the client side and easily prevent any other errors.
Nuxt Plugin
IMHO you were on the right track with the "plugin" solution. Only mistake was the
Vue.use(Ace) part. This only works for vue plugins.
The plugin file could look somewhat like that:
import Ace from 'ace-builds/src-noconflict/ace'
import Theme from 'ace-builds/src-noconflict/theme-monokai'
export default ({ app }, inject) => {
inject('ace', {
editor: Ace,
theme: Theme
})
}
Then you could use this plugin and initiate the editor in a component this way:
<template>
<div id="editor">
function foo(items) {
var x = "All this is syntax highlighted";
return x;
}
</div>
</template>
<script>
export default {
data () {
return {
editor: {}
}
},
mounted () {
this.editor = this.$ace.editor.edit('editor')
this.editor.setTheme(this.$ace.theme)
}
}
</script>

Calendly widget doesn't work after page refresh when live

The calendly widget works at first, but if you refresh the page it stops working but only when the website is live. In local development, no such issue occurs.
Also noticed that when I route to the page through navigation, it works. But if I enter the link to the specific page directly, it doesn't work.
Here's the code:
<template>
<client-only>
<vue-calendly url="link" :height="650"></vue-calendly>
</client-only>
</template>
<script>
import Vue from 'vue';
export default {
created() {
if (process.isClient) {
const VueCalendly = require('vue-calendly').default;
Vue.use(VueCalendly);
}
}
};
</script>
The Vue application is running on Gridsome so it's SSR. I set the widget to only display in client side. Not sure what the issue is.
There is a solution possible to integrate Calendly without using their widget. You can try it as well. This solution should not produce the error mentioned and was tried in an SSR application.
<template>
<!-- Calendly inline widget begin -->
<div class="calendly-inline-widget" data-url="YOUR_CALENDLY_URL" style="min-width:320px;height:630px;"></div>
<!-- Calendly inline widget end -->
</template>
<script>
export default {
mounted () {
const recaptchaScript = document.createElement('script')
recaptchaScript.setAttribute('src', 'https://assets.calendly.com/assets/external/widget.js')
document.head.appendChild(recaptchaScript)
}
}
</script>
From this link, we can see that he is importing the component with
import Vue from 'vue';
import VueCalendly from 'vue-calendly';
Vue.use(VueCalendly);
Then with
<vue-calendly url="your Calendly URL" :height="600"></vue-calendly>
I'm not sure if you are trying to use a syntax like es2020 import here but the require('vue-calendly').default is probably the issue here.
Try importing it in the basic way as suggested above, and then you will be able to make some lazy-loading of it later on if you wish.
Also, you may use your devtools to see why your Calendly instance is not present.
Addy Osmani did a great article on how to import on interaction if you're interested into optimizing your loading time. If it's not that much needed, simply use the usual method or even simpler, load the vanilla JS solution.

Can not read property "document" of undefined - ApexCharts

I'm attempting to import apexcharts into my nuxt project. I've used both the vanilla lib and vue wrapper.
Simply importing the library causes the following error
Like I said, i've attempted importing both
import ApexCharts from "apexcharts"
and
import VueApexCharts from "vue-apexcharts"
Both return the same error.
Is this something I have to configure in the nuxt.config.js file?
This is because you are using Nuxt.js which does SSR for you. Since document does not exist on the server-side it will break.
To work around it there a couple of approaches:
First you can create a plugin/apex.js which is responsible for registering your components
import Vue from 'vue';
import ApexChart from 'vue-apexcharts';
Vue.component('ApexChart', ApexChart);
and in your nuxt.config.js make sure to load the plugin file on the client-side:
module.exports = {
// ...
plugins: [
// ...
{ src: '~/plugins/charts', ssr: false }
],
// ....
};
Now you can reference the ApexChart component anywhere in your app, also make sure to wrap it with ClientOnly component to prevent Nuxt from attempting to render it on the server-side:
<ClientOnly>
<ApexChart type="donut" :options="chartData.options" :series="chartData.series" />
</ClientOnly>
The other approach is you can import Apex charts as async components, which do not get rendered on the server-side, but it has been a hit and miss with this approach, feel free to experiment.
Generally when using Nuxt or any SSR solution, be careful of the libraries you use as they might have an implicit dependency on the execution environment, like requiring browser-specific APIs in order to work like window or document.

Unknown html tag warning of Bootstrap-Vue.js support in WebStorm

I'm using WebStorm 2017.2.4 and webpack Vue.js project. I have added bootstrap-vue.js to my project and would like to see hints for it and components support.
But instead of that I have got "Unknown html tag" warning.
BTW: bootstrap-vue works as expected when running project.
Do you have any suggestions how to make it work?
UPDATED on 2019/07/30
PHPShtorm(WebStorm) was updated to 2019.2 and now they added better support for vuejs libraries:
https://blog.jetbrains.com/webstorm/2019/07/webstorm-2019-2/#development_with_vue
I've just tested and it works.
OLD answer
I solved this issue by adding components manually.
According to: https://bootstrap-vue.js.org/docs/#individual-components-and-directives
I created new file, e.g. bootstrap.js then register globally components which required
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
import Vue from 'vue';
import navbar from 'bootstrap-vue/es/components/navbar/navbar';
import container from 'bootstrap-vue/es/components/layout/container';
// ...
Vue.component('b-navbar', navbar);
Vue.component('b-container', container);
// ...
It work for me in phpstorm 2018.1
Bootstrap vue uses very dynamic way of defining components. I am using PyCharm with vuejs extension which is unable to resolve the components when registered using
import { Layout } from 'bootstrap-vue/es/components'
Vue.use(Layout)
What I use to do is make a new file bootstrap.js in components directory, and register all bootstrap components I would use like
import Vue from 'vue'
import bContainer from 'bootstrap-vue/es/components/layout/container'
import bRow from 'bootstrap-vue/es/components/layout/row'
import bCol from 'bootstrap-vue/es/components/layout/col'
Vue.component('b-container', bContainer);
Vue.component('b-col', bCol);
Vue.component('b-row', bRow);
and then import this file in main.js
import './components/bootstrap'
Just a little cleaner solution.
#Updated: There're two ways to fix "Unknown html tag" warning: (Global and Local Registration)
Global Registration :
You should have to register your component globally Vue.component(tagName, options) before creating the new Vue instance. For example:
Vue.component('my-component', {
// options
})
Once registered, a component can be used in an instance’s template as a custom element, <my-component></my-component>. Make sure the component is registered before you instantiate the root Vue instance. Here’s the full example:
HTML:
<div id="example">
<my-component></my-component>
</div>
JS:
// global register
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// create a root instance
new Vue({
el: '#example'
})
Which will render HTML::
<div id="example">
<div>A custom component!</div>
</div>
Local Registration :
You don’t have to register every component globally. You can make a component available only in the scope of another instance/component by registering it with the components instance option:
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// <my-component> will only be available in parent's template
'my-component': Child
}
})
The same encapsulation applies for other registerable Vue features, such as directives.
Read more at https://v2.vuejs.org/v2/guide/components.html#Using-Components
#Before Updated:
In WebStorm, a library is a file or a set of files whose functions and methods are added to WebStorm's internal knowledge in addition to the functions and methods that WebStorm retrieves from the project code that you edit. In the scope of a project, its libraries by default are write-protected.
WebStorm uses libraries only to enhance coding assistance (that is, code completion, syntax highlighting, navigation, and documentation lookup). Please note that a library is not a way to manage your project dependencies.
Source: https://www.jetbrains.com/help/webstorm/configuring-javascript-libraries.html
Simply, upgrade WebStorm from version 2017.2.4 to 2017.3 which fixed this issue. It is tested.