DEV Community

Manda Putra
Manda Putra

Posted on

Membuat static site dengan Nuxt.js

Selamat tinggal website yang dulu...

warning: this site not using this method anymore, since I cant figure it out how to do dynamic SEO in Nuxt.js, more on this information I'll explain in here but you can still use this guide to create Nuxt.js simple blog :)

Hai! πŸ˜ƒ dan selamat datang di blog baru ini sebelumnya maaf jika ini memakan waktu lama hanya untuk website dengan fitur tak banyak ini. JAMStack sendiri sudah cukup lama berkembang sejak saya mengenalnya 2017 lalu melalui sebuah perusahaan bernama netlify yang berhasil me-rework sebuah website yang suka saya kunjungi saat sedang belajar programming sampai sekarang berkarir di dunia ini.

Cukup simple

KISS dengan adanya banyak bantuan dari module di NPM... Cukup simple dan bahkan sebenarnya kita dapat menyelesaikannya satu hari.

Markdown Parsing

Bagian markdown-parsing saya menggunakan markdown-it module ofisial dari nuxtjs. Saya agak mendapatakan sedikit trouble menggunakan mdx padahal menurut saya ini lebih powerfull daripada sekedar parsing. Karena saya menganut filosofi dadi sik update sesuk maka saya memilih markdown-it

// nuxt.config.js

modules: ['@nuxtjs/markdownit'],
markdownit: {
  html: true,
  preset: 'default',
  linkify: true,
  breaks: true
},

Enter fullscreen mode Exit fullscreen mode

dan kita bisa menggunakannya dengan

// vue template you use

<template>
  <div v-html="postContent"/>
</template>

<script>
export default {
  computed: {
    postContent() {
      const post = this.$store.state.post
      // path to filename
      return require(`../../content/post/${post.filename}.md`)
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

Content Title and Blogpost Meta

Untuk hal ini saya manfaatkan YAML front matter pada markdown. Sayangnya markdown-it mendeteksi YAML front matter ini sebagai h2 dan di parse ke html πŸ˜„ jadi ya saya nemu workaround yang paling tidak bekerja di website saya.

// remove yaml from blogpost 😁
mounted() {
  const h2 = document.getElementsByTagName('h2')
  h2[0].outerHTML = ''
}
Enter fullscreen mode Exit fullscreen mode

Kembali ke topik meta tadi untuk parser YAML saya memakai gray-matter sebenarnya ini terlalu powerfull-sih tapi saya tidak bisa menemukan yang lebih simple lagi di NPM. Lalu kita buat simple script untuk men-generate meta kita.

// create-post-list.js

const fs = require('fs')
const matter = require('gray-matter')
// eslint-disable-next-line no-path-concat
const files = fs.readdirSync(__dirname + '/content/post')

console.time('⏲')

const posts = []

for (const i in files) {
  // eslint-disable-next-line no-path-concat
  const str = fs.readFileSync(__dirname + `/content/post/${files[i]}`, 'utf8')
  const post = matter(str).data
  posts.push(post)
}

//  to JSON
const data = JSON.stringify(posts)
fs.writeFileSync('blogposts.json', data)

console.timeEnd('⏲')
Enter fullscreen mode Exit fullscreen mode

Bang! dengan ini kita punya single source of truth yang gampang kita gunakan, adanya blogposts.json ini bisa digunakan juga untuk mempermudah proses generate route di nuxt.config.js

// nuxt.config.js

const blogJSON = require('./blogposts.json')

function generateStaticRoute() {
  const route = []
  for (let i = 0; i < blogJSON.length; i++) {
    // add /blog in frot of string
    const blog = blogJSON[i].slug.replace(/^/, '/blog/')
    route.push(blog)
  }
  return route
}

// pages routes automaticaly generated with nuxt πŸš„
module.exports = {
  generate: {
    routes: generateStaticRoute()
  }
}
Enter fullscreen mode Exit fullscreen mode

dengan tambahan script di package.json untuk run ini selesai sudah.

Kita juga gunakan blogpost.json tadi pada vuex store untuk fetch data artikel ini.

import dataJson from '../blogposts.json'

export const state = () => ({
  posts: [],
  post: {}
})

export const mutations = {
  updatePosts(state, postsJSON) {
    state.posts = postsJSON
  },
  updatePost(state, { post }) {
    state.post = post
  }
}

export const actions = {
  getPost({ commit, state }, slug) {
    const post = state.posts.find(post => {
      return post.slug === slug
    })
    commit('updatePost', { post: post })
  },
  getListOfPost({ commit, state }) {
    if (state.posts.length === 0) commit('updatePosts', dataJson)
  }
}
Enter fullscreen mode Exit fullscreen mode

naaah dengan ini kita fetch meta data blogpost kita yg ada pada markdown di vue-template

fetch({ store, params }) {
  // in case user reload the page
  store.dispatch('getListOfPost')
  //  fetch post
  store.dispatch('getPost', params.slug)
},
Enter fullscreen mode Exit fullscreen mode

Code highlighting

Saya pilih yang paling ringan Prism.js penggunaannya cukup simple.

// _slug.vue

mounted() {
  const block = document.querySelectorAll('code')
  for (let i = 0; i < block.length; ++i) {
    block[i].classList.add('language-javascript')
  }
  //  remove yaml title
  const h2 = document.getElementsByTagName('h2')
  h2[0].outerHTML = ''
  // hightlight code
  Prism.highlightAll()
}
Enter fullscreen mode Exit fullscreen mode

Enaknya memakai prism sendiri ini style dapat kita kustomisasi dengan mudah 😍.

Still on progress

Jika anda membaca sampai sini ini isinya hanya curhatan saja. Saya ada juga mengalami blocker lain selain kesusahan saat mengapliaksikan mdx di project ini. Salah-satunya adalah purgecss, project ini menggunakan TailwindCSS dimana jika tidak di kompress atau dikurangi class yang tidak digunakan maka size CSS-nya cukup besar yaitu 38.6kb.

Saat saya memutuskan menggukan purgecss, CSS custom saya banyak kena trim πŸ˜„ walaupun sudah saya include beberapa class yang tidak boleh di trim. Saya selalu strich soal size, saya sering curi soure code-nya lodash kalau hanya dipakai 4/6 fungsi saja pada proyek saya daripada harus meng-install-nya.

Commenting on blog sebenarnya saya mau menyematkan fitur komen pada blog ini, menggunakan utteranc.es darapida discus ... tapi kok style-nya kurang cocok jadi saya harus menyesuaikannya sedikit dengan website ini.

Karena saya tidak begitu paham paham benar soal CSS. Kadang masih bingung ini kenapa height: 100% kok tidak bisa bisa πŸ˜‚. Dengan ini saya nyatakan itu fitur berikutnya saja hehe.

I'm backend dev

Okay semoga anda menikmati first-post saya ini dan mendapat setidaknya sedikit ilmu 😁 oh yah untuk meninggalkan komen anda dapat mengunjungi github issue ini sambil saya coba coba integrasi untterances tadi.

Tidak lupa source code untuk website ini ada di sini

Top comments (0)