本文結合最近的工做經驗,總結出一個較簡潔的前端自動化構建方案,主張css和js的模塊化,並經過grunt的自動化構建,有效地解決css合併,js合併和圖片優化等問題,對於提升前端性能和項目代碼質量有必定參考價值,歡迎閱讀和點評:)php
github地址:https://github.com/liuyunzhuge/generator-webcss
demo地址:https://liuyunzhuge.github.io/generator-web/html
有興趣的同窗,在閱讀文章,學習或使用demo的過程當中,有任何的疑惑或者發現的問題儘管在評論中與我討論。前端
本項目是一個腳手架,應用於先後端結合型項目,能夠爲這種項目提供以下服務:java
先後端結合型項目是指javaweb,asp.net這種非先後端徹底分離的項目,頁面一般是jsp,aspx,php等模板,部署時的更新包同時包含先後端的文件,屬於傳統的項目類型。node
本腳手架應用場景受限於先後端結合型項目,它僅能解決這類項目的前端構建的工做,對於後端構建以及項目打包發佈的工做須要由後端來完成,若是你的是javaweb類型,後端發佈能夠用maven,它可同時完成後端構建和打包的任務。之因此有本腳手架的產生,主要仍是由於目前先後端結合型項目的開發方式仍是很是常見,畢竟不是每一個公司都有資源去作到徹底的先後端分離這類的架構,尤爲是小公司或者是項目型公司,沒有那麼的人和時間等資源能讓你玩高級的東西,快速開發纔是王道。可是對於任何一個web項目來講,前端部分的基礎服務都是同樣的,好比圖片優化,css和js合併壓縮等,並且這都是在團隊資源可行的狀況下最好作的,對於項目質量,只有好處沒有壞處。本腳手架的產生,正是從工做中總結出來的一套開發架子,基於這個架子,你能夠很方便獲得由它給你帶來的如下好處:jquery
WEB-INF/ html/ img/ js/ less/ Gruntfile.js bower.json optimize.json package.json
由於本腳手架是結合demo一塊兒發佈到github上的,demo是基於javaweb的,因此你會看到裏面有個WEB-INF/文件夾,這個是javaweb必須的,html/裏面的頁面都是jsp模板,這個也是javaweb必須的;因此若是你想把這個腳手架應用於asp.net和php須要你刪掉WEB-INF這個文件夾,而後將html/裏的jsp改爲aspx或php模板。linux
另外,無論你想把這個腳手架用於什麼類型的項目,最好的使用方式是先把demo跑起來,而後在demo的基礎上開發,這樣可以減小出錯~git
html/ 用來存放頁面的模板(jsp,aspx,php)或html文件 img/ 存放圖片 js/ 存放js less/ 存放less Gruntfile.js 這是grunt任務的配置文件 bower.json 這是bower的配置文件 optimize.json 這是requirejs的優化工具的配置文件 package.json 這是grunt依賴的配置文件
注:html/,img/,js/,less/這三個文件夾裏面還有子文件夾,各自都有相關的約定,後續逐個介紹。在demo運行成功以前,那幾個配置文件請先不要改動。github
查看DEMO:https://liuyunzhuge.github.io/generator-web/ 支持IE9+,chrome,firefox。
該DEMO是gh-pages搭建,你能夠經過查看本項目的gh-pages分支看到demo的文件內容,因爲github提供的這種服務僅支持靜態網頁,因此demo的首頁實際上是由html/index.jsp轉化過來的,另外位置也變了一下,index.jsp原來是放置在html/下面的,gh-pages分支裏的index.html放在了跟html/同級的位置,不這麼幹的話,gh-pages就看不到效果了。
因爲本項目是結合javaweb一塊兒發佈的,因此如下的使用步驟均是在java的開發環境下說明的,IDE爲Intellij IDEA。若是你的項目也是javaweb項目,那麼推薦你用這個IDE,這是本人用過的最好的java web開發工具,集成了衆多前端工具,好比less,emmet和grunt還有bower等。若是你用它來開發項目,你會發現編寫less和使用grunt是如此順暢!純粹的後臺開發可能不挑剔開發工具,可是前端開發若是要結合後臺一塊兒弄一下的話, 最好仍是使用高級一點的IDE。
安裝nodejs,git,bower,grunt。windows下安裝便可,不須要linux。其中:
注:這一步與IDE和後端語言沒有任何關係。無論什麼語言的項目,這個都是使用本腳手架的基礎。
新建web項目,好比我用IDEA新建一個項目名爲generator-web-demo,它的項目結構以下:
.idea/ src/ web/ generator-web-demo.iml
其中.iead/和generator-web.iml都是IDEA建完項目之後建立的,能夠不用管。src是java源文件的目錄,web文件夾是項目的web根目錄。
在github上,download zip或者用git clone本項目,複製本項目的如下文件夾或文件粘貼到你項目的web根目錄(前一步提到的web文件夾):
html/ img/ js/ less/ WEB-INF/ bower.json Gruntfile.js optimize.json package.json
WEB-INF直接覆蓋原來的WEB-INF便可。若是原來的web/下有一個index.jsp,能夠把它刪掉,個人習慣是把頁面都放一塊,html/已經提供一個index.jsp了,因此原來的index.jsp多餘了。
最後你的項目結構應該以下:
.idea/ src/ web/ html/ img/ js/ less/ WEB-INF/ bower.json Gruntfile.js optimize.json package.json generator-web-demo.iml
使用bower安裝bower.json中配置的庫(jquery,iCheck,requirejs,bootstrap)
bower install --save
注:以上庫除requirejs是腳手架必須的外,其它都可根據實際項目須要進行添加和刪除,不過爲了把demo先跑起來,仍是別去改它,看懂了構建的原理再來根據項目須要修改也不遲。
安裝grunt和grunt插件:
npm install --save
若是npm安裝速度慢,能夠按下面網址提供的方式安裝,速度會快一些: http://npm.taobao.org/
執行grunt的default任務:
grunt default
若是執行grunt這個任務報錯,通常都是grunt-contrib-imagemin插件報的錯,你能夠用下面的命令重裝grunt-contrib-imagemin
npm uninstall grunt-contrib-imagemin --save npm install grunt-contrib-imagemin --save
注:以上是兩個命令,分開執行。若是還報一樣錯誤,可將以上命令多試幾回。
最後啓動你的web服務器,好比tomcat。打開瀏覽器訪問應該就能看到跟demo一致的首頁效果:)。
本部分介紹如何在demo的基礎上進行開發。
每新增一個頁面都放在html/下面,目前demo內包含:
html/ base/ body_end.jsp head_end.jsp head_start.jsp index.jsp ltIE9.html
其中:base/下的是一些公共的jsp頁面,你看下index.jsp裏面的那些inclue你就明白了。 ltIE9.html是一個提示頁面,若是用戶以IE8及如下的IE瀏覽器訪問就會跳到這個頁面提示更新瀏覽器或者下其它的好用的瀏覽器。
若是你的項目是asp.net的項目,請把這些jsp都替換成aspx。
這個html/的思路是:base/放公共的,其它頁面按模塊分,若是一個模塊只有一個頁面,那麼就把它直接放在html/下面,若是一個模塊有多個頁面,能夠在html/以模塊名建一個文件夾,相關頁面都放那裏面。
你在開發頁面的時候,建議:html/base/下的公共jsp保留,新頁面以index.jsp爲參考進行開發,能夠往base/內添加更多公共頁面,也可按模塊對新頁面進行分類。
這個問題是這樣的,打比方說:
base元素設置的代碼以下<head_start.jsp>:
<% String base = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); base += base.endsWith("/") ? "" : "/"; request.setAttribute("base", base); request.setAttribute("rnd", "?v=0.0.1"); %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <base href="${base}"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!--[if lt IE 9]> <meta http-equiv="Refresh" content="0; url=${base}html/ltIE9.html"/> <![endif]-->
引用css,圖片和js時,直接使用相對web根目錄的路徑進行引用:
<link href="css/index.css" rel="stylesheet"> <img src="img/dist/logo.png" alt="LOGO"> <script data-main="js/dist/mod/index" src="js/dist/lib/require.js"></script>
還記得web根目錄的這個結構吧:
web/ img/ css/ js/
約定項目相關的圖片放在img文件夾下,img/的結構爲:
img/ dist/ src/ temp/
這個目錄結構最好是不改變。其中:
每增長一張圖片或雪碧圖,就把它丟到img/src裏面,頁面或css中引用圖片時,直接使用img/dist/這個路徑去引用便可。
約定css都用less來編寫,less文件夾的結構爲:
less/ app/ icon/ mixin/ widget/ mod/ sprite/
其中:
grunt的less任務,會把app/icon/下的字體拷貝到web/css/下,把app/mod/下的less編譯成的css也放到web/css/下,因此頁面引入css的時候,要相對css/這個文件夾引用:
<link href="css/index.css" rel="stylesheet">
在這一塊須要注意的問題是字體文件和圖片文件的路徑問題,記住less編譯後的css是放在css/下面的,而圖片優化後是放在img/dist/下面的;字體文件跟css默認都是直接位於css/目錄下的,具體請多參考demo中app/mod/index.less。
約定js源碼都在js/src/下定義,js/src/的結構爲
js/ js/src/ app/ mod/ widget/ lib/ mod/ common.js
其中:
在沒有優化以前,grunt任務會把js/src/的文件所有拷貝到js/dist/下,在優化以後,grunt任務會把js/dist/mod/下的每一個js依賴的全部js,都跟它合併成爲一個js。無論有沒有優化,頁面引用js文件時,都要相對js/dist這個目錄引用!
一個頁面相關的js整個加載流程,以demo中的index.js爲例:
<script data-main="js/dist/mod/index" src="js/dist/lib/require.js"></script>
加載js/dist/mod/index.js requirejs(['../common'], function (common) { requirejs(['app/mod/index']); });
因此開發一個js的步驟爲,假設要開發一個userCenter.js:
requirejs(['../common'], function (common) { requirejs(['app/mod/userCenter']); });
另外還要在optimize.json中增長一個對userCenter.js的配置項,以便生產環境構建時能把它依賴的js都跟它合併成一個js 。
簡單點來講,照着這個模板就能夠了:
[ { "name": "../mod/index", "include": [ "app/mod/index" ] } ]
好比若是userCenter.js,那麼就該配置成:
[ { "name": "../mod/index", "include": [ "app/mod/index" ] }, { "name": "../mod/userCenter", "include": [ "app/mod/userCenter" ] } ]
具體的原理牽扯的細節就比較多了,可參考如下兩個網址去研究一下:
grunt default
使用以上任務就會啓動構建,包括:
這個構建不會壓縮css,不會合並壓縮混淆js。
grunt release
使用以上任務,完成生產環境構建:
grunt optimize
這個任務可用於測試requirejs的合併是否正確,實際使用方式以下:
grunt default
grunt optimize
之因此沒跟default任務合併,是由於這個優化任務比較費時,不用每次開發的時候都執行優化
打包前,先執行下grunt release
,並將修改提交至代碼服務器。另外bower_components和node_modules這兩個文件夾千萬別傳到代碼服務器上去,前端用的東西,打包的後臺同事怎麼會要你這個呢;還要記得提醒他們把如下文件夾從工程中排除出去:
img/src/ img/temp/ js/src/ less/
這些文件是沒有必要發佈出去的。至於具體怎麼打包,就是後臺同事的責任了。
目前已知的未解決的問題:
下一步計劃就是要解決以上問題。