前端項目結構設計精細方案


開始的開始,前端項目很簡單,html放外面,然后新建一個css和js文件夾,看起來很清晰。

隨着時間推進,項目變大,問題開始一一出現了:

  • html 太多,找起來麻煩
  • css 和 js 需要壓縮
  • css 和 js需要發布到 CDN
  • 開始只簡單依賴一個jQuery,后來發現依賴的插件越來越多,不好更新維護
  • html 里面怎么實現公共一個頭
  • js和css包含大量重復代碼,怎么重構項目
  • 前端如何把代碼交付給后端填模板代碼

很多公司面對這些問題都有了自己的方案,Node 因為語言也是JS,成了很多公司的首選。

相關的熱門框架有grunt,gulp,webpack,bower等等。

願意讀文檔的人早以用上這些新奇玩意兒並且解決了大量前端問題。

 

雖然工具很多,但對於很多新團隊來說,如何完美地規划項目卻仍然是一道坎。

他們不知道應該在何時,如何使用這些工具。前端項目的設計可以非常隨意,正是這些隨意,讓很多人在選擇中開始迷茫。

 

本文將提供一個趨於完美的前端項目結構規划方案,希望能為各位在重構前端項目時提供幫助。

一個規划方案,並不只是定義文件怎么放,文件怎么命名,而更重要的是包含實現整個流程的工具,如果沒有工具支持,所有方案都是扯淡。

 

前端項目結構

根目錄
  |- assets:  存放所有js和css等,這些資源可能發布到 CDN
  |  |- images: 存放所有 CSS 樣式需要的背景圖片
| |- fonts: 存放所有 CSS 樣式需要的字體 | |- styles: 存放所有CSS
| | |- common: 存放公共的 CSS 代碼 | |- scripts: 存放所有 JS
| | |- common: 存放公共的 JS 代碼 |- include: 存放所有公共的 HTML 頭尾片段 |- images: 存放前景圖片和flash |- libs: 存放前端所需的第三方類庫 |- views: 如果使用了后端 MVC 框架,則頁面放在這里。 |- _my: 存放開發者自己需要的文件,這個文件夾應該被 GIT 和 SVN 忽略掉。 |- page1.html 存放最終的前端頁面,如果使用了 MVC 框架則不需要。

HTML 文檔結構

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>標題</title>
    <!-- #include virtual="/include/header.inc" -->
    <link rel="stylesheet" type="text/css" href="assets/styles/common/blog.css" />
    <link rel="stylesheet" type="text/css" href="assets/styles/page2.css" />
</head>
<body>
    <!-- #include virtual="/include/body.inc" -->
    內容
    <!-- #include virtual="/include/footer.inc" -->
    <script type="text/javascript" src="assets/scripts/common/blog.js"></script>
    <script type="text/javascript" src="assets/scripts/page2.js"></script>

    <!-- #include virtual="/include/stat.inc" -->
</body>
</html>

/include/header.inc:

    <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui, maximum-scale=1, user-scalable=no" />
    <meta name="apple-itunes-app" content="app-id, app-argument=">

    <meta name="description" content="" />
    <meta name="keywords" content="" />

    <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="" />
    <link rel="shortcut icon" href="favicon.ico" />
    <link rel="apple-touch-icon" href="favicon.png">

    <link rel="stylesheet" type="text/css" href="../assets/styles/common/common.css" />

/include/body.inc:

這里可以放一些全站公用的頁頭,比如需要為全站加一個緊急通知的 banner,可以加在這里。

<!--[if lt IE 9]>
<div role="alert">你的瀏覽器實在<strong>太太太太太太舊了</strong>,放學別走,升級完瀏覽器再說 <a target="_blank" class="alert-link"
 href="http://browsehappy.com">立即升級</a>
</div>
<![endif]-->

/include/footer.inc:

這里可以放一些全站公用的頁腳,比如版權聲明之類。

<div>版權所有 @copy; 2015 xuld</div>
<script type="text/javascript" src="assets/scripts/common/common.js"></script>

/include/stat.inc:

這里可以放一些網站統計代碼。

<!-- 在這里添加網站統計代碼 -->

其它文件

如果項目里還有公共的側邊欄、廣告位等,也可以自行在 include 添加其它文件。

如果一個網站需要有多種不同版權聲明,可以分別做一個 footer-full.inc 和 footer-simple.inc,然后公共包含:footer-common.inc。

靜態資源引用

如果項目里需要使用 less/sass/coffee 等技術,則可以直接引用這些文件。發布時,發布工具完成這些事情:

1. 編譯 less/sass/coffee 文件,轉換為對應的 css/js 文件。

2. 更新 HTML 文件里的資源引用地址,引用生成好的 css/js 文件。

3. 為這些資源文件引用地址添加時間戳。

4. 如果項目使用了 CDN,則發布工具應該自動上傳文件到 CDN,並更改文件里的路徑為 CDN 的地址。

發布前:

<link rel="stylesheet" type="text/css" href="../assets/styles/page1.less" />

發布后:

<link rel="stylesheet" type="text/css" href="http://cdn.com/project/assets/styles/page1.css?_=md5" />

時間戳問題

靜態文件由於存在緩存,每次發布如果保持路徑不變,很容易導致頁面不更新。有三種方案:

  1. 為路徑加上 ?_=md5
  2. 更新文件名為 page1_md5.js
  3. 復制到名為 20151021 的文件夾

個人建議使用方案1,因為改動量少,不易出錯。但如果CDN不支持,可以采用其它方案。

腳本和樣式

如果項目中,一個人專門負責 css,一個人專門負責 js,一個人專門負責將 html 轉換為后台代碼,則上述文件夾結構是比較合理的。

如果是同一個人負責css和js,則建議不區分 styles 和 scripts 文件夾,直接放在 assets 目錄。

如果連轉換html 到后台代碼都是同一個人,則建議將 css 和 js 直接寫在頁面里,發布工具負責提取出來:

<style __dest="assets/styles/page1.css">
   /*  CSS 代碼 */
</style>

公共代碼依賴

每個HTML頁面,都必須引3個js和3個css,分別是:

  • 全站公用的 js:common/common.js
  • 全項目(或類似頁面,比如列表頁、詳情頁)公用的js:common/blog.js
  • 頁面私有的js:common/page1.js

css 和 js處理方式一致,且一一對應。

個別頁面可以引入一些外部的js和css,比如 editor.js 這種比較大的文件。但原則上每個文件最多只能引 5個js和5個css。需要引的文件多時則需要打包合並。

出於性能考慮,有時候可以將頁面私有的js和css直接內聯到頁面。

<script src="assets/page1.js?__inline"></script>

模塊化組件

所有可復用組件、第三方框架都放在 libs,libs 文件發布時會被忽略掉,項目里也不能直接引用 libs 下的代碼。

如果需要引用一個組件,有三種方案:

  • 簡單的文件包含
  • 基於 CommonJS 模塊化方案
  • 基於其它模塊化方案

簡單的文件包含

如果項目較小,並不需要太大模塊化東西,直接使用文件包含是最方便的:

common.js

// #include /libs/3rdlibs/jquery-2.1.0.js
// #include /libs/3rdlibs/jquery.mobile.js


// 其它項目需要的公共代碼

發布工具會處理 #include 。

CommonJS 模塊化方案

var $ = require('libs/3rdlibs/jquery');

發布后,CommonJs 模塊會被轉換為標准的 AMD 模塊。

打包問題

假設一個頁面需要引用 common.js 和 page1.js ,而這2個js又分別引用了 libs 下的若干個組件(可能有重復)

那么 page1.js 可以添加如下指令排除掉 common.js 所引入的文件

// #exclude common.js
var $ = require('libs/3rdlibs/jquery');

最后生成的代碼,page1.js 將包含所有所需的模塊,並刪除了 common.js 包含的模塊。

項目發布和調試

以上所介紹的代碼方案是不能直接在瀏覽器運行的,這里有三個方案可以實現本文所描述的各個功能:

  1. 在瀏覽器執行 JS 實現上文所描述的所有功能。優點:兼容性好,缺點:效率低。
  2. 監聽文件改變,文件保存后就解析以上指令並生成文件。優點:兼容性好,處理方便,缺點:不穩定。
  3. 自定義服務器,這個服務器在請求時自動完成生成任務。優點:效率高且穩定,缺點:需要定制服務器,且只在開發時使用。

其它工具支持

占位圖

對應經常切頁面的哥們,占位圖是非常有用的。

<img src="@100x100.jpg">

Ajax 接口模擬

a.njs:

writeJsonp({
    a: 1
});

 

寫在最后

本文所描述的是一種建議的做法,也是一個發布工具所需要提供的功能。每個團隊可以針對自己的需求做一些個別的定制。本文所提到的示例都是以 tpack 為原型書寫的。不同的工具會有稍微不同的寫法。但是其解決的問題是一樣的。


免責聲明!

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



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