It is really easy to use any external javascript with Gridsome. Being a Vue based framework any method of importing external scripts in Vue works out of the box with Gridsome
If you want to use external Vue plugins inside your component without defining it globally you can do so by importing it inside your component and registering it for your component.
Example:
<template>
<Carousel>
<Slide />
<Slide />
</Carousel>
</template>
<script>
import {Carousel,Slide} from 'vue-carousel'
export default {
data() {
return { /* data properties here */ }
},
components: {
Carousel,
Slide
}
}
</script>
If you want to use a external javascript library inside your component you can do so by importing the component and requiring it once Vue components are mounted.
Example:
//MyComponent.vue
<template>
<div v-if="theTime">
</div>
</template>
<script>
import moment from 'moment';
export default {
data() {
return {
theTime: false
}
},
mounted() {
this.theTime = 'The time is ' + moment().format("HH:mm")
}
}
</script>
If you want scripts to be globally available you usually add them to src/main.js
.
Note: Avoid injecting dependencies globally, and use it only if really necessary. Injecting locally into components is considered a better practice for code splitting.
To use any external Vue plugin with Gridsome. Just import the required plugin and pass the required plugin to Vue using the following function Vue.use
inside your main.js file
Example:
//main.js
import DefaultLayout from '~/layouts/Default.vue'
import VueTypedJs from 'vue-typed-js'
export default function (Vue) {
// Set default layout as a global component
Vue.component('Layout', DefaultLayout)
//Use VueTypedJs plugin inside our project
Vue.use(VueTypedJs)
}
In this example we are importing VueTypedJs
plugin inside our Gridsome project
To use any external library on our Gridsome project you may proxy it to a property of the Vue prototype object. Since all components inherit their methods from the Vue prototype object this will make your external library or libraries automatically available across any and all components with no global variables or anything to manually import.
Example:
//main.js
import DefaultLayout from '~/layouts/Default.vue'
import moment from 'moment';
export default function (Vue) {
// Set default layout as a global component
Vue.component('Layout', DefaultLayout)
//Use Moment.Js library inside our project
Vue.prototype.$moment = moment
}
In this example we have imported moment.js library into our project, now you may use the library in any page
export default {
mounted() {
console.log('The time is ' . this.$moment().format("HH:mm"))
}
}
Note: You could do it this way, but by using Object.defineProperty instead we are able to define our property with a descriptor. A descriptor allows us to set some low-level details such as whether or not our property is writable and whether it shows up during enumeration in a for loop and more. It gives us a distinct advantage that properties created with a descriptor are read-only by default.
Some coffee-deprived developer won't be able to do something silly like this in a component and break everything:
this.$http = 'Assign some random thing to the instance method';
this.$http.get('/'); // TypeError: this.$http.get is not a function
Instead, our read-only instance method protects our library, and if you attempt to overwrite it you will get "TypeError: Cannot assign to read only property".
So you can proxy your library to VuePrototype using Object.defineProperty in the following way:
//src/main.js
import DefaultLayout from '~/layouts/Default.vue'
import moment from 'moment';
export default function (Vue) {
// Set default layout as a global component
Vue.component('Layout', DefaultLayout)
//Use Moment.Js library inside our project
Object.defineProperty(Vue.prototype, '$moment', {
value: moment
});
}
While gridsome build
Gridsome uses server side rendering to create a fully rendered page. So if your Vue component does not support SSR or your external library like jquery
changes the DOM
element it won't be rendered properly. For these type of components we suggest you to bind the component inside <ClientOnly></ClientOnly>
tag and import library inside Vue's mounted()
function.
For Example to use Vue-carousel
that does not yet support SSR you can do the following
<template>
<Layout>
<ClientOnly>
<carousel :perPage="1">
<slide>
Hello World
</slide>
<slide>
Gridsome is awesome
</slide>
</carousel>
</ClientOnly>
</Layout>
</template>
<script>
export default {
name: 'Index',
components: {
Carousel: () =>
import ('vue-carousel')
.then(m => m.Carousel)
.catch(),
Slide: () =>
import ('vue-carousel')
.then(m => m.Slide)
.catch()
},
}
</script>
This will stop SSR from rendering the component, and component is displayed after the Vue components are mounted.
Same way you can use any external library that causes issue in server side rendering like jquery
<template>
<Layout>
<div class="landing-page">
</div>
</Layout>
</template>
<script>
// import $ from 'jquery'; //import it inside main.js
export default {
name: 'Index',
mounted() {
//require our external library and load it in window
window.owl = require('owl-carousel')
window.$ = require('jquery')
// This works now
$('.some-carousel').owlCarousel()
}
}
</script>
Note: You should avoid using external library like jquery
that manipulates the DOM and try using a Vue Plugin instead.