Web前端持續整合方案(二)
Grunt是一款基於node的javascript工作管理員工具。我們的專案使用Grunt實現專案自動化打包,以及後續的持續整合。Grunt如何使用,本文不詳細介紹(其實是不會-_-!),詳見《【grunt整合版】30分鐘學會使用grunt打包前端程式碼》。
1、打包思路
專案從開發態到釋出態,需要做哪些事情?一、程式碼檢查,包括程式碼風格檢查、js靜態程式碼檢查、單元測試、程式碼靜態分析。二、檔案預處理:包括sass轉css、seajs模組轉換、檔案變數巨集替換。三、檔案拷貝、壓縮、合併。所以處理流程也很簡單。如下圖所示:
2、程式碼風格檢查
jscs: { src: ['script/module/**/*.js', '!script/module/**/tpl/*.js'], options: { config: '.jscsrc', reporter: 'node_modules/jscs-html-reporter/jscs-html-reporter.js', reporterOutput: 'report/jscs/index.html' } },
其中,.jscsrc是程式碼風格規則檔案。參考配置如下:
{ "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, "disallowSpacesInFunctionExpression": { "beforeOpeningRoundBrace": true }, "disallowSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true }, "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, "disallowEmptyBlocks": true, "disallowSpacesInsideArrayBrackets": true, "disallowSpacesInsideParentheses": true, "disallowQuotedKeysInObjects": true, "disallowSpaceAfterObjectKeys": true, "disallowSpaceAfterPrefixUnaryOperators": true, "disallowSpaceBeforePostfixUnaryOperators": true, "disallowSpaceBeforeBinaryOperators": [ "," ], "disallowMixedSpacesAndTabs": true, "disallowTrailingWhitespace": true, "disallowTrailingComma": true, "disallowYodaConditions": true, "disallowKeywords": [ "with" ], "disallowMultipleLineBreaks": true, "requireSpaceBeforeBlockStatements": true, "requireParenthesesAroundIIFE": true, "requireSpacesInConditionalExpression": true, "requireMultipleVarDecl": "onevar", "requireBlocksOnNewline": 1, "requireCommaBeforeLineBreak": true, "requireSpaceBeforeBinaryOperators": true, "requireSpaceAfterBinaryOperators": true, "requireCamelCaseOrUpperCaseIdentifiers": true, "requireLineFeedAtFileEnd": true, "requireCapitalizedConstructors": true, "requireDotNotation": true, "requireCurlyBraces": [ "do" ], "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "case", "return", "try", "catch", "typeof" ], "safeContextKeyword": "_this", "validateLineBreaks": "LF", "validateQuoteMarks": "'", "validateIndentation": 2 }
生成報表如下圖所示:
3、js程式碼靜態檢查
其中,.jshintrc是靜態檢查規則檔案。參考配置如下:
{ "asi" : true, "browser" : true, "eqeqeq" : false, "eqnull" : true, "es3" : true, "expr" : true, "jquery" : true, "qunit" : true, "latedef" : "nofunc", "nonbsp" : true, "strict" : false, "undef" : true, "unused" : "vars", "sub" : true, "multistr" : true, "loopfunc" : true }
生成報表如下圖所示:
4、單元測試
我們的專案中,單元測試採用qunit。所以需要下載grunt的qunit外掛:jquery/qunit。另外,為了能夠在jenkins中顯示單元測試報告,還需要qunit轉junit外掛:sbrandwoo/grunt-qunit-junit。引數配置如下:
// 單元測試
qunit: {
script: ['test/**/*.html']
},
qunit_junit: {
options: {
dest: 'report/qunit',
classNamer: function (moduleName, url) {
var cn = url.replace(/\.html(.*)$/, '').replace(/[\\|\/]/g, '.');
var index = cn.lastIndexOf('.');
cn = cn.substr(index+1);
return cn;
},
testNamer: function (testName, moduleName, url) {
var tn = url.replace(/\.html(.*)$/, '').replace(/[\\|\/]/g, '.');
var index = tn.lastIndexOf('.');
tn = tn.substring(0, index);
// return moduleName.replace(/[\\|\/]/g, '.').replace(/\s+/g, '_');
return tn;
}
}
},
生成的報表如下圖所示:
點選失敗用例,可以檢視詳情:
單元測試完成後,還要生成覆蓋率報告,這一部分內容坑比較多,另寫一篇文章詳細介紹。
5、js程式碼靜態分析。
js程式碼靜態分析需下載外掛:es-analysis/plato。引數配件比較簡單,如下圖所示:
plato: {
your_task: {
files: {
'report/plato': ['script/**/*.js', '!script/**/tpl/*.js']
}
}
}
生成報表如下圖所示:
Plato中通過一系列指標來衡量一個專案的程式碼質量情況。下面詳細介紹一下各指標的意義。
5.1、Total Lines
總程式碼行,表示檔案中的程式碼總行數。
5.2、Avarage Lines
平均程式碼行=總程式碼行/檔案數。
5.3、Maintainability
Maintainability Index = MAX(0,(171 - 5.2 * log(Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * log(Lines of Code))*100 /171)。
可維護性指標是0-100之間的數字,越高越容易維護。其中:
20-100:易於維護
10-19:較難維護
0-9:很難維護
提高可維護性的方法有:
降低圈複雜度
降低單檔案程式碼行數
5.4、Average Maintainability
平均可維護性=每個檔案的可維護性指數求平均。
5.5、Halstead complexity measures
Halstead複雜度測量演算法,如下圖所示:
5.6、Estimated errors in implementation
潛在bug數估計,演算法如下圖所示:
降低潛在bug數的方法:
降低程式碼量。
5.7、Lint errors
jsLint錯誤數。
5.8、Difficulty
檔案中去重運算元越多,越難;重複操作符越多,越難。
5.9、Complexity
圈複雜度,表示程式碼塊中所有可能的路徑數。圈複雜度越低越好。
降低圈複雜度的方法:
減少分支數。
5.10、Function weight
函式權重。有如下幾種分類方式:
By Complexity:按圈複雜度統計。
BySLOC:按照SLOC/LSLOC(原始碼行/邏輯程式碼行)統計。
SLOC:物理程式碼行,統計物理行數,包括註釋、空行等。
LSLOC:邏輯程式碼行,統計語句數。
6、css、js轉換
因為專案中有用到sass和seajs。所以,打包的時候需要把sass檔案轉為css檔案,用到gruntjs/grunt-contrib-sass外掛,具體配置如下:
sass: {
dist: {
options: {
style: "compressed",
sourcemap: 'none'
},
files: [{
expand: true,
cwd: 'theme/default/scss',
src: ['**/*.scss'],
dest: 'dist/theme/default/css',
ext: '.css'
}, {
expand: true,
cwd: 'theme/affairs/scss',
src: ['**/*.scss'],
dest: 'dist/theme/affairs/css',
ext: '.css'
}]
}
}
CMD規範規定一個檔案內只能定義一個模組。因此多個模組檔案不能合併為一個檔案。為了解決這個問題,需要引入spmjs/grunt-cmd-transport外掛。該外掛可以為seajs模組分配id和提取依賴項,這樣就能夠支援多模組檔案合併。相應配置如下:
// 轉化
transport: {
options: {
debug: false,
idleading: 'dist/',
alias: {
'$': '$',
'helper': 'helper',
'cache': 'cache',
'fun': 'fun',
'kissy': 'kissy'
}
},
script: {
options: {
idleading: 'script/module/'
},
files: [{
expand: true,
cwd: 'script/module/',
src: ['**/*.js', '!**/index.js', '!**/tpl/*.dev.js'],
dest: '.build/script/module'
}]
}
}
7、檔案刪除、合併、拷貝、壓縮。