個人網站架構設計(三) - 從設計到前端到后台


網站地址:http://barretlee.com

在五月份,寫過兩篇博客,提到了要給自己做個網站,當時人在實習,沒太多的時間,只是把大概的思路捋了一番,順道也買了個雲主機(配置比較低,內存才500M)。接着返校處理畢業事宜,於是六月也隨着同學之間揮淚告別的聲音漸漸遠去。七月,家里呆着,中旬回公司。想必這也是我近幾年最長的一次假期了=。 =

一、先說設計

1. 阮一峰的博客

目前我的博客設計是 fork 了 BeiYuu 的主題,然后七改八改,除了主頁 BeiYuu 還認得出是他的之外,其他頁面已經動了很大的手術,而這些手術靈感都是源自阮一峰阮大大(我的博客地址是<barretlee.com>,正文部分基本是抄襲他的設計,雖然代碼是我重新敲的…)。

阮教授自2003年開始經營他的博客ruanyifeng.com,到目前為止已有十一載,期間肯定也是改版了N次。在多次的改版之后,整個網站,結構上,幾乎沒有太多的冗余,內容上,更不用說,每一篇都是深入淺出、鞭辟入里,絕對可以給32個贊,想表達的內容全部十分清晰地呈現給了讀者,阮大大的文字功底,我輩望塵莫及。

他的博客涉及面廣,而且網站的設計上也是花夠了心思,在觀察他的博客設計時,想到了一些問題。

  • 讀者進入頁面,他最關注的是什么?
  • 通過什么方式來突出文章的重點和亮點?
  • 網站主頁展示哪些元素?
  • 如何去表述一個比較新的技術點或者觀點?

自己的鄙見我就不發表了,不過上面提到的幾個問題都是值得去思考的。

2. 張鑫旭的博客

張鑫旭大哥,也是通過博客認識的,后來才發現,我與他同是華中科技大學[校友],再后來又發現,我竟然與他是同一個技術團隊(學校·網絡應用研發中心)的成員[隊友],再后來還發現,我竟然早就跟他在同一個群里[朋友]。

很多人提到張鑫旭的博客,都說“就是那個喜歡張含韻的人的博客啦”,我倒是問過他,他說測試圖片前幾張正好是張含韻,順手選中拿出來。。他的博客也是十分有特色的:

  • 專注點很集中 - 前端,而且是小而美的研究,很贊
  • 文風 - 很能扯淡,喜歡的人豎拇指,不喜歡的人覺得羅里吧嗦

思考的兩個問題:

  • 如何讓別人一眼發現,“哦,這是那個xxx的博客”?
  • 博客先是記錄自己,然后變成服務他人。

3. 簡書

簡書的口號就是“找回文字的力量”,我不太喜歡文字(基本沒看過小說),所以沒有仔細品味簡書里面的東西,但卻對他網站視覺的設計很感興趣。簡潔大方,有書的味道,整個體驗很有質感。

我是個程序猿,不算射雞濕。如果文章呈現的內容太多,我會hold不住整體的布局,所以會比較中意簡潔的設計,簡潔的另一個好處就是突出正文,內容很直觀的被呈現出來。

以上我列舉了三個網站,不用想,肯定又會去抄他們了,囧。。。但其實我參考的網站有十幾個,把十幾個網站(我覺得)突出的地方整合進了自己的設計,請不要噴我這個不懂設計的程序猿。

二、從設計到前端實現

正常的流程是設計->設計稿->切圖,我跳過了設計稿,直接開始敲代碼,貌似自己對代碼的親切度比PSD圖片更高(所以為什么總說擼代碼呢…)。

設計很簡單,故意弱化設計以強化內容,希望能夠取長補短。

1. 正文的設計與實現

正文的設計參考了簡書,但是簡書是一個以文字為中心的網站,圖片都很少出現。而對於一個博客來說,有幾個元素十分重要:代碼、引用塊、圖片、表格、list列表等等。所以這些元素的展示要自己來設計。

細節上的東西,只要進入網站就能看到,所以在這里就不贅述太多。代碼的高亮使用的是 prettify 的 light 主題,對它做了微調。

代碼塊滾動條的樣式也修改了下:

pre::-webkit-scrollbar {width:10px;height:10px;background:#F6F6F6;border-top:1px solid #CCC;padding-top:1px;}
pre::-webkit-scrollbar-thumb {background:#EEE;border-radius:5px;border:1px solid #CCC;border-bottom:0px;}
pre::-webkit-scrollbar-thumb:hover {background:#DDD;}
pre::-webkit-scrollbar {width:10px;height:10px;background:#CCC;}
pre::-webkit-scrollbar-thumb {background:#999;border-radius:5px;}
pre::-webkit-scrollbar-thumb:hover {background:#666;}
pre::-webkit-scrollbar-corner {background:#CCC;}
pre::-webkit-color-swatch {border:none;}

效果是這樣的:

整個設計都是扁平化,沒有圓角,看起來感覺還算舒服,下面是引用塊的樣式呈現:

由於一些代碼是可以直接運行的,所以也給可運行代碼加上了一個運行的 button:

在IE下,是使用一個 about:blank 的空白頁打開代碼文件,如果瀏覽器支持 blob 流,將會使用 blob 流打開:

if (!operation.isIE()) {
    window.open(URL.createObjectURL(new Blob([code], {
        type: "text/html; charset=UTF-8"
    })));
} else {
    var d = window.open("about:blank").document;
    d.write(code);
    d.close();
}

2. 側邊欄的設計與實現

1) 側邊欄-未展開

從上圖可以看到,側邊欄都是一些功能按鈕,從上往下依次是:顯示隱藏文章目錄,頁面主題和字體設置,關於作者,反饋信息,RSS訂閱。

為啥要搞個側邊欄,還放那么多的功能按鈕?就拿司徒正美的博客來說,我在群里吐槽了他博客風格好幾次(被罵回來了…理由是每個人審美觀不一樣),你可以去瞅瞅他的頁面,代碼字體實在是太小了,每次看他的博客都會把字號和行高調大一點,后來直接寫個腳本放在收藏夾,進入他的網頁一鍵處理。

這個例子說明,每個人的口味不一樣。一個網站,倘若冷暖色調,字體大小等可以自定義的話就更棒了,我沒做那么復雜,就是給文章加了個黑色主題。

通過這個按鈕可以進行相應的設置。然后是側邊欄下面的幾個按鈕:

“跟我對話”點擊之后會在右下角往上蹦出一個浮層:

這個浮層是可拖動的。

2) 側邊欄-展開

做了個未展開的側邊欄其實也差不多了,后來發現我的頁面中好像並沒有“文章歸檔”,“最新文章”,“最近評論”等這些對一個博客來說很常見的元素,於是乎,抄襲了下豆瓣FM的設計,弄了下面的東西:

這塊效果還挺難做的,主要是滾動不好處理。左側是一個 fixed 定位,容器的高度是死的,也就是 $(window).height() 的高度,blabla.. 細節我不說了,如果你感興趣可以去思考下如何實現類似豆瓣FM左側的功能塊。我后來是監聽鼠標滾動設置負margi-top值來模擬頁面滾動。並且這個監聽是在整個 document 而不是僅僅是 左側的 box 上。

整體效果實現並不復雜,麻煩的是一些細節處理。

2. 底部的設計與實現

底部的設計我最糾結的是內容,到底放點什么東西。跟文章相關度最高的,一是相關文章,二是評論,所以也就只把這兩樣放上了。

三、后台設計和數據庫

開始想過后台用 wordpress 或者其他的框架系統來構建,但是這些東西提供的接口比較冗余,而且功能復雜,沒有全盤研究過他們的源碼,最后決定自己寫一套后端框架以及前后端接口,工作量立馬就上去了… 我也是想趁此機會回顧下 php 和 mysql 的知識,太久不用都生疏了。

1. 舊博客寫入數據庫

以前的博客都是使用 Markdown 語法寫的,Markdown 的優點就是簡潔清晰,但是在解析的時候總是會有這樣那樣的問題,並且很多 Markdown 解析工具都不支持給元素添加 id 或者 class,這讓人很糾結。所以存入數據的文章已經解析成 HTML 了。

Github pages 支持 jekyll 語法,jekyll 允許使用 Markdown,使用 jekyll 語法寫的文章內容中多了很多 `{{xxx.xxx}}`

對頭部的解析也沒啥好辦法,就是使用正則來匹配:

$html = file_get_contents($path);
$reg = "/---\n\s*layout:\s*[\s\S]+?\ntitle:\s*(?<title>[\s\S]+?)\n"
  . "description:\s*(?<description>[\s\S]+?)\ncategory:\s*"
  . "(?<category>[\s\S]+?)\n(tags:\s*(?<tags>[\s\S]+?)\n)?---\n(?<content>[\s\S]+)/";

preg_match_all($reg, $html, $match);

由於文章並沒有集中放在一個文件夾,寫了個遍歷文件夾的 travel 函數:

function traverse($path = '.') {
    $current_dir = opendir($path);
    while(($file = readdir($current_dir)) !== false) {
        $sub_dir = $path . DIRECTORY_SEPARATOR . $file;
        if($file == '.' || $file == '..') {
            continue;
        } else if(is_dir($sub_dir)) {
            //echo 'Directory ' . $file . ':<br>';
            traverse($sub_dir);
        } else {
            //echo 'File in Directory ' . $path . ': ' . $file . '<br>';
            dealFile($path . DIRECTORY_SEPARATOR . $file);
        }
    }
}   

這里需要注意的是,存入數據庫之前要處理一些單雙引號/UTF-16字符,否則存入的時候會出錯。

function remSpecialChars($string) {
    $string = stripslashes($string);
    $string = preg_replace("/'/","&#039;",$string);
    $string = preg_replace('/"/','&quot;',$string);
    return $string;

取出的時候還原單雙引號:

function addSpecialChars($string) {
    //  $string = htmlspecialchars($string);
    $string = preg_replace("/&#039;/","'",$string);
    $string = preg_replace('/&quot;/','"',$string);
    return $string;
}

2. 網頁各個模塊的處理

網頁中,正文、底部和邊欄需要數據,所以數據的查詢主要是針對這三塊。

目前這三塊數據是后台直接同時輸出的,稍微想想就知道這個效率並不高,后續肯定會改成異步接口。封裝之后,獲取並渲染一篇文章就變得異常輕松了:

include 'page.class.php';

$page = new PageInitor();

# 正文內容
$post = $page->getPageByTitleEn($_GET['title']);
# 底部和側邊內容
$otherData = $page->getPostOtherData();

后台數據的渲染都是:

如果改成前端異步獲取,那前端又得寫一套模板渲染數據,這里感覺流程上存在冗余,后期肯定會改進。

3. 內容的解析

文章內容的編寫還是使用Markdown,盡管他在某些地方不能滿足我的需求。內容的解析使用的是 michelf 的 php-markdown 開源框架:

$cotent = file_get_contents($path);
$html = Markdown::defaultTransform($content);

使用起來也是十分方便,但是上面的函數只能解析一些基礎的 Markdown 格式,諸如圖片、表格等解析不出來。這需要引入:

# Get Markdown class
use \Michelf\Markdown;
use \Michelf\MarkdownExtra;

# 然后使用
MarkdownExtra::defaultTransform($content)

使用 MarkdownExtra 的類來解析, MarkdownExtra 是繼承 \Michelf\_MarkdownExtra_TmpImpl 的。

四、服務器的設置和維護

目前使用 apache 作為服務器已經夠用了,需要緩存的頁面也並不多,就是幾個列表頁和搜索頁,所以這方面可以采用技術成熟的 memcache 來處理,只不過后期在同一台服務器上會搭建多個網站,每個網站對應的域名不一樣,並且有些網站的后台會使用 nodeJS 來編寫,所以還是需要 Nginx 來配置 Virtual Host,Apache 也可以實現 Vhost 的配置,我在本地測試的時候就是使用的 apache 的 Vhost,這里也簡單說說 vhost 的配置。

1. apache 的 vhost 配置

配置步驟如下:

  1. 在 httpd.conf 中開啟 vhost 模塊,並 include 其配置文件 httpd-vhosts.conf
  2. 在 httpd-vhosts.conf 寫入
# 這是配置 localhost 這個"域名"
<VirtualHost *:80>
    ServerAdmin i@localhost
    DocumentRoot "E:/wamp/www"
    ServerName localhost
    ServerAlias localhost
    ErrorLog "logs/localhost.log"
    CustomLog "logs/localhost-access.log" common
</VirtualHost>

# 這是配置 test.barretlee.com 這個域名
<VirtualHost *:80>
    ServerAdmin test@barretlee.com
    DocumentRoot "E:/wamp/www/barretlee"
    ServerName test.barretlee.com
    ErrorLog "logs/test.barretlee.com-error.log"
    CustomLog "logs/test.barretlee.com-access.log" common
</VirtualHost>

因為網上對這方面的配置有詳細說明,我也不是行家,就不細說了。

2. Rewrite模塊

其實就是網頁的靜態化,我們看到的php頁面是:

 /index.php?id=23

但是我們更希望通過這種方式來獲取頁面:

/index.php/23

URL 需要進行重寫,算是內部重定向吧。這方面的工作可以交給 Nginx 來處理,也可以交給 Apache,由於我本地目前還只配置了 Apache,所以先看看 Apache 的配置方式:

1) 使用了Vhost

<VirtualHost *:80>
    ServerAdmin test@barretlee.com
    DocumentRoot "E:/wamp/www/barretlee"
    ServerName test.barretlee.com
    ErrorLog "logs/test.barretlee.com-error.log"
    CustomLog "logs/test.barretlee.com-access.log" common

    <Directory E:\wamp\www\barretlee>
        Options FollowSymLinks
        AllowOverride None
        Order deny,allow
        Allow from all

        RewriteEngine on
        RewriteRule ^blog/(\d+)/(\d+)/(.*).html$ index.php?title=$3&year=$1&month=$2
        RewriteRule ^static/(.*)$ static/$1
    </Directory>
</VirtualHost>

如果使用了 Vhost,可以在配置里寫上 RewriteEngine on,然后加上需要的 RewriteRule 規則就行了。

2) 沒有使用 Vhost

在網頁所在文件的根目錄下,新建一個 .htaccess 文件,里頭寫上:

RewriteEngine on
RewriteBase /barretlee
RewriteRule ^blog/(\d+)/(\d+)/(.*).html$ index.php?title=$3&year=$1&month=$2
RewriteRule ^static/(.*)$ static/$1

重定向的內容就行了。

第二種方式會存在一個問題,如果你的資源請求在 /barretlee 的上一層或者上幾層,那么這里的正則就會匹配不到了,所以建議使用 Vhost 來配置自己的 Apache。

五、后期優化和改進

上面說了這么多,都是這七天來建站的總結,目前的狀態是,博客系統已經搭建完畢,但是沒有寫博客和管理博客的后台,這又是件頭疼的事情,不過還好,后台之后自己看得見,就隨意一些。也沒有歸檔頁面、分類頁等頁面,這些頁面的設計也是傷腦細胞的。

整個網站,博客系統只是一個部分,還有其他的問答平台、好文的爬蟲抓取、每月期刊、每周好文推送、郵件系統等等,工程量還蠻大,這對我來說也是一個挑戰,可以盡情發揮自己的技能,也是個深度學習的好機會!

頁面的加載,首屏時間不能忍受,如果文章篇幅比較大,大約需要1.5到3s才渲染完畢,這個值有點不能忍受。優化方向有:

  • PJAX,頁面采用 pushState + AJAX,減少請求,不支持 pushState 的頁面采用 hash bang 兼容處理。
  • bigPipe,如果文章內容比較多,或者其他的模塊有所增加,會采用 bigPipe 分撥往前端扔數據。
  • 前后端統一模板,之前也提到了這個問題,后端渲染的時候使用的后端模板,如果前端要異步加載,則需要重新寫一套模板來解析合並數據,這兩個模板的相似度是很高的,如果可以復用將減少很多工作量。
  • 靜態數據的緩存問題
  • ETag等對頁面的標記緩存問題

六、小結

我最怕的是事情沒有一個開始,現在既然已經開始了,我想,離結束也就不遠了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM