了解Browserify

Browserify是一个Javascript的库,可以用来把多个Module打包到一个文件中,并且能很好地应对Modules之间的依赖关系。而Module是封装了属性和功能的单元,是一个Javascript对象,Modules之间可以相互依赖。某种程度上来说,Browserify模仿了Node.js加载Module的方式。一个js文件包含一个Module。所以,Browserify通过读取文件来加载该文件内的Module。

【module的写法】

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

还可以这么写:

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

【module的缓存】

1、单例模式缓存

module a

exports.value = "original";

module b

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是有缓存的,也可以理解成单例模式。

2、实例模式缓存

还可以通过构造函数来创建一个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

【明确目标】

了解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 = '';

//返回一段带值的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 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){

    //&#x914D;&#x7F6E;
    grunt.initConfig({
        browserify: {
            app: {
                src: 'templates/src/js/app.js',
                dest: 'templates/src/js/app.bundle.js',
                options: {
                    browserifyOptions:{
                        debug: true
                    }
                }
            }
        }
    });

    //&#x52A0;&#x8F7D;&#x5176;&#x5B83;module/plugins
    grunt.loadNpmTasks('grunt-browserify');

    //&#x5B9A;&#x4E49;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){

    //&#x914D;&#x7F6E;
    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']
            }
        }
    });

    //&#x52A0;&#x8F7D;&#x5176;&#x5B83;module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    //&#x5B9A;&#x4E49;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){

    //&#x914D;&#x7F6E;
    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'
                }
            }
        }
    });

    //&#x52A0;&#x8F7D;&#x5176;&#x5B83;module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');

    //&#x5B9A;&#x4E49;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){

    //&#x914D;&#x7F6E;
    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: { //&#x4E3A;&#x4FDD;&#x6301;web server &#x7684;&#x81EA;&#x52A8;&#x5237;&#x65B0;&#x800C;&#x8BBE;&#x7F6E;
                    livereload: true
                }
            }
        },
        connect: {
            app: {
                options: {
                    port: 9001,
                    base: 'templates/src',
                    middleware: function(connect, options, middlewares){//&#x4E3A;&#x4FDD;&#x6301;web server &#x7684;&#x81EA;&#x52A8;&#x5237;&#x65B0;&#x800C;&#x8BBE;&#x7F6E;
                        middlewares.unshift(require('connect-livereload')());
                        return middlewares;
                    }
                }
            }
        }
    });

    //&#x52A0;&#x8F7D;&#x5176;&#x5B83;module/plugins
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-connect');

    //&#x5B9A;&#x4E49;task
    grunt.registerTask('default',['browserify']);
    grunt.registerTask('serve',['browserify:app', 'connect:app', 'watch:app']);
}

在命令行窗口输入:grunt serve

在浏览器中打开:http://localhost:9001/

修改某个文件,浏览器中自动有变化。

Original: https://www.cnblogs.com/darrenji/p/5492028.html
Author: Darren Ji
Title: 了解Browserify

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/551545/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 梯度下降(Gradient Descent)小结

    from https://www.cnblogs.com/pinard/p/5970503.html 在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient …

    技术杂谈 2023年5月31日
    094
  • Gson的TypeToken与泛型擦除

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 问题 在Java的json框架中,Gson是使用得比较广泛的一个,其 Gson类提供了 toJson…

    技术杂谈 2023年7月24日
    0121
  • 单点登录(SSO)

    1 基础知识 单点登录机制(SSO)允许用户登录应用程序一次,并访问所有相关的系统,而不需要单独登录它们。 由于 SSO,用户只需登录一次即可使用服务,并自动登录到所有相关应用程序…

    技术杂谈 2023年7月23日
    0103
  • vue部署在nginx后刷新404,nginx.conf一行代码解决掉

    直接 vim conf/nginx.conf文件 server {listen 8081;server_name localhost; charset koi8-r; access…

    技术杂谈 2023年6月21日
    0102
  • JSON数据和Java对象的相互转换

    JSON数据和Java对象的相互转换 JSON解析器 创建的解析器:Jsonlib,Gson,Fastjson,jackson JSON转为Java对象 使用步骤: 导入jacks…

    技术杂谈 2023年6月21日
    0110
  • 【leetcode】151. 颠倒字符串中的单词

    给你一个字符串 s ,颠倒字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空…

    技术杂谈 2023年7月24日
    068
  • SpringBoot异步调用

    在程序执行时候还有一个瓶颈,串行执行,可以通过使用不同线程类快速提升应用的速度。 要启用Spring的异步功能,必须要使用 @EnableAsync注解。这样将会透明地使用 jav…

    技术杂谈 2023年7月24日
    084
  • 亿级消息中心架构方案概述【原创】

    目标 技术目标: 上行到消息队列api吞吐量10000条/秒,下发第三方平台1000条/秒(仅平台自身处理能力,第三方看第三方处理能力极限指标为准);保证消息中心100%高可用。 …

    技术杂谈 2023年7月23日
    071
  • Maskrom模式

    启动模式 ROC-RK3308-CC 有四种启动模式: Loader 模式 MaskRom 模式 Recovery 模式 Normal 模式 Loader 模式下,可以进行固件的烧…

    技术杂谈 2023年5月30日
    0105
  • [Python]-pandas模块-机器学习Python入门《Python机器学习手册》-02-加载数据:加载文件

    这本书类似于工具书或者字典,对于python具体代码的调用和使用场景写的很清楚,感觉虽然是工具书,但是对照着做一遍应该可以对机器学习中python常用的这些库有更深入的理解,在应用…

    技术杂谈 2023年7月10日
    0100
  • gauss杀进程

    1)查询当前所有连接的状态 select datname,pid,application_name,state from pg_stat_activity; 2)关闭当前state…

    技术杂谈 2023年7月24日
    092
  • SpringSecurity 自定义表单登录

    SpringSecurity 自定义表单登录 本篇主要讲解 在SpringSecurity中 如何 自定义表单登录 , SpringSecurity默认提供了一个表单登录,但是实际…

    技术杂谈 2023年7月11日
    081
  • xampp相关配置文件所在路径

    环境: Xampp3.2.4一般来讲,可以在xampp的控制面板打开先关的配置文件,但是出现有些问题的时候,还是需要到别的路径下找到相关配置文件修改才行。 todo:更改xampp…

    技术杂谈 2023年7月25日
    081
  • Service与Activity通信 回调方式***

    要实现service与activity的高强度通信用什么方法? service与activity之前的通信方式有很多,回调接口方式、观察者模式、广播、还有handler等,方法有很…

    技术杂谈 2023年5月31日
    0108
  • pdf文件 a4转到手机

    pdf文件 a4转到手机 pdf文件 a4转到手机 pdf文件 a4转到手机 人工智能演示 ……. 计算….. Original: https:…

    技术杂谈 2023年5月31日
    090
  • 关于戴德金分割的几点思考

    谨以此文纪念杨振宁、李政道先生获得诺贝尔物理学奖60周年. 由无理数引发的数学危机一直延续到19世纪,直到1872年,德国数学家戴德金从连续性的要求出发,用有理数的”分…

    技术杂谈 2023年5月31日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球