Vue多頁應用腳手架

二哲發表於2019-03-03

前言

一直以來都在研究多頁應用如何能有一套像SPA一樣優雅的開發模式

本套架構在專案上使用感覺還不錯(已跑在上百個頁面的專案上),所以決定開源出來給大家

閱讀完本文能實現在專案中使用ES6(7)+元件化(.vue | .jsx)開發多頁應用

如果你不需要SEO,需要前後端分離,專案是多頁應用,選擇我就對了

(其實我是想把它做為大家多頁應用的腳手架)

目錄結構介紹

TIPS:任何的專案的架構都和目錄結構有關,所以這部分非常重要,請仔細耐心閱讀

我們先巨集觀的看下結構

|--- public // 生產環境下所需的檔案
    |--- components
    |--- css
    |--- fonts
    |--- images
    |--- js
    |--- sass
    |--- views
|--- src
    |--- components
    |--- css
    |--- fonts
    |--- images
    |--- js
    |--- sass
    |--- views複製程式碼

我們展開介紹下具體的頁面應該如何對應它的資源。拿jsviews為例

|--- views
    |--- home // 官網介紹 業務模組
        |--- index.html
        ...
    |--- shopping // 購物業務模組
        |--- buy.html
        ...
|--- js
    |--- lib
        |--- vue.js
        |--- react.js
        |--- react.dom.js
        ...
    |--- home // 官網介紹業務模組的js
        |--- index.js
        ...
    |--- shopping // 購物業務模組的js
        |--- buy.js
        ...
    tools.js
    common.js複製程式碼

在多頁應用中,往往我們的頁面以業務模組劃分,業務模組由許多的頁面組成。
home,shopping,可能就分別為官網介紹和購物的業務模組。在這業務模組下,分別有許多個頁面,那我們的js檔案也需要命名一一對應。

當然,我們還有第三方的js庫是不需要編譯的,所以我們專門用一個lib資料夾來存放他們。(包括你自己編寫的指令或者filter等,不需要編譯的,也直接放在lib下引入即可)

另外,你還有許多自己寫的需要編譯的工具庫直接放在js目錄下即可(如,tools.js,common.js)


我們的sass也是同理

|--- sass
    |--- home
        |--- index.scss
        ...
    |--- shopping
        |--- buy.scss
        ...複製程式碼

他們會分別編譯在cssjs下的檔案將為

|--- css // scss 編譯後的
    |--- home
        |--- index.css
    |--- shopping
        |--- buy.css
|--- js // babel處理後的js
    |--- home
        |--- index.js
    |--- shopping
        |--- buy.js複製程式碼

頁面引用的路徑就為(home/index.html為例)

...
<link rel="stylesheet" href="../../js/css/home/index.css">

...

<script src="../../js/lib/vue(react).js"></script>
<script src="../../js/lib/react.dom.js"></script>
<script src="../../js/home/index.js"></script>
...複製程式碼

js和sass搞定了後,我們的難點是編寫元件的過程中,如何知道應該編譯哪個入口js檔案呢?
所以我們需要對我們的元件名進行一些約定,這也就是約定大於配置的前提。

|--- components
    |--- home // home 業務模組
        |--- home-header.vue(jsx)
        |--- index-info.vue(jsx)
        ...
    |--- shopping  // shopping 業務模組
        |--- buy-list.vue(jsx)
        ...複製程式碼

我們components下的業務模組名和之前的sass,js一樣。具體元件那就有所不同。

我們分為幾種型別的元件

  • 一、當前頁面使用的元件
  • 二、當前業務模組下的公用元件
  • 三、所有業務模組的通用元件

當前頁面元件的命名,我們約定為 [頁面]-[元件].vue(jsx)

如下

|--- components
    |--- home
        |--- index-info.vue(jsx)複製程式碼

這個index-info的元件就僅僅只有在home/index.html頁面下使用,當你修改了這個元件後,會自動編譯home/index.js路口js檔案並重新整理頁面。

當前業務模組下的公用元件,我們約定為 [業務模組]-[元件].vue(jsx)

如下

|--- components
    |--- home
        |--- home-header.vue(jsx)複製程式碼

這個home-header元件就屬於home業務模組下的公用元件,當你修改了這個元件後,會自動編譯home業務模組下所有的js檔案並重新整理頁面。

剩下的就是所有業務模組下的通用元件,我們約定全放在components/common目錄下,不需要具體命名約定

|--- components
    |--- common
        |--- loading.vue(jsx)複製程式碼

這個loading元件就屬於所有業務模組下的公用元件,當你修改了這個元件後,會自動編譯所有業務模組下的js檔案並重新整理頁面。

編譯元件的原理以及為什麼約定命名的原因是:

我會根據元件更改變動,去讀取資料夾名,元件名,並編譯對應名的路口js

至此,我們就把元件的問題也解決了

由於我採用的是主gulp輔webpack,webpack僅僅只編譯用,所以編譯基本達到秒編譯。比單純利用webpack做構建快得多。如果單純採用webpack做構建,需要去配置entry,配置HTMLPlugin。所以會慢得多,然而我這一套並不需要如此繁瑣。

圖片&&字型檔案

這其實是一個大坑

我們的實現目標是元件能相對路徑引入圖片或字型檔案

// 如 在html標籤裡這樣
<template>
    <figure>
        <img src="../../images/home/logo.jpg" alt="頭像">
    </figure>
</template>

// 在style裡這樣
<style rel="stylesheet/scss" lang="sass">
    @import "../../sass/home/index-info";
    // 甚至可能在這@import面引入相對路徑,這都會算是在元件裡引入相對路徑
    #bg h3 {
        background: url("../../images/holmes.jpg");
        color: #fff;
    }
</style>複製程式碼

這個坑,真是不可描述,我個人嘗試了各種體位,才把這個坑配置好。

直接給大家看最後實現是怎樣的。

dev 的路徑是這樣,頁面可以顯示圖片或字型。

Vue多頁應用腳手架

build 後的路徑是這樣

Vue多頁應用腳手架

這樣就達到了開發和釋出後的資源統一,摸索這一步真是挺累的 T.T,有興趣的自己看原始碼吧。

環境變數的配置

我們在webpack中經常會遇見不同環境下不同配置的問題

首先可在package.json裡配置一條script

// package.json
"scripts": {
    "build": "NODE_ENV=production gulp build",
    "dev": "NODE_ENV=dev gulp reload"
},複製程式碼

假設我們需要為不同環境配置不同的api請求地址,就可以利用我們在package.json設定的NODE_ENV來識別當前環境(這部分我在gulpfile中處理了,所以在檔案裡可直接識別NODE_ENV,如下)

//  src/js/ajaxurl.js

const server1 = `https://production.server.com`;
const server2 = `https://dev.server.com`;

let useServer = null;
if(NODE_ENV === `production`) {
    useServer = server1;
} else if(NODE_ENV === `dev`) {
    useServer = server2;
}

export default useServer;複製程式碼
// src/js/home/index.js

import url from `../ajaxurl`;
console.log(url);複製程式碼

這樣就解決了我們不同環境下不同配置的問題,我預設配置了devproduction,大家可以自行擴充。比如

假設你需要在 開發中 配置測試,你可以寫一條NODE_ENV=test gulp reload

如果需要 預釋出打包 測試,就可以另一條NODE_ENV=preproduction gulp build

總之就是打包使用gulp build,開發使用gulp reload

注意事項

開發:執行命令 npm run dev
釋出:執行命令 npm run build (BTW,別忘了去gulpfile.js裡替換你的CDN連結,進入gulp檔案修改 const CDN = `yourCDNLink`這裡的變數即可)

命名一定要按約定來!
命名一定要按約定來!
命名一定要按約定來!

否則不知道要編譯誰!!!

gulp配置很簡單,大家可以看一下針對各自專案進行修改,不懂得可以直接問我。

如果你們不完全的前後端分離,把這個src直接放在後臺目錄下也沒有問題。

TODO

  • [ ] 專案的Unit test
  • [ ] 專案Cli腳手架

後話

本來是想寫成vue-cli或者是create-react-app這種cli腳手架的,但是!本人真是太懶又沒有時間了! 各位看官可以先嚐試clone把玩把玩,如果有足夠多人喜歡,我就把他寫成cli,釋出npm ?

我是用mac下開發完成的,用了半天多時間專門去給window寫了相容,window還可能會有bug,不是我說!window就是辣雞!

最後給大家看下我們的某專案結構。


總覽

Vue多頁應用腳手架
總覽

js部分

Vue多頁應用腳手架
js部分

images

Vue多頁應用腳手架
images

元件

Vue多頁應用腳手架
元件和頁面

你們可能在總覽的圖會發現多了apismock資料夾,這個是我們promise封裝介面層和前端本地mock層,由於每個團隊的做法都不同,我就沒有放在這次的腳手架裡

vue-multpage 通用版: github.com/MeCKodo/vue…

這個是我們內部的版本


Have a nice day

相關文章