Egg + Vue 服務端渲染開發指南

1. 項目初始化

1.1 通過 easywebpack-cli 腳手架初始化

  1. 安裝腳手架 npm install easywebpack-cli -g 命令行,然后就可以使用 easywebpackeasy 命令

  2. 命令行運行 easywebpack init

  3. 選擇 egg+vue server side render boilerplate 初始化骨架項目

  4. 安裝依賴 npm install

1.2 通過骨架項目初始化

git clone https://github.com/hubcarl/egg-vue-webpack-boilerplate.git
npm install

初始化的項目提供多頁面和SPA(vue-router/axios)服務端渲染實例,可以直接運行。

2. 項目運行

2.1 本地運行

npm start

npm start 做了如下三件事情

  • 啟動 egg 應用
  • 啟動 Webpack 構建, 文件不落地磁盤,構建的文件都在內存里面(只在本地啟動, 發布模式是提前構建好文件到磁盤)
  • 構建會同時啟動兩個 Webpack 構建服務, 客戶端js構建端口9000, 服務端端口9001
  • 構建完成,Egg應用正式可用,自動打開瀏覽器

2.2 發布模式

  • 構建文件落地磁盤
npm run build 或 easywebpack build prod
  1. 啟動 Webpack 構建,文件落地磁盤
  2. 服務端構建的文件放到 app/view 目錄
  3. 客戶端構建的文件放到 public 目錄
  4. 生成的 buildConfig.jsonmanifest.json 放到 config 目錄
  5. 構建的文件都是gitignore的,部署時請注意把這些文件打包進去
  • 運行

啟動應用前, 請設置 EGG_SERVER_ENV 環境變量,測試環境設置 test, 正式環境設置 prod

npm start

3. 項目構建

  • 通過 easywebpack-cli 統一構建,支持 dev,test,prod 模式構建

  • easywebpack-cli 通過項目根目錄下的 webpack.config.js 配置文件構造出 Webpack 實際的配置文件,配置項請見 webpack.config.js

  • 獲取 Webpack 實際的配置文件, egg-webpack 會使用到該功能。構建會根據 webpackConfigList.length 啟動對應個數的 Webpack 編譯實例,這里會同時啟動兩個 Webpack 構建服務, 客戶端jsbundle構建,端口9000, 服務端jsbundle構建端口9001。默認端口為9000, 端口依次遞增。

// config/config.local.js 本地 npm start 使用
const EasyWebpack = require('easywebpack-vue');
exports.webpack = {
  webpackConfigList:EasyWebpack.getWebpackConfig()
};
  • 該項目中,app/web/page 目錄中所有 .vue 文件當作 Webpack 構建入口是采用 app/web/framework/vue/entry 的 client-loader.js 和 server-loader.js 模板實現的,這個需要結合 webpack.config.js 下的 entry.loader 使用。
entry: {
   include: ['app/web/page', { 'app/app': 'app/web/page/app/app.js?loader=false' }],
   exclude: ['app/web/page/[a-z]+/component', 'app/web/page/app'],
   loader: { // 如果沒有配置loader模板,默認使用 .js 文件作為構建入口
      client: 'app/web/framework/vue/entry/client-loader.js',
      server: 'app/web/framework/vue/entry/server-loader.js',
   }    
}

上面 { 'app/app': 'app/web/page/app/app.js?loader=false' } 這個 loader=false 的含義表示 app/web/page 目錄下的 app/app.js 不使用 entry.loader 模板。因為這個app/app.js是一個SPA服務端渲染Example,實現邏輯與其他普通的頁面不一樣,不能用 entry.loader 模板, 這個功能在自定義entry文件構建規范時使用。

4. 項目規范

  • 遵循 egg 開發規范
  • Vue 項目代碼放到 app/web 目錄,頁面入口目錄為 page,該目錄的 所有 vue 文件默認會作為 Webpack 的 entry 構建入口。建議每個頁面目錄的只保留一個vue文件,vue關聯的組件可以放到widget 或者 compnent目錄。如果非要放到當前目前,請配置 webpack.config.js entry.exclude 排除 vue文件。
egg-vue-project.png

5. 項目開發

支持多頁面/單頁面服務端渲染, 前端渲染, 靜態頁面三種方式.

5.1 多頁面服務端渲染實現

5.1.1 多頁面前端頁面實現

在app/web/page 目錄下面創建home目錄, home.vue 文件, Webpack自動根據.vue文件創建entry入口, 具體實現請見webpack.config.js

  • home.vue 編寫界面邏輯, 根元素為layout(自定義組件, 全局注冊, 統一的html, meta, header, body, 你可以自定義 title,description,keywords SEO信息,更多信息請擴展layout).
<template>
  <layout title="基于egg-vue-webpack-dev和egg-view-vue插件的工程示例項目" description="vue server side render" keywords="egg, vue, webpack, server side render">
   {{message}}
  </layout>
</template>
<style>
  @import "home.css";
</style>
<script type="text/babel">

  export default {
    components: {

    },
    computed: {

    },
    methods: {

    },
    mounted() {

    }
  }
</script>

5.1.2 多頁面后端渲染實現, 通過 egg-view-vue-ssr 插件 render 方法實現

  • 創建controller文件home.js
exports.index = function* (ctx) {
  yield ctx.render('home/home.js', { message: 'vue server side render!' });
};
  • 添加路由配置
app.get('/home', app.controller.home.home.index);

5.1.3 多頁面走前端渲染(后端路由)實現, 通過 egg-view-vue-ssr 插件 renderClient 方法實現

  • 創建controller文件home.js
exports.client = function* (ctx) {
  yield ctx.renderClient('home/home.js', { message: 'vue server side render!' });
};
  • 添加路由配置
app.get('/client', app.controller.home.home.client);

5.2 HTML靜態頁面前端渲染

  • 直接有easywebpack構建出靜態HTML文件, 請見 webpack.config.js 配置和 app/web/page/html代碼實現

  • 通過 egg-static 靜態文件訪問HTML文件

5.3 單頁面服務器渲染同構實現

5.3.1 單頁面前端實現

在app/web/page 目錄下面創建app目錄, app.vue, app.js 文件.

  • app.vue 編寫界面邏輯, 根元素為layout(自定義組件, 全局注冊, 統一的html, meta, header, body)
<template>
  <app-layout>
    <transition name="fade" mode="out-in">
      <router-view></router-view>
    </transition>
  </app-layout>
</template>
<style lang="sass">

</style>
<script type="text/babel">
  export default {
    computed: {

    },
    mounted(){

    }
  }
</script>
  • app.js 頁面調用入口
import { sync } from 'vuex-router-sync';
import store from 'store/app';
import router from 'component/app/router';
import app from './app.vue';
import App from 'app';
import Layout from 'component/layout/app';

App.component(Layout.name, Layout);

sync(store, router);

export default App.init({
  base: '/app',
  ...app,
  router,
  store
});

5.3.2 單頁面后端實現

  • 創建controller文件app.js
exports.index = function* (ctx) {
  yield ctx.render('app/app.js', { url: this.url.replace(/\/app/, '') });
};
  • 添加路由配置
  app.get('/app(/.+)?', app.controller.app.app.index);

6. 項目部署

  • 正式環境部署,請設置 EGG_SERVER_ENV=prod 環境變量, 更多請見運行環境
  • 構建的 app/view 目錄, public 目錄以及 buildConfig.jsonmanifest.json等文件, 都是 gitignore 的,部署時請注意把這些文件打包進去。

7. 項目和插件

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在實現 egg + vue 服務端渲染工程化實現之前,我們先來看看前面兩篇關于Webpack構建和Egg的文章: ...
    hubcarl閱讀 6,046評論 0 19
  • 1.概要 隨著越來越多的項目采用 Vue, React, Weex 進行業務開發, 在前端構建方面大多數是用web...
    hubcarl閱讀 6,352評論 3 18
  • 嗯,我大一了。我想要的自己,可以每天在第一縷陽光下醒來,可以接受不同的新鮮事物,可以吸收不同的樂觀能量,不熬夜不喝...
    心上人喜歡閱讀 127評論 0 0
  • 沒有任何提示音,他準點醒來。拿出手機摁了一下,手機屏顯示“10月3日2:00”。再摁一下關機鍵,閃著熒光的時間像一...
    撫琴_張顥閱讀 570評論 13 6
  • 每逢下雨天 就覺得天空離我很近 因為雨帶來了天空的味道 聞著很舒服 呼吸時感到很輕松 一場雨 洗盡鉛華
    辰漁閱讀 295評論 0 2