本文的目的在於使用npm進行js類庫依賴管理,同時精簡html中繁雜的<script>
導入。javascript
目前類庫加載器(如requirejs/seajs等)能夠解決script加載的問題。但對依賴處理很差,還須要開發者一個一個去下載js庫,根據我的喜愛把js堆砌在項目中。css
nodejs中的npm等工具能夠很好的處理依賴,但它是爲nodejs服務的,它的模塊打包格式是CMD,而requirejs是AMD。seajs官方卻是推薦了spm,聽說該項目已經終止維護了。html
在必定程度上,nodejs的bower插件能夠維護AMD類庫的依賴,但和requirejs合併共處,我一直沒搞明白。前端
抽時間梳理了一下npm+gulp+browserify的組合,感受還不錯。npm來管理CMD類庫的依賴,browserify來進行CMD到AMD的轉換,gulp來管理browserify進行自動構建。java
構建前是多個js,構建後會把編寫的代碼js和依賴的類庫打包爲一個js文件。這樣,html中只須要導入一個js文件就能夠了。node
注:這裏沒有類加載器的事。jquery
從一個裸centos開始。linux
[vagrant@bogon ~]$ cat /etc/redhat-release CentOS release 6.7 (Final) [vagrant@bogon ~]$ which node /usr/bin/which: no node in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin)
不要使用yum裝nodejs,epel中的版本過低,而其餘倉庫的拉取速度太慢。web
[vagrant@bogon myweb]$ npm -v 1.3.6 [vagrant@bogon myweb]$ node -v v0.10.46
目前npm已經4.1.1了, 而nodejs版本都已經6.9.2 LTS/7.3.0 latest了。npm
推薦使用淘寶鏡像站的安裝包。
#須要root # sudo -i # yum install -y perl # cd /opt # wget https://npm.taobao.org/mirrors/node/v6.9.2/node-v6.9.2.tar.gz # tar xvfz node-v6.9.2.tar.gz # ln /opt/node-v6.9.2-linux-x64/bin/node /usr/bin/node # cd /opt/node-v6.9.2-linux-x64/lib/node_modules/npm # make && make install
npm install -g cnpm --registry=https://registry.npm.taobao.org
到如今爲止,你徹底能夠用cnpm代替npm,固然若是你的npm速度夠快也能夠不用考慮。
gulp建議安裝到全局,這樣能夠經過命令行gulp
運行。若是安裝到項目,就須要使用路徑訪問,如:node ./node_modules/gulp/bin/gulp.js
$ sudo cnpm install -g gulp $ sudo gulp -v [08:05:11] CLI version 3.9.1 [08:05:11] Local version 3.9.1
我用虛擬機測試,在宿主機器上訪問方便,安裝一下http-server
。
$ sudo cnpm install -g http-server
$ mkdir ~/myweb $ cd ~/myweb $ cnpm init
一路回車,缺省就能夠了。實際開發中輸入本身的項目信息。
jquery很經常使用,就以它爲例。
$ npm install jquery@1.12.4
這時候文件就在項目目錄的node_modules中了。目前目錄結構以下:
$ tree node_modules -L 2 node_modules └── jquery ├── AUTHORS.txt ├── bower.json ├── dist ├── external ├── LICENSE.txt ├── package.json ├── README.md └── src
這時候在node_modules/jquery/dist
已經有jquery.min.js
了。
在項目目錄建立index.html
測試一下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="node_modules/jquery/dist/jquery.min.js" charset="utf-8"></script> </head> <body> <div id="div1"> 123 </div> <button id="edit">修改</button> <script type="text/javascript"> $(function(){ $("#edit").on("click",function(){ $("#div1").text("abc"); }); }); </script> </body> </html>
啓動http-server
:
[vagrant@bogon myweb]$ http-server Starting up http-server, serving ./ Available on: http://127.0.0.1:8080 http://10.0.2.15:8080 http://192.168.33.11:8080
它自動以當前目錄爲webroot啓動一個簡單的web服務。
訪問網址測試正常與否:http://192.168.33.11:8080/index.html
這樣能夠了嗎?這不是本文的目的,若是須要使用多個js類庫,仍是有不少的<script src="balaba.js"/>
。
若是單獨使用browserify,應該安裝在全局。
$ sudo cnpm install -g browserify
構建過程當中,源碼在src中,構建後會保存到dist中,html實際引入的是dist的。考慮代碼保護,咱們可能還要對js等資源混淆,因此不該該把src目錄暴漏在webroot中。
本例項目結構採用maven工程格式,考慮約定俗成的習慣,構建結果保存到$webroot/js中:
[vagrant@bogon myweb]$ tree src src └── main ├── nodejs └── webapp └── js
src/main/webapp/index.html
仍然使用以前的例子,將123
改成abc
,如今把代碼單獨從js/index.js
中引入。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="js/index.js" charset="utf-8"></script> </head> <body> <div class="container" id="div1"> 123 </div> <button id="edit">修改</button> </body> </html>
src/main/nodejs/index.js
注意: 此index.js
非彼index.js
。
var $ = require("jquery"); $(function(){ $("#edit").on("click",function(){ $("#div1").text("abc"); }); });
有疑問了,jquery
在哪裏?管他呢,browserify
知道就好了。
browserify src/main/nodejs/index.js -o src/main/webapp/js/index.js
cd src/main/webapp http-server
注意,項目結構變了,執行http-server
要進入webroot目錄。
每一次編輯js都手動調用browserify不現實,咱們可使用gulp進行自動構建。
var gulp = require("gulp"); var watch = require("gulp-watch"); var browserify = require("browserify"); var sourcemaps = require("gulp-sourcemaps"); var source = require('vinyl-source-stream'); var buffer = require('vinyl-buffer'); gulp.task("browserify", function () { var b = browserify({ entries: "./src/main/nodejs/index.js", debug: true }); return b.bundle() .pipe(source("index.js")) .pipe(buffer()) .pipe(sourcemaps.init({loadMaps: true})) .pipe(sourcemaps.write(".")) .pipe(gulp.dest("./src/main/webapp/js")); }); gulp.task("watch",function(){ gulp.watch("./src/main/nodejs/index.js",["browserify"]); });
cnpm install browserify cnpm install gulp cnpm install gulp-watch cnpm install gulp-sourcemaps cnpm install vinyl-source-stream cnpm install vinyl-buffer cnpm install debug-fabulous cnpm install debug cnpm install css
gulp browserify
gulp會監聽"./src/main/nodejs/index.js"的變化,而後指定"browserify"任務。
$ sudo gulp watch [09:37:00] Using gulpfile /home/vagrant/myweb/gulpfile.js [09:37:00] Starting 'watch'... [09:37:00] Finished 'watch' after 8.91 ms
這時候能夠回到eclipse編輯代碼,一旦修改了"./src/main/nodejs/index.js"就會自動構建,刷新頁面就看到效果了。
[vagrant@bogon myweb]$ sudo gulp watch [09:37:00] Using gulpfile /home/vagrant/myweb/gulpfile.js [09:37:00] Starting 'watch'... [09:37:00] Finished 'watch' after 8.91 ms [09:38:34] Starting 'browserify'... [09:38:35] Finished 'browserify' after 740 ms
gulp監聽到09:38:34
文件被編輯了,即刻構建。
若是構建的js不少,gulp文件會很大。
增長插件:
cnpm install gulp-rename cnpm install event-stream
修改gulpfile.js
var gulp = require('gulp'); var source = require('vinyl-source-stream'); var rename = require('gulp-rename'); var browserify = require('browserify'); var es = require('event-stream'); gulp.task('browserify', function(){ //定義多個入口文件 var entityFiles = [ './src/main/nodejs/index.js', './src/main/nodejs/a.js', ]; //遍歷映射這些入口文件 var tasks = entityFiles.map(function(entity){ return browserify({entries: [entry]}) .bundle() .pipe(source(entry)) .pipe(rename({ extname: '.bundle.js', dirname: '' })) .pipe(gulp.dest('./src/main/webapp/js')); }); //建立一個合併流 return es.merge.apply(null, tasks); }); gulp.task("watch",function(){ gulp.watch("./src/main/nodejs/*.js",["browserify"]); });
文件名會修改成index.bundle.js,能夠寫多個文件。
增長插件:
cnpm install glob
修改gulp
var gulp = require('gulp'); var source = require('vinyl-source-stream'); var rename = require('gulp-rename'); var browserify = require('browserify'); var es = require('event-stream'); var glob = require('glob'); gulp.task('browserify', function(done){ glob('./src/main/nodejs/*.js', function(err, files) { if(err) done(err); var tasks = files.map(function(entry) { return browserify({ entries: [entry] }) .bundle() .pipe(source(entry)) .pipe(rename({ extname: '.bundle.js', dirname: '' })) .pipe(gulp.dest('./src/main/webapp/js')); }); es.merge(tasks).on('end', done); }) }); gulp.task("watch",function(){ gulp.watch("./src/main/nodejs/*.js",["browserify"]); });
完美~
gulp很強大,插件太多,這裏只是冰山一角,之後有時間梳理一下gulp。
寫到這裏發現sudo執行gulp時生成的文件有權限問題,先mark之後再調整吧。