A Modern Site Generator for Vue.js
Maria Fernana Serna Arboleda
Co-Organizer MedellinJS
https://mafe.dev 💻
Javascript Developer 🤓
A Dynamic website is a collection of dynamic web pages whose content changes dynamically. It accesses content from a database or Content Management System (CMS).
Better Performace
Higher Security
Cheaper, Easier Scaling
Better Developer Experience
JavaScript
Any dynamic programming during the request/response cycle is handled by JavaScript, running entirely on the client.
APIs
All server-side processes or database actions are abstracted into reusable APIs, accessed over HTTPS with JavaScript
Markup
Templated markup should be prebuilt at deploy time, usually using a site generator for content sites, or a build tool for web apps.
Gridsome is a modern website development framework for creating fast and secure websites that can be deployed anywhere. Static HTML files are generated to create SEO-friendly markup that hydrates into a Vue.js-powered SPA once loaded in the browser.
Bring your data
Build
Deploy
CMS: Any Headless CMS, Contentful, WordPress, Drupal, Sanity.io, etc.
Data: Any APIs, Databases, AirTable, YAML, CSV, JSON, etc.
Markdown: Any Git-based CMS, Forestry, Netlify CMS, Blogs, Documentation.
Centralized data management
powered by GraphQL
Static Web Hosts & CDNs
Netlify, AWS Amplify, Zeit Now, Amazon S3, Surge.sh, Aerobatic, Now.sh & many more.
1. Install the Gridsome CLI tool
2. Create a Gridsome project
3. Start the local dev server
yarn global add @gridsome/cli
gridsome create my-gridsome-site
gridsome develop
Open http://localhost:8080
in your browser
.gitignore
package.json
gridsome.config.js
gridsome.server.js
📁dist
📁node_modules
📁src
├─ main.js
├─ 📁layouts
└─ Default.vue
├─ 📁pages
├─ Index.vue
├─ AboutUs.vue
└─ Blog.vue
├─ 📁templates
└─ BlogPost.vue
📁static
module.exports = {
siteName: 'Gridsome',
siteUrl: 'https://www.gridsome.org',
plugins: []
}
This is optional and is for using various parts of the Gridsome Server API.
Local GraphQL data layer
Add data with Source plugins
module.exports = {
plugins: [
{
use: '@gridsome/source-contentful',
options: {
typeName: 'Contentful',
space: 'YOUR_SPACE', // required
accessToken: 'YOUR_ACCESS_TOKEN', // required
host: 'cdn.contentful.com',
environment: 'master'
}
}
]
}
Add data from any APIs
module.exports = function (api) {
api.loadSource(async store => {
// Fetch data from APIs
const { data } = await axios.get('https://scrapp-slide.herokuapp.com/api/scrap/find/mafeserna')
// Create a new GraphQL content type
const posts = store.addContentType({
typeName: 'Talks'
})
// Add data to the new content type
data.map((item) => {
posts.addNode({
id: item.id,
url: 'https://slides.com' + item.url,
slug: item.slug,
viewCount: item.viewCount,
imageUrl: item.imageUrl,
description: item.description
})
})
})
}
Use Markdown for data
module.exports = {
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
path: 'docs/**/*.md',
typeName: 'DocPage'
}
}
]
}
https://localhost:8080/___explore
Preview & test queries from the local data layer
Query
Results
Browse
Schema
<!-- Layout -->
<template>
<div>
<header />
<slot /> <!-- Page content will be inserted here -->
<footer />
</div>
</template>
Layout components are used to wrap pages and templates. Layouts should contain components like headers, footers or sidebars that will be used across the site.
// src/main.js
import Layout from '~/layouts/Default.vue'
export default function (Vue, { head, router, isServer }) {
Vue.component('Layout', Layout)
}
Layout Global
<template>
<Layout>
<h1>About us!</h1>
</Layout>
</template>
<style>
h1 { font-size: 32px }
</style>
<script>
export default {
metaInfo: {
title: 'About us'
}
}
</script>
src/pages/About.vue
https://website.com/about
All .vue files in the src/pages directory will become the pages for your website. The page URL is generated based on the location and name of the file.
Pages are used for normal pages and for listing & paginating GraphQL collections.
<template>
<Layout>
<h1>My blog</h1>
<div v-for="edge in $page.talks.edges" :key="node.id">
<h3>{{ node.slug }}</h3>
<g-link :to="node.id">Read more</g-link>
</div>
</Layout>
</template>
<page-query>
query Talks {
talks: allTalks {
edges {
node {
id
imageUrl
slug
url
}
}
}
}
</page-query>
<template>
<Layout>
<h1 v-html="$page.post.title" />
<div v-html="$page.post.content" />
</Layout>
</template>
<page-query>
query Post ($id: String!) {
post: contenfulPost (id: $id) {
title
content
}
}
</page-query>
<script>
export default {
metaInfo () {
return {
title: this.$page.post.title
}
}
}
</script>
Templates are used for single post views to GraphQL collections.
/blog
/blog/:slug (dynamic)
<template>
<div class="card">
{{ message }}
<button @click="onClick">
Change
</button>
</div>
</template>
<script>
export default {
name: 'Card',
data () {
return {
message: 'Try change me!'
}
},
methods: {
onClick () {
this.message = 'Here you go :)'
}
}
}
</script>
<style>
.card {
padding: 20px;
background: #FFF;
}
</style>
Gridsome uses Vue Single File Components. This means you add HTML, JavaScript and CSS in the same file. This makes your projects easier to maintain and test and your components more reusable.
<template>
<Card />
</template>
<script>
import Card from '~/components/Card.vue'
export default {
components: {
Card
}
}
</script>
<!-- Link with string path -->
<g-link to="/about">About us</g-link>
<!-- Link with variable path -->
<g-link :to="node.path">Read more</g-link>
<g-link> uses Intersection Observer to prefetch linked pages when link is in view. This makes browsing around very fast because the clicked page is already downloaded.
<g-image src="~/image.png" width="500" height="300" />
<g-image> automatically generates an ultra-compressed blurred Base64 image by default and lazy loads the proper image when it's in view.
<g-image> lets you set width, height, and quality in real-time when in development mode, so what you set is what you get.
To deploy a Gridsome site you need a static web host.
Smart link prefetching that uses Intersection Observer to load next pages.
Code Splitting. Only what you need is loaded per page.
Pre-rendered HTML. Nothing beats static HTML on a CDN in speed.
Progressive Images with automatic image compression and lazy loading.
Vue.js SPA Hydration for fast browsing with no page refresh.
Follows the PRPL-pattern for instant page loads.
No need to be a performance expert.
Centralized data management.
Build on the JAMstack 💚
mafe.dev