自動提取HTML中的JS進行合併與壓縮
前段時間公司做網站的優化,其中就有將HTML檔案中用到的多個JS壓縮成一個min.js。現在做一個總結:
css js 壓縮用的是 gulp,只要寫一個gulpfile.js指令碼即可,非常方便
css 目前只是將每個源CSS檔案壓縮了一下,沒有進行合併。
JS 做了兩步工作
A. 將每個源JS檔案壓縮
這個簡單,不細說,下面會貼出程式碼。
gulp.task('minifyjs-root',fistGulpTask, function() {
return gulp.src(rootDir+'/*.js').pipe(gulp.dest(rootDir+'js')).pipe(rename ({suffix: ''})).pipe(uglify()).pipe(gulp.dest(rootDir+'js'));
});
B. 將HTML檔案中包含的JS合併為一個JS並且進行壓縮
我當時第一個想法就是先將HTML檔案用到的JS手動找出來放到gulpfile.js中的一個數組中,然後再將它合併成一個min.js。
如HTML檔案中包含myjs1.js, myjs2.js, myjs3.js,要將它們合併壓縮為myjs.min.js.
源HTML檔案(本地開發檔案)
<!-- JS_MERGE_FLAG:this is flag for js files join to one min.js -->
<script type="text/javascript" src="sresource/js/myjs1.js"></script>
<script type="text/javascript" src="sresource/js/myjs2.js"></script>
<script type="text/javascript" src="sresource/js/myjs3.js"></script>
合併壓縮為myjs.min.js(釋出檔案)
<!-- JS_MERGE_FLAG:this is flag for js files join to one min.js -->
<script type="text/javascript" src="sresource/js/myjs.min.js"></script>
可以發現這種做法會導致本地開發環境的HTML檔案與釋出時的不一樣。那就有下列問題
1.釋出時手動來修改HTML檔案嗎?(將引用的JS修改為myjs.min.js)
2.當開發新功能時HTML要增加JS,那我就要修改gulpfile.js中的那個陣列。
3.當有多個HTML檔案要合併壓縮引用到的JS,那就要在gulpfile.js檔案中維護多個數組。
4.當有部署時有使用jenkins打包(不能手動修改HTML檔案)時,我應該怎麼辦。維護兩個HTML,
一個是本地開發環境的HTML,另一個是釋出的?
發現有這些問題的存在將使得工程難以維護,或者說釋出時膽戰心驚。
當時有發現gulp是構建在node.js基礎上的,那麼能不能讓nodejs去查詢html檔案中引用了哪些js,並且將它們提取出來。
最後用它修改HTML檔案(為釋出檔案)。好!有想法,那就試一試唄。下面是我的程式碼。可以實現這個功能。
//gulpfile.js
var gulp = require('gulp'),
minifycss = require('gulp-minify-css'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
rename = require('gulp-rename'),
jshint=require('gulp-jshint');
var glpTask = ['minifycss','minifyjs-root'];
//var glpTask = [];
var fistGulpTask=[];
var fs = require('fs');
var path = require('path');
var rootDir = 'src/main/webapp/sresource/'; //這個目錄下有 js html css 資料夾
var tmpDir = 'src/main/webapp/tmpjs';
var webappDir = 'src/main/webapp/';
var sourceDir = rootDir+'js';
var destDir = sourceDir;
funcCompressJs();
function funcGulp(){
gulp.task('minifycss', fistGulpTask, function() {
return gulp.src([rootDir+'css/*.css',rootDir+'css/*/*.css'])
.pipe(rename({suffix: ''}))
.pipe(minifycss())
.pipe(gulp.dest(rootDir+'css/'));
});
gulp.task('minifyjs-root',fistGulpTask, function() {
return gulp.src(rootDir+'js'+'/*.js').pipe(gulp.dest(rootDir+'js')).pipe(rename({suffix: ''})).pipe(uglify()).pipe(gulp.dest(rootDir+'js'));
});
// 其它壓縮任務
gulp.task('default',[],function() {
gulp.start(fistGulpTask.concat(glpTask));
});
}
function funcCompressJs() {
for (i = 0; i < joinJsHtml.length; i++) {
funcHtmlJoinJsPro(webappDir + joinJsHtml[i]);
}
funcGulp();
}
//js合併
function funcJsMerge(taskName, srcJs, targetJs){
console.log("taskName:"+taskName+", targetJs:"+targetJs);
console.log("source js files:");
for(var i=0; i<srcJs.length; i++){
console.log(" "+srcJs[i]);
}
gulp.task(taskName, function(){
return gulp.src(srcJs) //需要操作的檔案
.pipe(concat(targetJs)) //合併所有js到main.js
.pipe(gulp.dest(rootDir+'js')) //輸出到資料夾
.pipe(rename({suffix: '.min'})) //rename壓縮後的檔名
.pipe(uglify()) //壓縮
.pipe(gulp.dest(rootDir+'js')); //輸出
});
}
//要合併JS的HTML
var jsMergeFg = "JS_MERGE_FLAG"; //<!--JS_MERGE_FLAG-->這個標誌意味著從這裡開始的JS 要合併為一個
var joinJsHtml = ["mb.html"]; //要進行JS合併的HTML檔案
function funcHtmlJoinJsPro(file) {
var readmaxLen = 3072;
var writeBuffer;
var readBuffer = new Buffer(readmaxLen);
var strReadBuf;
var taskName = file.substring(file.lastIndexOf('/')+1);
var targetName = taskName.replace(/\./g,"-");
var targetStr = "";
taskName = "minifyjs-"+targetName;
var fd;
var i=0;
var fileStats = fs.statSync(file);
var offset = fileStats.size-readmaxLen;
//console.log("-1---offset:"+offset);
fd = fs.openSync(file, 'r+');
if(!fd){
console.error("open file "+file+" error!");
throw "open file "+file+" error!";
return;
}
var readCunt = fs.readSync(fd, readBuffer, 0, readBuffer.length, offset);
strReadBuf = readBuffer.toString();
//console.log("strReadBuf:"+strReadBuf);
var startIndex = strReadBuf.indexOf(jsMergeFg);
//console.log("indexOf(jsMergeFg):"+startIndex);
if(startIndex<0){
console.error("file:"+file+" can not find js join flag:"+jsMergeFg);
console.log("read finle content:"+strReadBuf);
console.log("read finle length:"+strReadBuf.length);
throw "file:"+file+" can not find js join flag:"+jsMergeFg;
return ;
}
var lastIndex = strReadBuf.lastIndexOf('</script>')+'</script>'.length;
var endIndex = strReadBuf.lastIndexOf('</html')+'</html>'.length;
//console.log('1-startIndex'+startIndex+'---strReadBuf.length'+strReadBuf.length+'-----strReadBuf--'+strReadBuf);
var joinFgStr = strReadBuf.substring(startIndex);
//console.log("--1--d--joinFgStr:"+joinFgStr);
var tempStrAry = [];
var tempIndex = joinFgStr.indexOf("-->")+'-->'.length;
startIndex += tempIndex;
//console.log("1--1--joinFgStr:"+joinFgStr);
//console.log("----startIndex:"+startIndex+", tempIndex:"+tempIndex);
joinFgStr = joinFgStr.substring(tempIndex);
//console.log("--1----joinFgStr:"+joinFgStr);
var constStr = strReadBuf.substring(0, startIndex);
var constBuf = new Buffer(constStr);
var constLen = constBuf.length;
offset += constLen;
//console.log("1----constStr:"+constStr);
tempStrAry = joinFgStr.split(/\r|\n/g);
//提取要壓縮的JS
var souceJs=[];
var sourceJsStr;
for(i=0; i<tempStrAry.length; i++){
sourceJsStr = tempStrAry[i].match(/\"([^\"]+)\.js/g);
if(sourceJsStr) {
if(sourceJsStr[0].indexOf('"/')==0) {
souceJs.push(sourceJsStr[0].replace(/^\"\//, '')); //1. 去掉 "/
}else if(sourceJsStr[0].indexOf('"')==0){
souceJs.push(sourceJsStr[0].replace(/^\"/, '')); //1. 去掉 "
}
}
}
//console.log("a---souceJs.length:"+souceJs.length+", souceJs:"+souceJs);
funcChangeSourceJs2TempJsDri(file,souceJs);
//console.log("souceJs.length:"+souceJs.length+", souceJs:"+souceJs);
var targetMinJS = targetName+'.min.js';
var targetJoinJS = targetName+'.js';
funcJsMerge(taskName, souceJs, targetJoinJS);
fistGulpTask.push(taskName);
//delFiles.push(targetMinJS);
var strHtml = '<script src="/sresource/js/'+targetMinJS+'" type="text/javascript"></script>';
targetStr = '\n' + strHtml;
targetStr += strReadBuf.substring(lastIndex);
//console.log("html:"+targetStr);
endIndex = targetStr.lastIndexOf('</html')+'</html>'.length;
var newLen = fileStats.size-new Buffer(joinFgStr).length+new Buffer(targetStr.substring(0,endIndex)).length;
writeBuffer = new Buffer(readmaxLen-constLen);
for(i=0; i<writeBuffer.length; i++){
writeBuffer[i]=13;
}
fs.writeSync(fd, writeBuffer, 0, writeBuffer.length, offset);
writeBuffer = new Buffer(targetStr);
fs.writeSync(fd, writeBuffer, 0, writeBuffer.length, offset);
fs.ftruncateSync(fd, newLen);
fs.closeSync(fd);
}
//將要合併的JS定位完全路徑
function funcChangeSourceJs2TempJsDri(htmlFile, sourceJs){
var file = htmlFile;
var relPath;
var i=0;
for(i=0; i<sourceJs.length; i++) {
//源JS定位於sresource
if (sourceJs[i].indexOf('sresource') == 0) {
}else{
//相對路徑形式 ../
relPath = path.resolve(file, sourceJs[i]);
sourceJs[i] = path.relative(rootDir, relPath);
}
}
for(i=0; i<sourceJs.length; i++) {
sourceJs[i] = webappDir+sourceJs[i];
}
}
注意我這裡有幾個重要的點
1. 將要合併壓縮的JS放在HTML檔案的尾部,有利於網頁的載入反應速度。其它JS或者HTML依賴的JS才放在頭部,如jQuery
2. 我在HTML檔案中增加<!-- JS_MERGE_FLAG -->標誌,這個模組下面的JS將會被合併為壓縮為一個.min.js檔案。
3. 我是將html檔案的尾部讀出來的,因為我的HTML檔案比較大。
4. 我的工程目錄是 src/main/webapp/sresource/, 以gulpfile.js所在的目錄為根。程式碼中“sresource”字串是與路徑有關的,我沒有提取出來(本人比較懶)。
程式碼流程
1. 將html檔案的尾部讀出來
2. 查詢標誌 JS_MERGE_FLAG ,從這個標誌開始提取JS
3. JS檔案的路徑處理
4. 增加JS合併壓縮GULP任務
5. 修改HTML檔案
好了,現在只需要釋出前在工程根目錄下,開啟CMD,輸入gulp就OK了,如果配置有jenkins,只要將gulp命令配置到execute shell中即可。
相關推薦
自動提取HTML中的JS進行合併與壓縮
前段時間公司做網站的優化,其中就有將HTML檔案中用到的多個JS壓縮成一個min.js。現在做一個總結: css js 壓縮用的是 gulp,只要寫一個gulpfile.js指令碼即可,非常方便 css 目前只是將每個源CSS檔案壓縮了一下,沒有進行合併。 JS 做了兩
gulp入坑系列(2)——初試JS程式碼合併與壓縮
在上一篇裡成功安裝了gulp到專案中,現在來測試一下gulp的合併與壓縮功能 在之前建立的專案中寫入,在根目錄新建js資料夾,並在資料夾中新建兩個js檔案,程式碼如下: index.js: var
JS程式碼在Html中的位置分佈與呼叫
JS由EcmaScript、Dom、Bom組成 EcmaScript:語法和基本物件、Dom:文件物件模型,描述處理網頁內容的方法和介面 Bom:Browser 出現位置: //JS出現在行間 <input type="button" id="btn" v
HTML 表格中的行合併與列合併
colspan是橫向合併;rowspan是縱向合併。 colspan是“column span(跨列)”的縮寫。colspan屬性用在td標籤中,用來指定單元格橫向跨越的列數: 單元格1 單元格2 單元格3 單元格4 該例通過把colspan設為“3”, 令所在
HTML中JS對於字符串的切割截取實現
空字符串 切割 子串 stop 位置 obj str 發布 dst 在網站編程制作中,對於字符串的切割截取平時所用可能不是特別多,而且分的比較細,所以自備自查。有備無患。由於之前所有均在一個demo測試,下面就來跟大家分享一下成果。 1.函數:split() 功能:
HTML中浮動佈局float與定位佈局position的區分
浮動 float 取值 right/left:元素向右/左浮動。 注意 元素設定為浮動之後,就可以設定寬高(如下圖所示:li元素的寬高) 元素設定為浮動之後,會脫離文件流,在文件中不佔位。(即漂浮在文件流的上方,height為0) 元素浮動之後,後邊的正常
html中元素動態新增與刪除
<div class="unit" > <label>產品引數</label> <input type="button" value="新增" onclick="addProduc
php正則提取html圖片(img)src地址與任意屬性的方法
<?php /*PHP正則提取圖片img標記中的任意屬性*/ $str = '<center><img src="/uploads/images/2017020716154162.jpg" height="120" width="120"
關於GDI+中GraphicsPath進行合併 Union 截切 Exclude 等程式設計的探討 1
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
C#正則表示式提取HTML中IMG標籤的SRC地址
原文:http://blog.csdn.net/smeller/article/details/7108502 一般來說一個 HTML 文件有很多標籤,比如“<html>”、“<body>”、“<table>”等,想把文件中的 img 標籤提取出來並不
logstash中fliter進行JDBC與ruby操作
fliter中JDBC操作有兩個外掛: jdbc_streaming:這個是流式執行的,每來一條資料就會執行一次JDBC操作,具體介紹見官網https://www.elastic.co/guide/en/logstash/current/plugins-filters-jdbc_streamin
kindeditor自動過濾html中樣式
當用kindeditor的【html程式碼】新增功能的時候。會出現裡面自帶的樣式被過濾掉;一直不知道什麼原因。到網上查詢資料之後才發現原來:kindeditor預設開啟【filterMode】而這個屬性就是他過濾一些程式碼的引數;我們把他設定為false:更改kindedi
PHP:使用php,迴圈html中的select標籤與Php資料
select標籤,我們都知道是下拉列表,這裡,我們使用foreach迴圈,將select中的資料進行輸出 例子: 1、資料表:mimi_article,表中有個欄位,為1或0,表示著是或否 2、通過php迴圈,將它輸出,並獲取資料庫中,當前記錄中readi
HTML中,相對定位與絕對定位,以及z-index
之前一直搞不明白html中positon:relative; 和 position:absolute;這兩個屬性。這裡記錄一下。理論解釋:相對定位:該元素相對於自己原有位置,偏移一定距離。相對的是自己。絕對定位:該元素相對於其父元素,偏移一定距離。相對的是父元素,重點是這個父
【shell】分別提取檔名中的基本名與副檔名
檔名是有【基本名】與【副檔名】兩部分構成 1.藉助【%】操作符從檔名中提取基本名部分 Linux:/qinys # file_name='get_name.tar.gz'Linux:/qinys # name=${file_name%.*}Linux:/qinys # echo "Th
win7下,Ant 配合yuicompressor對js和css進行合併、壓縮、拷貝處理
更新:2015/8/13 【NAnt】 NAnt is a .NET-based build tool. In theory it is kind of like make without make's wrinkles. In practice it's a lot
提取HTML中所有a標籤的href連結
/** * 提取html中a標籤的href * @param strs * @return */ public List<String> getAHref(String s
正則表示式提取HTML中IMG標籤的SRC地址
一般來說一個 HTML 文件有很多標籤,比如“<html>”、“<body>”、“<table>”等,想把文件中的 img 標籤提取出來並不是一件容易的事。由於 img 標籤樣式變化多端,使提取的時候用程式尋找並不容易。於是想要尋找它們就
php正則提取html圖片(img)src地址與任意屬性
簡單版:<?php header("Content-Type: text/html;charset=utf-8"); $str = '<div class="ui-block-a" align="center"> <a href="
vue根目錄下的index.html中的id="app"與src目錄下的App.vue中的id="app"為什麼不會衝突
具體描述 在vue的專案開發中,我們通過vue-cli生成的專案結構中預設有index.html的檔案作為預設的渲染主頁檔案它的外層div有id=”app”,而在專案的src目錄中主元件App.vu