面對日益複雜的前端環境以及前端技術、node技術的高速發展,前端的開發也愈來愈工程化,體系化,也就是出現了前端自動化構建工具。他們完成的任務目標基本是:javascript
- js,css,圖片的自動壓縮合並(圖片也便是是自動sprite)
- js,css,圖片自動添加域名
- js,css,圖片自動添加md5或版本號
- 自動監聽文件變化
- sass/less/coffee等的自動編譯
- 支持amd/cmd的模塊開發,可自動文件依賴
- 能夠部署文件
- 網頁自動刷新
- 實時編譯
成熟的前端構建工具也有不少,好比:Gulp.js,Grunt,webpark, fis等等,其餘構建工具本人使用很少,本文主要是對fis的前端工程化和模塊化的使用作詳細介紹php
fis是百度研發的一套前端構建工具,擁有豐富的腳手架和組件倉庫。由於fis是本人接觸的最先的前端構建工具,因此一直沿用到了至今。css
注: 本文是針對fis2,基於fis3的配置和插件將在稍後給出
//開始autoCombine能夠將零散資源進行自動打包 fis.config.set('settings.postpackager.simple.autoCombine', true); //開啓autoReflow使得在關閉autoCombine的狀況下,依然會優化腳本與樣式資源引用位置 fis.config.set('settings.postpackager.simple.autoReflow', true); fis.config.set('settings.postpackager.simple.output', 'pkg/mcren_${hash}');
將html中分散的靜態資源進行自動合併打包html
原始文件前端
<link rel="stylesheet" type="text/css" href="/css/mcren.css"> <link rel="stylesheet" type="text/css" href="/site/index/index/index.css">
轉換後java
<link type="text/css" rel="stylesheet" href="/pkg/mcren_7636e.css">
能夠看到fis會自動合併多個css到同一個文件裏,這個合併不只僅適用於css,也一樣適用與js,而且將自動把css文件放入header頭,js放在body結束前,有了這個功能也就具有的模塊化開發的大前提node
默認支持,無須插件jquery
你們在使用模板的時候,確定是少不了include功能的, 即公共部分的文件引用。fis一樣支持這個功能,並且藉助與自動打包功能,include功能的做用也被放大的不少.(fis支持多級include)git
<!DOCTYPE html> <html> <head> <meta name="description" content=""> <meta name="keywords" content=""> <link rel="stylesheet" type="text/css" href="/css/mcren.css"> <link rel="stylesheet" type="text/css" href="/site/index/index/index.css"> <script type="text/javascript" src="/lib/mod.js"></script> </head> <body> <link rel="import" href="/widget/header-small/header.html?__inline">
<link rel="stylesheet" type="text/css" href="header.css"> <div class="header"> <div> <link rel="import" href="../loginstate/loginstate.html?__inline"><h1><a href="/">主頁</a></h1> </div> </div> <script type="text/javascript"> var jsfunc = require('jsfunc/jsfunc'); jsfunc.init(); </script>
<!DOCTYPE html> <html> <head> <meta name="description" content=""> <meta name="keywords" content=""> <link type="text/css" rel="stylesheet" href="/pkg/mcren_7636e.css"> </head> <body> <div class="header"> <div> <div class="loginstate"> <a href="/space">左鹽</a> | <a href="javascript:void(0);">退出</a><img src="member.jpg" id="avatar" /> </div> <h1><a href="/">名場</a></h1> </div> </div> <!--省略的html代碼--> <script type="text/javascript" src="/lib/mod.js"></script> <script type="text/javascript"> var jsfunc = require('jsfunc/jsfunc'); jsfunc.init(); </script> </body>
能夠看到,通過fis處理後,原本應該分散的css被組合放進了head頭裏,js被放在了body結束前,模板的html代碼也正常引入了進去。github
另外你們能夠看到我模塊的劃分,header模塊的html是引入css的,也就是說模塊與模塊之間以及模塊和主體頁面之間的css都是獨立的,這樣充分解耦,能夠有效的解決css的維護問題,
fis.config.set('modules.spriter', 'csssprites');
自動把css中的圖片轉換成雪碧圖
不寫了,你們都懂的
//tell fis that `.ejs` is a js file fis.config.set('roadmap.ext.ejs', 'js'); //tell fis that parse `.ejs` file by using `fis-parser-ejs` plugin fis.config.set('modules.parser.ejs', 'ejs');
你們知道,寫js打印html字符串到頁面的時候,若是在js裏面串接html字符串是一種很難受的體驗,因此fis也就有了這個插件,這個插件能夠給js方法添加引用ejs模板的能力,這裏ejs的使用方法和原生的徹底兼容
function ejsEx() { var tpl = __inline('comment.ejs'); var s = tpl({ title: "個人ejs模板" }); console.log(s); }
<h1><%= title%></h1>
<h1>個人ejs模板</h1>
上面已經介紹了fis的模塊化基礎能力,如今開始實踐fis的模塊化開發能力。固然fis的amd/cmd,域名添加等等基礎功能,這裏沒有敘述,您能夠自行上官網查看學習
根目錄
css //less生成的css文件
font //字體圖標文件
img //公共圖片
less
lib //系統類庫
modules //經常使用的modulejquery
laydate
layer
pizzalayer
pizzatools //網站工具類
pizzaui //ui組件
store //本地化插件
xss //xss過濾插件
site //非模塊的css,js
views //網頁模板文件
widget //模塊head //頭部模塊
footer //底部模塊
nav //菜單模塊
fis-conf.js //fis配置文件
由於個人技術構架是: 前端 + nodejs + api,因此使用這種目錄結構,用戶可根據本身的項目目錄自由更改。
modules都是工具類,只包含js,
目錄結構爲:
---根目錄 ----modules -----jquery ------jquery-1.11.3.min.js
引用方式爲:require('文件夾名字')
require('jquery')
widget目錄都是網站模塊,可包含js,css,html,圖片
目錄結構爲:
---根目錄 ----widget -----loginstate ------loginstate.less ------loginstate.js ------loginstate.html ------loginstate.jpg
引用方式爲:
<link rel="import" href="/widget/loginstate/loginstate.html?__inline">
<link rel="stylesheet" type="text/css" href="loginstate.css"> <div class="loginstate"> <a href="/space">左鹽</a> | <a href="javascript:void(0);">退出</a><img src="member.jpg" id="avatar" /> </div> <script type="text/javascript"> var loginstate = require('loginstate/loginstate'); loginstate.init(); </script>
var $ = require('jquery'); var tools = require('pizzatools'); require('pizzalayer'); var loginState = new function() { var _self = this; /** * 打印登陸狀態 * @return {[type]} [description] */ _self.init = function() { var s = ''; var id = tools.getCookie('id'); if(id == '0' ) {//未登陸 s = '<a href="/login?f='+document.location.href+'" class="btn btn-primary">登陸</a> <a href="/reg" class="btn btn-primary">註冊</a>'; } else { s = '<a href="/space">' + tools.getCookie('nickname') + '</a> | <a href="javascript:void(0);" onclick="loginstate.loginout();">退出</a><img src="' + tools.siteData.url.avatar + tools.getCookie('avatar') + '!v1" id="avatar" />'; } $('.loginstate').html(s); } /** * 退出登陸 * @return {[type]} [description] */ _self.loginout = function() { $.ajax({ type:'GET', url:'/index/loginout', success: function(msg) { var url = document.location.href.split('/'); if(url[3] == 'space') { document.location.href = '/'; } else { document.location.reload(); } } }) } } module.exports = loginState;
<div class="header"> <div> <link rel="import" href="/widget/loginstate/loginstate.html?__inline"><h1><a href="/">主頁</a></h1> </div> </div>
由此前端模塊化已經所有完成
npm install 以上插件便可
結合個人項目,本人的配置文件以下。下載本配置文件而且安裝好fis後,能夠直接使用。(因爲項目發展時間很長,配置文件已經顯得囉嗦,若是大拿研究了fis,可自行優化本身的配置文件)
fis.config.set('livereload.port', 8136); //use css sprites fis.config.set('modules.spriter', 'csssprites'); //tell fis that `.ejs` is a js file fis.config.set('roadmap.ext.ejs', 'js'); //tell fis that parse `.ejs` file by using `fis-parser-ejs` plugin fis.config.set('modules.parser.ejs', 'ejs'); //set options if you need //@see https://github.com/visionmedia/ejs#options fis.config.set('settings.parser.ejs', { open: '<%', close: '%>' }); //使用simple插件,自動應用pack的資源引用 fis.config.set('modules.postpackager', 'simple'); //開始autoCombine能夠將零散資源進行自動打包 fis.config.set('settings.postpackager.simple.autoCombine', true); //開啓autoReflow使得在關閉autoCombine的狀況下,依然會優化腳本與樣式資源引用位置 fis.config.set('settings.postpackager.simple.autoReflow', true); fis.config.set('settings.postpackager.simple.output', 'pkg/mcren_${hash}'); fis.config.merge({ pack: { 'pkg/base.js': ['/modules/jquery/*.js', '/modules/layer/*.js', '/modules/pizzalayer/*.js', '/modules/pizzatools/*.js'], 'pkg/kindeditor.js': ['/widget/kindeditor/kindeditor-min.js'] } }); fis.config.merge({ statics: '/public', modules: { postprocessor: { js: "jswrapper, require-async", html: "require-async" }, postpackager: ['autoload', 'simple'], lint: { js: 'jshint' } }, roadmap: { ext: { }, path: [{ reg: /^\/modules\/laydate\/(need|skins)\/.*\.(js|css|png|gif)$/i, useHash: false, isMod: false, release: '${statics}/$&', url: '$&' }, { reg: /^\/widget\/kindeditor\/(lang|plugins|themes)\/.*\.(js|css|png|gif)$/i, useHash: false, isMod: false, release: '${statics}/$&', url: '$&' }, { reg: /^\/lib\/(.*)\.(js)$/i, isMod: false, release: '${statics}/$&', url: '/lib/$1' }, { reg: /^\/font\/(.*)$/i, isMod: false, release: '${statics}/$&', url: '/font/$1' }, { reg: /^\/views\/(.*)$/i, useCache: false, release: '/views/$1' }, { //一級同名組件,能夠引用短路徑,好比modules/jquery/juqery.js //直接引用爲var $ = require('jquery'); reg: /^\/modules\/([^\/]+)\/(.*)\.(js)$/i, //是組件化的,會被jswrapper包裝 isMod: true, //id爲文件夾名 id: '$1', release: '${statics}/$&', url: '$0' }, { //組件化的webpart的js reg: /^\/(widget|site)\/(.*)\.(js)$/i, isMod: true, id: '$2', release: '${statics}/$&', url: '$&' }, { //modules目錄下的其餘腳本文件 reg: /^\/modules\/(.*)\.(js)$/i, //是組件化的,會被jswrapper包裝 isMod: true, //id是去掉modules和.js後綴中間的部分 id: '$1', release: '${statics}/$&', url: '/modules/$1' }, { //組件化的webpart的html reg: /^\/widget\/(.*)\.(html)/i, release: false }, { //組件化的webpart的css reg: /^\/(widget|site)\/(.*)\.(css|png|jpg)/i, release: '${statics}/$&', useSprite: true, url: '$&' }, { //其餘css文件 reg: /^(.*)\.(css|less)$/i, release: '${statics}/$&', url: '$&' }, { //前端模板 reg: '**.ejs', //當作類js文件處理,能夠識別__inline, __uri等資源定位標識 isJsLike: true, //只是內嵌,不用發佈 release: false }, { reg: "map.js", release: "${statics}/" }, { reg: /.*\.(html|jsp|tpl|vm|htm|asp|aspx|php)$/, useCache: false, release: '${statics}/$&' }, { reg: "**", release: '${statics}/$&', url: '$&' }] }, settings: { postprocessor: { jswrapper: { type: 'amd' } }, lint: { jshint: { camelcase: true, curly: true, eqeqeq: true, forin: true, immed: true, latedef: true, newcap: true, noarg: true, noempty: true, node: true } } } }); fis.config.merge({ roadmap: { //全部靜態資源文件都使用 http://s1.example.com 或者 http://s2.example.com 做爲域名 domain: 'http://static1.example.com, http://s2.example.com' } }); fis.config.merge({ project: { exclude: /.docx|.bak$|.bat$|.md$|.rar$$|^\/less\/*|.less$|^\/modules\/pizzaui\/pizzaui\/*/i } //排除壓縮包,文檔,和bak文件 });