使用npm+gulp+browserify網頁前端開發

本文的目的在於使用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)

安裝nodejs

不要使用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

使用淘寶cnpm加速npm

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

一路回車,缺省就能夠了。實際開發中輸入本身的項目信息。

安裝js依賴

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

若是單獨使用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轉換

browserify src/main/nodejs/index.js -o src/main/webapp/js/index.js

測試

cd src/main/webapp
http-server

注意,項目結構變了,執行http-server要進入webroot目錄。

gulp自動構建

每一次編輯js都手動調用browserify不現實,咱們可使用gulp進行自動構建。

建立gulpfile.js

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"]);
});

安裝gulp的插件

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任務

gulp browserify

啓動gulp監聽進程

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文件被編輯了,即刻構建。

gulp綁定多個文件

若是構建的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"]);
});

完美~

Final

gulp很強大,插件太多,這裏只是冰山一角,之後有時間梳理一下gulp。

寫到這裏發現sudo執行gulp時生成的文件有權限問題,先mark之後再調整吧。

相關文章
相關標籤/搜索