瞭解Browserify

Browserify是一個Javascript的庫,能夠用來把多個Module打包到一個文件中,而且能很好地應對Modules之間的依賴關係。而Module是封裝了屬性和功能的單元,是一個Javascript對象,Modules之間能夠相互依賴。某種程度上來講,Browserify模仿了Node.js加載Module的方式。一個js文件包含一個Module。因此,Browserify經過讀取文件來加載該文件內的Module。css

【module的寫法】html

'use strict';
exports.save = function(tasks){};
exports.load = function(){};
exports.clear = function(){};

還能夠這麼寫:jquery

'use strict';
module.exports = {
    save: function(tasks){},
    load: function(){},
    clear: function(){}
};

【module的緩存】web

一、單例模式緩存npm

module ajson

exports.value = "original";

module bgulp

var a = require('./a');
a.value = "changed";
console.log(a.value);//changed

module c數組

var a = require('./a');
console.log(a.value);//original

module c中的a.value值之因此是original,是由於module c對module a有依賴,並且依賴的是緩存。因此,在默認狀況下,module是有緩存的,也能夠理解成單例模式。瀏覽器

二、實例模式緩存緩存

還能夠經過構造函數來建立一個module。

module a

module.exports = function(){
  this.value = "original value";  
};

module b

var A = require('./a');
var a = new A();
a.value = "changed";
console.log(a.value);//changed

module c

var A = require('./a');
var a = new A();
console.log(a.value);//original

【準備工做】

  • 安裝Node.js
  • 安裝Browserify:npm install -g browserify

【明確目標】

  • app這個module包含了和視圖交互的邏輯,是整個程序的entry point
  • app這個module依賴tasks這個module,tasks這個module用來管理task list
  • taskRender這個module用來渲染頁面,taskData這個module用來保存加載有關task list的數據

【文件結構】

.....css/
..........tasks.css
.....js/
..........data/
...............taskData.js
..........renderers/
...............taskRenderer.js
..........tasks.js
..........app.js
.....index.html

【代碼實現】

文件結構有了,module的寫法也搞清楚了,接下來就實現一遍。

① taskData.js 是用來處理數據的一個module

'use strict';

var STORE_NAME = "tasks";

exports.save = function(tasks){
    localStorage.setItem(STORE_NAME, JSON.stringify(tasks));
};

exports.load = function(){
    var storedTasks = localStorage.getItem(STORE_NAME);
    if(storedTasks){
        return JSON.parse(storedTasks);
    }
    return [];
};

exports.clear = function(){
    localStorage.removeItem(STORE_NAME);
};

② taskRenderer.js 是用來處理頁面相關的一個module

'use strict';

var $ = require('jquery');
var taskTemplate = '<li class="task"><input class="complete" type="checkbox" /><input class="description" type="text" /></li>';

//返回一段帶值的html
//task是傳入的一個object對象
function _renderTask(task){
    var $task = $(taskTemplate);
    if(task.complete){
        $task.find(".complete").attr("checked", "checked");
    }
    $task.find(".description").val(task.description);
    return $task;
}

exports.renderTasks = function(tasks){
    
    //遍歷任務得到帶值html的數組
    var elementArray = $.map(tasks, _renderTask);
    
    $("#task-list")
        .empty()
        .append(elementArray);
};

exports.renderNew = function(){
    var $taskList = $("#task-list");
    $taskList.prepend(_renderTask({}));
}

③ tasks.js 用到了以上2個module

'use strict';

var $ = require('jquery');
var taskData = require('./data/taskData');
var taskRenderer = require('./renderers/taskRenderer');

exports.add = function () {
    taskRenderer.renderNew();
};

exports.remove = function (clickEvent) {
    var taskElement = clickEvent.target;
    $(taskElement).closest(".task").remove();
};

exports.clear = function(){
    taskData.clear();
    exports.render();
};

exports.save = function(){
    var tasks=[];
    $("#task-list .task").each(function(index, task){
        var $task = $(task);
        tasks.push({
            complete: $task.find(".complete").prop('checked'),
            description: $task.find(".description").val()
        });
    });
    taskData.save(tasks);
};

exports.cancel = function(){
  exports.render();  
};

exports.render = function(){
  taskRenderer.renderTasks(taskData.load()); 
};

④ app.js 只須要和tasks.js打交道就能夠

'use strict';

var $ = require('jquery');
var tasks =require('./tasks');

function _addTask(){
    tasks.add();
}

function _deleteAllTasks(){
    tasks.clear();
}

function _saveChanges(){
    tasks.save();
}

function _cancelChanges(){
    tasks.cancel();
}

function _deleteTask(clientEvent){
    tasks.remove(clientEvent);
}


function _registerEventHandlers(){
    $('#new-task-button').on("click", _addTask);
    $('#delete-all-button').on("click", _deleteAllTasks);
    $('#save-button').on("click",_saveChanges);
    $('#cancel-button').on("click", _cancelChanges);
    $('#task-list').on("click", ".delete-button", _deleteTask);
}

_registerEventHandlers();
tasks.render();

⑤ 使用browserify把全部module捆綁到一個js文件中去:

browserify src\js\app.js -o src\js\app.bundle.js

⑥ index.html 只須要引用src\js\app.bundle.js就能夠

<!DOCTYPE html>
<html>
    <head>
        <title>Task List</title>
        <link rel="stylesheet" href="css/tasks.css">
    </head>
    <body>
        <header>
            <h1>TaskList</h1>
        </header>
        
        <div class="toolbar">
            <button id="new-task-button">New Task</button>
            <button id="delete-all-button">Delete All</button>
        </div>
        
        <div id="content">
            <ul id="task-list">
                
            </ul>
            
            <ul id="log-list">
                
            </ul>
        </div>
        
        <div class="toolbar">
            <button id="save-button">Save</button>
            <button id="cancel-button">Cancel</button>
        </div>
        
        <script src="js/app.bundle.js"></script>
    </body>
</html>

【若是有不少文件,調試時出錯】

當有不少文件的時候,調試出錯,使用Source Map能夠方便找到出錯的文件和出錯的地方。

如今,有了app.bundle.js文件,以及有了app.js, tasks.js, taskRenderer.js, taskData.js文件們,咱們能夠在app.bundle.js和其它js文件中建立一個Souce Map.

browserify src\js\app.js -o src\js\app.bundle.js --debug

這樣,會在app.bundle.js文件最後面追加上相似//# sourceMappingURL=data:application/json;,這樣在調試的時候會很容易找到出錯的文件和出錯的位置。

【修改文件】

若是此時修改某個js文件呢?咱們還須要使用browserify把全部的module依賴關係捆綁到一個文件中,執行以下的命令:

browserify src\js\app.js -o src\js\app.bundle.js

解決思路:Watchify爲此而生,當發現有文件變化,自動運行Browserify。

全局安裝Watchify:npm install -g watchify

在命令行窗口運行Watchify命令:watchify src\js\app.js -o src\js\app.bundle.js --debug -v

此時保持命令窗口打開着。

修改某個文件,並保存,發現命令窗口會自動運行:watchify src\js\app.js -o src\js\app.bundle.js --debug -v

【Grunt Browserify】

Grunt是Javascript Task Runner,也是運行在Node.js之上。

如何安裝Grunt?

  1. npm install -g grunt-cli
  2. npm install grunt --save-dev

檢測版本?

grunt --version

在哪一個文件中配置?

通常在根目錄下的Gruntfile.js

Grunt與Browserify的結合?

npm install grunt-browserify --save-dev

在根目錄下的Gruntfile.js文件:

module.exports=function(grunt){
    
    //配置
    grunt.initConfig({
        browserify: {
            app: {
                src: 'templates/src/js/app.js',
                dest: 'templates/src/js/app.bundle.js',
                options: {
                    browserifyOptions:{
                        debug: true
                    }
                }
            }
        }
    });
    
    //加載其它module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    
    //定義task
    grunt.registerTask('default',['browserify']);
}

【Grunt Watch】

使用了Grunt以及用Gruntfile.js進行配置以後,每次有文件變化,咱們須要在命令行窗口輸入gulp命令。能不能自動爲咱們運行gulp命令呢?

Grunt Watch出場。

如何安裝Grunt Watch?

npm install grunt-contrib-watch --save-dev

修改Gruntfile.js文件

module.exports=function(grunt){
    
    //配置
    grunt.initConfig({
        browserify: {
            app: {
                src: 'templates/src/js/app.js',
                dest: 'templates/src/js/app.bundle.js',
                options: {
                    browserifyOptions:{
                        debug: true
                    }
                }
            }
        },
        watch: {
            app: {
                files: ['templates/src/js/*/*.js'],
                tasks: ['browserify']
            }
        }
    });
    
    //加載其它module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    
    //定義task
    grunt.registerTask('default',['browserify']);
}

在命令行窗口輸入:grunt watch

如今,修改templates/src/js中的任何js文件,會自動運行browserify命令。

【Grunt Connect】

Grunt Connect可讓咱們搭建一個web server。

如何安裝?

npm install grunt-contrib-connect --save-dev

修改Gruntfile.js文件

module.exports=function(grunt){
    
    //配置
    grunt.initConfig({
        browserify: {
            app: {
                src: 'templates/src/js/app.js',
                dest: 'templates/src/js/app.bundle.js',
                options: {
                    browserifyOptions:{
                        debug: true
                    }
                }
            }
        },
        watch: {
            app: {
                files: ['templates/src/js/*/*.js'],
                tasks: ['browserify']
            }
        },
        connect: {
            app: {
                options: {
                    port: 9001,
                    base: 'templates/src'
                }
            }
        }
    });
    
    //加載其它module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');
    
    //定義task
    grunt.registerTask('default',['browserify']);
    grunt.registerTask('serve',['browserify:app', 'connect:app', 'watch:app']);
}

在命令行窗口輸入:grunt serve

在瀏覽器窗口輸入:localhost:9001

【Connect Live Reload】

如今,能夠在瀏覽器中輸入localhost:9001瀏覽到網頁內容,此時,若是某個文件有變化,咱們須要從新刷新瀏覽器。web server能夠有自動刷新的功能嗎?

Connect Live Reload就是解決這個問題的。

如何安裝?

npm install connect-livereload --save-dev

修改Gruntfile.js文件

module.exports=function(grunt){

//配置
    grunt.initConfig({
        browserify: {
            app: {
                src: 'templates/src/js/app.js',
                dest: 'templates/src/js/app.bundle.js',
                options: {
                    browserifyOptions:{
                        debug: true
                    }
                }
            }
        },
        watch: {
            app: {
                files: ['templates/src/js/*/*.js'],
                tasks: ['browserify'],
                options: { //爲保持web server 的自動刷新而設置
                    livereload: true
                }
            }
        },
        connect: {
            app: {
                options: {
                    port: 9001,
                    base: 'templates/src',
                    middleware: function(connect, options, middlewares){//爲保持web server 的自動刷新而設置
                        middlewares.unshift(require('connect-livereload')());
                        return middlewares;
                    }
                }
            }
        }
    });
    
    //加載其它module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');
    
    //定義task
    grunt.registerTask('default',['browserify']);
    grunt.registerTask('serve',['browserify:app', 'connect:app', 'watch:app']);
}

在命令行窗口輸入:grunt serve

在瀏覽器中打開:http://localhost:9001/

修改某個文件,瀏覽器中自動有變化。

相關文章
相關標籤/搜索