序
我們都知道,瀏覽器上是可以看到前端的html和js程式碼的,所以如果遇到隱私心比較強的老闆,你就冷不丁的會接受到一個程式碼加密的需求,當接受到這個需求的時候你怎麼完成?那我希望我的這篇部落格可以幫助到你。
首先,告訴你的老闆,嚴格意義上的加密是不存在的,能夠實現的只有對前端程式碼進行壓縮混淆,增加閱讀難度。
本篇教程全篇描述的,就是對程式碼進行混淆的手段,從而滿足老闆提出的加密需求。
為了保證本篇教程真實可用,我將使用一臺新的Windows系統,從無到有進行演示,同時將操作流程記錄在這裡,供你參考,也希望能夠幫你跳過一些坑,如果你遇到什麼問題,請留言討論。
安裝NodeJs
如果你沒安裝過node,請跟著教程走,如果你安裝過,請直接跳到下一節。
下載地址:http://nodejs.cn/download/
直接下載安裝,安裝的過程是傻瓜式的下一步,唯一可以改變的是安裝位置。
安裝完成後開啟cmd命令列,檢視版本號是為了確認是否安裝成功。
安裝外掛
切換到專案根目錄:
安裝gulp外掛包:npm install --save-dev gulp
效果如圖:
別急,還有很多包,命令一條一條刷起來:
npm install --save-dev del
npm install --save-dev gulp-concat
npm install --save-dev gulp-header
npm install --save-dev gulp-if
npm install --save-dev gulp-minify-css
npm install --save-dev gulp-htmlmin
npm install --save-dev gulp-rename
npm install --save-dev gulp-replace
npm install --save-dev gulp-uglify
npm install --save-dev gulp-babel
npm install --save-dev babel-preset-es2015
npm install --save-dev @babel/core
npm install --save-dev @babel/preset-env
注意事項
外掛安裝完成後,我們的前期工作就做完了。
我們會發現專案目錄中多個一個node_modules目錄和package-lock.json檔案,json檔案中是我們的外掛列表,node_modules目錄中是我們安裝的外掛包。
index.html是我的主入口檔案,src目錄就是我的專案中存放程式碼的目錄,也就是我要壓縮加密構建的目錄。
src裡有三個子目錄,controller存放獨立的js處理前端業務邏輯,style存放css樣式檔案,view存放html頁面。
在編寫指令碼之前,我需要直白的告訴你,如果你的JS裡有ES6語法,正常打包是打不了的,不過我們的前期工作已經把處理這個問題的工具包也一起安裝了,但是也僅限於處理單獨的JS檔案。
如果你是HTML程式碼裡嵌JS,並且JS裡有ES6語法,那麼需要把JS程式碼拎出來做成單獨的JS,或者手動將ES6寫法改成ES5。
總之,如果你打包報錯,很大可能是ES6語法導致,其次是檔案路徑錯誤。
壓縮JS
回到我們的專案根目錄,建立一個gulpfile.js檔案,這個是固定的檔名:
引入包:
var gulp = require('gulp'); var uglify = require('gulp-uglify'); var babel = require('gulp-babel'); var minifyCss = require("gulp-minify-css"); var htmlmin = require('gulp-htmlmin'); var header = require('gulp-header'); var del = require('del');
定義一個目標目錄:
var destDir = './dist';
定義一個註釋,因為我希望在壓縮後的程式碼中第一行新增一點註釋:
var note = ['/** 小樣,看原始碼?想得美! */\n <%= js %>', {js: ';'}];
監聽任務:
gulp.task('minjs', function () { //定義路徑 var src = [ './src/**/*.js' ]; gulp.src(src) .pipe(babel({presets: ["@babel/env"], plugins: []}))//es6轉es5 .pipe(uglify())//壓縮 .pipe(header.apply(null, note))//新增頭部註釋 .pipe(gulp.dest(destDir));//將壓縮後的內容輸出到目標目錄 });
minjs就是我們自定義的任務名,也就是說 我們在命令列輸入gulp minjs 這行命令,這段程式碼就會執行。
如果只輸入gulp命令,它會自動去找名為default的任務。
var src = ['./src/**/*.js']; 就是我們想要抓取的檔案,使用了萬用字元,你幾乎一定會有需求像下面這樣寫:
var src = [ './src/**/*.js' , '!./src/config.js' , '!./src/lib/extend/*.js' ];
感嘆號的意思是排除。
這裡說明一下destDir只會代替萬用字元之前的目錄路徑,比如說我這裡的destDir定義的是./dist,那麼 ./src/controller/admin.js 壓縮後的路徑就是 ./dist/controller/admin.js。
好了,開啟命令列,輸入命令:gulp minjs
檢視專案,js檔案已經壓縮成功了。
壓縮CSS
任務的監聽和壓縮JS是沒有差別的,只不過壓縮任務用gulp-minify-css外掛來完成。
gulp.task('mincss', function () { var src = [ './src/style/*.css' ]; gulp.src(src).pipe(minifyCss()).pipe(gulp.dest(destDir + '/style')); });
輸入命令:gulp mincss
檢視專案也沒有任何問題:
非常智慧的它會把css中的註釋給你刪掉。
壓縮HTML
壓縮HTML可以傳入很多引數指定相應的行為:
gulp.task('minhtml', function () { var options = { removeComments: true,//清除HTML註釋 collapseWhitespace: true,//摺疊空白 minifyJS: true,//壓縮頁面JS minifyCSS: true//壓縮頁面CSS }; var src = [ './src/views/**/*', ]; gulp.src(src) .pipe(htmlmin(options)) .pipe(gulp.dest(destDir + '/views')); });
更多引數請移步這裡來看:https://github.com/kangax/html-minifier/blob/gh-pages/README.md
輸入命令:gulp minhtml
壓縮後的HTML:
全部壓成一行,檔案中的css和js也一併壓縮了。
一條龍處理
但是我們總不可能是打個包要跑多條命令吧,那多麻煩,現在我們就整合整合,讓這些任務合併成一個任務。
我們建立一個task物件,把各個任務的內容放進去,並且加一個清理dist目錄的方法,和一個move方法負責將沒有被壓縮的檔案複製過去。
//任務列表 var task = { //清理dist目錄 clear:function () { del(['./dist/*']); }, minjs:function () { //定義路徑 var src = [ './src/**/*.js' ]; gulp.src(src) .pipe(babel({presets: ["@babel/env"], plugins: []}))//es6轉es5 .pipe(uglify())//壓縮 .pipe(header.apply(null, note))//新增頭部註釋 .pipe(gulp.dest(destDir)); }, mincss:function () { var src = [ './src/style/*.css' ]; gulp.src(src).pipe(minifyCss()).pipe(gulp.dest(destDir + '/style')); }, minhtml:function () { var options = { removeComments: true,//清除HTML註釋 collapseWhitespace: true,//摺疊空白 minifyJS: true,//壓縮頁面JS 如果你確信你的HTML頁面中的js不包含有es6語法,那麼可以壓縮js 否則還是得把js抽離成單獨的檔案進行壓縮 minifyCSS: true//壓縮頁面CSS }; var src = [ './src/**/*', ]; gulp.src(src) .pipe(htmlmin(options)) .pipe(gulp.dest(destDir)); }, move: function () { //複製資料夾 沒有被壓縮的檔案就在這裡複製 gulp.src('./src/**/*.png').pipe(gulp.dest(destDir)); } };
我們在壓縮js的時候說了,如果只是gulp命令,它會去找名為default的任務,我們就在default任務裡遍歷task物件,將其中的方法輪流執行一遍。
gulp.task('default', function () { for (var key in task) { task[key](); } });
這樣,我們只需要一個gulp命令,也就走完了整個構建流程。
同時,我們將單個的任務指向task中對應的方法:
gulp.task('clear',task.clear); gulp.task('minjs',task.minjs); gulp.task('mincss',task.mincss); gulp.task('minhtml',task.minhtml); gulp.task('move',task.move);
無論是單獨處理一個環節,還是整個構建流程,我們都可以很方便的完成。
最後,感謝閱讀。 PS:歡迎關注,有粉必回。