關於我

Hunter

前端工程師

用 Nuxt.js 2.x 自幹一個部落格

大綱

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

 1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

使用者模式

  • 首頁
  • 自我介紹
  • 文章列表
  • 標籤列表
  • 文章內容

部落格功能介紹

開發者模式

  • 登入
  • 文章列表
  • 發佈文章
  • 編輯文章

使用者模式-首頁

使用者模式-自我介紹

使用者模式-文章列表

使用者模式-標籤列表

使用者模式-文章內容

開發者模式-登入

開發者模式-文章列表

開發者模式-發佈文章

開發者模式-編輯文章

寫篇文章吧!

  1. 部落格功能介紹

 2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

套件選用

  • Lodash
  • Disqus
  • simple-vue-validator
  • Codemirror
  • markdown-it
  • hightlight.js

套件選用與指令介紹

指令介紹

  • dev
  • storybook
  • build
  • analyze
  • start
  • plop
  • generate
  • generate:github
  • generate:storybook

Lodash

1. uniq

2. flatten

3. camelCase

4. debounce

Lodash 是一個提供模組化、擁有優秀效能的函式庫。

(~24kB gzipped)

Lodash

只用了四個函式就要引入整個函式庫?

Lodash: tree-shaking

1. babel-plugin-lodash

2. lodash-webpack-plugin

Disqus

https://disqus.com/

留言板功能

 

透過 vue-disqus 實現

simple-vue-validator

simple-vue-validator 是一個表單驗證的解決方案

Why simple-vue-validator?

可以去參考我的鐵人賽

simple-vue-validator

1. 輕量 (~3.56kb gzipped)

2. 驗證邏輯和提交寫在 js

3. 錯誤訊息可以 js 組成,不污染 HTML

4. 唯一的遺憾,多國語系

5. 高彈性和可擴充性

simple-vue-validator

Codemirror

文字編輯器:codemirror

CodeMirror 是一個基於 javascript 的多功能的文字編輯器,可在瀏覽器中執行。

CodeMirror 提供程式碼的高亮和縮排等功能。

 

透過 vue-codemirror 實現

markdown-it

markdown-it 是一個 markdown 編譯器,

將 markdown 編譯為 html

highlight.js

highlight.js

Syntax highlighting for the Web

指令介紹

"scripts": {
    "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
    "storybook": "start-storybook -p 9002 -c .storybook",
    "build": "nuxt build",
    "analyze": "nuxt build -a",
    "start": "nuxt start",
    "plop": "plop --plopfile ./plop/index.js",
    "generate": "nuxt generate",
    "generate:github": "cross-env DEPLOY_ENV=GH_PAGES nuxt generate",
    "generate:storybook": "build-storybook -c .storybook -o blog-storybook"
}

  1. 部落格功能介紹

  2. 套件選用與指令介紹

 3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

Are you Nuxt?

Nuxt.js 簡介

Nuxt.js 是一個基於 Vue.js 的應用框架

Nuxt.js 依賴

1. Vue 2

2. Vue Router

3. Vuex

4. Vue Server Renderer (universal mode only)

5. vue-meta

Nuxt.js 提供三種模式

1. universal: 簡單理解為有 SSR

2. spa: 簡單理解為無 SSR

3. generate: 將應用產出為靜態 HTML 頁面,即可作為靜態資源部署至 github-page 等。

Nuxt.js 的特性

  1. 以 SFC 構成

  2. 代碼分層

  3. 服務端渲染

  4. 靜態文件服務

  5. 強大的路由,除非超複雜的路由,否則不必再寫 router.js

  6. 透過 webpack 打包及壓縮 js, css,以及效能優化。

  7. HTML 頭部標籤管理 (透過 vue-meta)

  8. 支持 hot reload

  9. Eslint, Prettier

10. 使用模塊化的方案擴充 Nuxt 應用 (如:gtm, axios, ...)

11. 支持 HTTP/2

12. 支持各種樣式預處理器,例如:scss, less, stylus

...

...

Nuxt.js 提供的元件

  1. nuxt

  2. nuxt-child

  3. nuxt-link

  4. no-ssr

What's different Nuxt@2.x ?

  1. use Webpack 4

  2. ESM is supported everywhere

  3. Upgraded to use Babel 7

  4. create-nuxt-app

1. 建立一個足夠彈性的新專案

2. 導入你現有的 Node.js 的專案當中

 

Nuxt.js 可以

Nuxt.js 已經預設好一個 Vue.js 應用,並且提供舒適的開發流程與體驗,使開發者能方便處理 Server-Side Rendering(SSR) 及 SEO 相關問題。

create-nuxt-app

npx? npm? nvm?

npx 是 npm 5.2.0 開始新增的指令,

可以方便開發者避免全域安裝套件。

 

npx 會臨時安裝 create-nuxt-app,

並完成指令後自動移除,

不會造成 global 的污染。

npx

想用 Nuxt@1.x 怎麼辦?

create-nuxt-app@version

挑戰從 0 到部署

Let's nuxt

Nuxt.js 目錄結構

目錄結構:元件

1. /layouts (使用者模式, 編輯者模式)

2. /pages (路由)

3. /components (UI 元件)

目錄結構:Assets

1. webpack assets (/assets)

    => css-loader, file-loader, url-loader

2. static assets (/static)

目錄結構:模組

1. Modules (/modules)

2. serverMiddleware (/api)

3. Plugins (/plugins)

目錄結構:模組

Modules (/modules)

擴充 nuxt 核心,並於應用啟動時按順序調用"一次"

// nuxt.config.js
module.exports = {
  modules: [
    '@nuxtjs/axios',

    ['~/modules/SimpleModule', { key: 'value' }]
  ],
}

// modules/SimpleModule.js
module.exports = function SimpleModule (moduleOptions) {
  // console.log(moduleOptions)
  // { key: 'value' }

  // console.log(this.options)
  // content of nuxt.config.js
}

目錄結構:模組

serverMiddleware (/api)

在 vue-server-render 執行前被調用

// nuxt.config.js
module.exports = {
  serverMiddleware: [
    'redirect-ssl',

    '~/api/logger',

    { path: '/api', handler: '~/api/index.js' }
  ]
}

// api/logger.js
module.exports = function (req, res, next) {
  ...
}

目錄結構:模組

Plugins (/plugins)

在 Vue 被實例化前被調用

// nuxt.config.js
module.exports = {
  plugins: [
    '@/plugins/vuetify',
    { src: '@/plugins/codemirror', ssr: false },
  ]
}

// plugins/vuetify/index.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'

import theme from './vuetify.config.js'

Vue.use(Vuetify, {
  theme
})

Nuxt.js 設定檔

./nuxt.config.js

Nuxt 部落格的:nuxt.config.js

1. mode

2. head

3. loading

4. css

5. plugins

6. build

7. render

8. router

9. generate

Nuxt.js 2.x 生命週期

nuxtServerInit

一個在 server-side 執行的 action

接收兩個參數

非同步的 nuxtServerInit 需回傳 promise

middleware

1. Global middleware 

2. Layout middleware

3. Page middleware

// nuxt.config.js 
export default {
  router: {
    middleware: 'authenticated'
  }
}
// layouts/admin.vue
export default {
  middleware: 'authenticated'
}
// pages/index.vue
export default { 
  middleware: 'authenticated'
}

middleware: authenticated

// middleware/authenticated.js
export default function ({ store, redirect }) {
  if (!store.state.auth.user) {
    return redirect('/admin/login')
  }
}

validate(), asyncData(), fetch()

Page components (/pages)

// pages/index.vue 
export default {
  validate(context) { /* 驗證動態路由是否可用 */ 
    return false // 自動導頁 404 錯誤頁
  },
  data: vm => ({
    name: 'Hunter Liu' // 預設值
  }),
  asyncData(context) { /* 設置元件 data */ 
    return {
      name: 'Sherry Hsu' // 合併回 data
    }
  },
  async fetch ({ store, params }) {
    let { data } = await axios.get('http://my-api/stars')
    store.commit('setStars', data)
  }
}

validate(), asyncData(), fetch()

注意:asyncData(), fetch()

會在 server-side 或 client-side 被執行

// pages/index.vue 
export default {
  validate(context) { /* 驗證動態路由是否可用 */ 
    return false // 自動導頁 404 錯誤頁
  },
  data: vm => ({
    name: 'Hunter Liu' // 預設值
  }),
  asyncData(context) { /* 設置元件 data */ 
    return {
      name: 'Sherry Hsu' // 合併回 data
    }
  },
  async fetch ({ store, params }) {
    let { data } = await axios.get('http://my-api/stars')
    store.commit('setStars', data)
  }
}

Q&A

Difference between

middleware and serverMiddleware ?

Nuxt 部落格的目錄結構

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

 4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

Vuetify

A Material Design Component Framework

Vuetify 和他們有什麼不同?

 

Element UI

VueStrap

Bootstrap-Vue

Vue Material

...等

Vuetify 是一個基於 Vue 的 UI 框架。

 

 

Element UI

VueStrap

Bootstrap-Vue

Vue Material

...等等

比較像 Vue 元件庫

Vuetify 有

  • 支援 SSR, PWA, Mobile App
  • 支援多國語系
  • 大量的元件,class 命名遵循 BEM,容易客製化與複寫樣式
  • 優秀的 grid system
  • 可自定義 breakpoints 處理 RWD
  • 預定義好的全域 class ,避免不斷重複寫樣式
  • ......

vuetify@1.3.x

Release at 2018/10/17

開始支援 vuetify-loader

vuetify plugin

/assets/style/app.styl

@require '~vuetify/src/stylus/bootstrap'
$colors = {
  "red": $red,
  "pink": $pink,
  "purple": $purple,
  "deep-purple": $deep-purple,
  "indigo": $indigo,
  "blue": $blue,
  "light-blue": $light-blue,
  "cyan": $cyan,
  "teal": $teal,
  "green": $green,
  "light-green": $light-green,
  "lime": $lime,
  "yellow": $yellow,
  "amber": $amber,
  "orange": $orange,
  "deep-orange": $deep-orange,
  "brown": $brown,
  "blue-grey": $blue-grey,
  "grey": $grey,
  "shades": $shades
}
@require '~vuetify/src/stylus/app'

/plugins/vuetify/index.js

import Vue from 'vue'
import Vuetify from 'vuetify/lib'

import theme from './vuetify.config.js'

Vue.use(Vuetify, {
  theme
})

/plugins/vuetify/vuetify.config.js

export default {
  primary: '#41B883',
  main: '#121212'
}

vuetify-loader in Nuxt.js

// nuxt.config.js

const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')

module.exports = {
  css: [
    '@/assets/style/app.styl',
  ],
  plugins: [
    '@/plugins/vuetify'
  ],
  build: {
    extractCSS: true,
    transpile: [/^vuetify/],
    extend(config, ctx) {
      config.plugins.push(
        new VuetifyLoaderPlugin()
      )
    }
  }
}

vuetify-loader@1.0.6

tree shaking

自動引入元件

Vuetify@2

  • Monorepo
  • Core rebuilt from ground up
  • Full Typescript support
  • Moving from avoriaz to vue test utils
  • Moving from Stylus to SCSS

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

 5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

Stoybook?

Storybook

  • storybook 4
  • /.storybook
  • storybook@4.x & vuetify@1.3.x
  • storybook@4.x & nuxt@2.x
  • DEMO

storybook@4.0.0

  1. use Webpack 4

  2. Upgraded to use Babel 7

Release at 2018/10/29

與 Nuxt@2.x 不謀而合

先看看畫面

/.storybook

  • addons.js
  • config.js
  • preview-head.html
  • webpack.config.js

/.storybook/addons.js

import '@storybook/addon-storysource/register'
import 'storybook-readme/register'
import '@storybook/addon-actions/register'
import '@storybook/addon-options/register'
import '@storybook/addon-viewport/register'

/.storybook/config.js

import { configure, addDecorator } from '@storybook/vue'
import { withOptions } from '@storybook/addon-options'
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

Vue.use(Vuetify, {
  theme
})

addDecorator(
  withOptions({
    name: 'nuxt blog',
    url: 'https://github.com/hunterliu1003/blog',
    addonPanelInRight: true
  })
)

const req = require.context('../components', true, /stories\.js$/)

function loadStories() {
  req.keys().forEach(filename => req(filename))
}

configure(loadStories, module)

/.storybook/preview-head.html

<!-- Vuetify using material icons -->
<link 
  rel="stylesheet" 
  href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons"
>
<!-- Vuetify using fontawesome icons -->
<link 
  rel="stylesheet" 
  href="https://use.fontawesome.com/releases/v5.2.0/css/all.css"
>

/.storybook/webpack.config.js

const path = require("path")

module.exports = (storybookBaseConfig, configType) => {
  storybookBaseConfig.module.rules.push({
    test: /\.stories\.jsx?$/,
    loaders: [require.resolve('@storybook/addon-storysource/loader')],
    enforce: 'pre'
  })
  storybookBaseConfig.module.rules.push({
    test: /\.pug$/,
    loader: 'pug-plain-loader'
  });
  storybookBaseConfig.module.rules.push({
    test: /\.styl(us)?$/,
    use: [
      'vue-style-loader',
      'css-loader',
      'stylus-loader'
    ]
  })
  storybookBaseConfig.resolve.alias['@'] = path.dirname(path.resolve(__dirname))

  return storybookBaseConfig
}

storybook@4.x & vuetify@1.3.x

// .storybook/config.js

import Vuetify from 'vuetify'
import theme from '@/plugins/vuetify/vuetify.config.js'

import '!!style-loader!css-loader!stylus-loader!../assets/style/app.storybook.styl'

Vue.use(Vuetify, {
  theme
})

storybook@4.x & nuxt@2.x

// .storybook/config.js

Vue.component('nuxt-link', {
  functional: true,
  render: function (createElement, context) {
    let allClass = {}
    let arrClass = context.data.staticClass
      ? context.data.staticClass.split(' ')
      : []
    arrClass.forEach(theClass => {
      allClass[theClass] = true
    })
    return createElement('a', { class: allClass }, context.children)
  }
})

Vue.component('no-ssr', {
  functional: true,
  render (createElement, context) {
    return context.children
  }
})

Demo

yarn storybook

yarn plop

yarn generate:storybook

cd blog-storybook

now

接下來會是一堆程式碼

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

 6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

佈局介紹 (/layouts)

  • default.vue
  • admin.vue
  • error.vue

default: template

default: style

<style lang="stylus">
  @import '~vuetify/src/stylus/settings/_variables'
  
  .default-nav
    width 350px
    padding 20px
    position fixed
    height 100%
  .default-content
    padding 40px 30px
    margin-left 350px
    height 100%
    
  @media $display-breakpoints.md-only
    .default-nav
      width 300px
    .default-content
      margin-left 300px
</style>

admin: template

error page

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

 7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

所有元件

  • TheTags
  • TheMarkdown
  • ThePostPreview
  • FormAddPost
  • StoryCentered.vue

元件:TheTags

元件:TheMarkdown

元件:ThePostPreview

使用者模式

元件:ThePostPreview

開發者模式

元件:FormAddPost

元件:StoryCentered

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

 8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

firebase

  • auth
  • firestore

firebase 設定

  • ./firebase.json
  • ./firestore.indexes.json
  • ./firestore.rules

firebase.json

{
  ...,

  "hosting": {
    "public": "dist"
  },

  ...
}

firestore.rules

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read
      allow write: if request.auth != null;
    }
  }
}

firebase.indexes.json

{
  "indexes": [
    {
      "collectionId": "posts",
      "state": "READY",
      "fields": [
        {
          "fieldPath": "isShow",
          "mode": "ASCENDING"
        },
        {
          "fieldPath": "postTime",
          "mode": "DESCENDING"
        }
      ]
    }
  ]
}

firebase in Nuxt.js

/plugins/firebase/config.js

export default {
	apiKey: "AIzaSyBn1kNP-yxMT4ddncPXsNm46hXYyCWCkXU",
	authDomain: "blog-6894c.firebaseapp.com",
	databaseURL: "https://blog-6894c.firebaseio.com",
	projectId: "blog-6894c",
	storageBucket: "blog-6894c.appspot.com",
	messagingSenderId: "872777000678"
}

firebase in Nuxt.js

/plugins/firebase/index.js

import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import config from './config.js'

!firebase.apps.length ? firebase.initializeApp(config) : ''

const firestore = firebase.firestore()

const settings = {
  timestampsInSnapshots: true
}

firestore.settings(settings)

export const auth = firebase.auth()
export const db = firestore

使用 firestore

使用 auth

import { auth } from '@/plugins/firebase'
import { db } from '@/plugins/firebase'

中間件

export default function ({ store, redirect }) {
  if (!store.state.auth.user) {
    return redirect('/admin/login')
  }
}

./middleware/authenticated.js

使用中間件

Page Middleware

export default { 
  middleware: 'authenticated'
}

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

 9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

Vuex module registration

/store/index.js

import Vuex from 'vuex'
import auth from '@/store/modules/auth'
import post from '@/store/modules/post'
import tags from '@/store/modules/tags'

const createStore = () => {
  return new Vuex.Store({
    modules: {
      auth,
      post,
      tags,
    }
  })
}

export default createStore

Vuex module registration

/store/modules/index.js

import camelCase from 'lodash/camelCase'

const requireModule = require.context('.', false, /\.js$/)
const modules = {}

requireModule.keys().forEach(fileName => {
    // Don't register this file as a Vuex module
    if (fileName === './index.js') return

    const moduleName = camelCase(
        fileName.replace(/(\.\/|\.js)/g, '')
    )
    modules[moduleName] = {
        namespaced: true,
        ...requireModule(fileName)
    }
})

export default modules

Vuex module registration

/store/index.js

import Vuex from 'vuex'
import modules from '@/store/modules'

const createStore = () => {
  return new Vuex.Store({
    modules
  })
}

export default createStore
import Vuex from 'vuex'
import auth from '@/store/modules/auth'
import post from '@/store/modules/post'
import tags from '@/store/modules/tags'

const createStore = () => {
  return new Vuex.Store({
    modules: {
      auth,
      post,
      tags,
    }
  })
}

export default createStore

Vuex store

  • /store/index.js
  • /modules
    • /index.js
    • /auth.js
    • /post.js
    • /tags.js

modules/auth.js

  • state
    • user: null
  • mutations
    • setUser
  • actions
    • signInWithEmail
    • signOut
    • signInAuto
  • getters
    • authenticated

modules/post.js

  • actions
    • addPost
    • setPost
    • getPostByPostId
    • getPostsByPage
    • getPostsByTagId
    • getPostsAdmin
    • getPosts

modules/tags.js

  • actions
    • getAllTags

看看程式碼

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)  

11. 部署 heroku, github pages, firebase hosting

12. 總結

所有路由

使用者模式

  • /
  • /about
  • /posts
  • /posts/_postId
  • /tags
  • /tags/_tagId
  • /pages/_pageNum

開發者模式

  • /admin
  • /admin/_postId
  • /admin/addPost
  • /admin/login

滿滿的程式碼

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

分享三種部署方法

  • Heroku
  • Github Page
  • Firebase Hosting

部署至 Heroku

// package.json

{
  "scripts": {
    "heroku-postbuild": "yarn build"
  }
}

部署 generate 模式

需要將 nuxt.config.js 的 firestore 註解拿掉

// nuxt.config.js

/* only for scripts generate */

import { db } from './plugins/firebase'

部署至 Github page

yarn generate:github

部署至 Firebase Hosting

yarn generate
firebase deploy

bonus

npm i -g now

yarn global add now

storybook

yarn generate:storybook
cd blog-storybook
now
now alias https://blog-storybook-[hash].now.sh blog-storybook

universal 部落格

static 部落格

now
now alias https://hunterliu-blog-[hash].now.sh hunterliu-blog
now scale https://hunterliu-blog.now.sh 1
yarn generate
cd dist
now
now alias https://dist-[hash].now.sh hunterliu-static

  1. 部落格功能介紹

  2. 套件選用與指令介紹

  3. Nuxt.js 2.x 簡介, 目錄結構, 設定檔, 生命週期

  4. Vuetify 1.3.x 簡介與 vuetify-loader 導入

  5. Storybook 4 簡介與導入

  6. 部落格:  佈局介紹 (/layouts)

  7. 部落格:  所有元件介紹 (/components)

  8. Firebase 簡介, 登入, 中間件, 資料庫

  9. Vuex store & module registration

10. 部落格:  各頁面介紹 (/pages)

11. 部署 heroku, github pages, firebase hosting

12. 總結

nuxt.config.js/build

yarn build

yarn analyze

優化:Step by step

優化:splitChunks & http2

// nuxt.config.js
module.exports = {
  build: {
    optimization: {
      splitChunks: {
        minSize: 10000,
        maxSize: 250000
      }
    }
  },  
  render: {
    http2: {
      push: true
    }
  }
}

優化:lodash tree-shaking

// nuxt.config.js
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
module.exports = {
  babel: {
    plugins: ['lodash']
  },
  plugins: [new LodashModuleReplacementPlugin]
}

優化:Vuetify tree-shaking

// nuxt.config.js
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
module.exports = {
  plugins: [new VuetifyLoaderPlugin()]
}

Build size 減少約 87kb

縮小 20%

效能如何?

Page: about

Page: login

Page: postId

.nuxt

還記得這張圖嗎?

看看 .nuxt

Q&A

謝謝大家

nuxt-blog

By hunterliu1003

nuxt-blog

  • 2,341