转载

browserify总结

一。browserify 简介

browserify is a tool for compiling node-flavored commonjs modules for the browser

You can use browserify to organize your code and use third-party libraries even if you don't use node itself in any other capacity except for bundling and installing packages with npm .

The module system that browserify uses is the same as node, so packages published to npm that were originally intended for use in node but not browsers will work just fine in the browser too.

官网链接

简介就直接从官网上copy过来,重点信息都加粗了。

二。学习总结

browserify 可以使开发前端组件就像开发node后端一样----使用require引入依赖(无缝使用了node模块系统的优点),甚至可以使用node里面才有的东西(比如Buffer对象,events,crypto等)。然后最终将编写的模块编译成一个js文件。

我的观点

对于模块化

browserify在他的handbook里面论述了前端模块系统(window globals,concatenate,AMD)的优缺点. 其中对挂载在window对象上这种方式的批判理由是:

Instead of a module system, each file defines properties on the window global object or develops an internal namespacing scheme.

This approach does not scale well without extreme diligence since each new file needs an additional tag in all of the html pages where the application will be rendered. Further, the files tend to be very order-sensitive because some files need to be included before other files the expect globals to already be present in the environment.

It can be difficult to refactor or maintain applications built this way.This approach tends to be very slow since each tag initiates a new round-trip http request.

browserify相对于挂载到window对象的优势在于:他将js文件都编译成了一个,只有一个http请求,并且消除了因为加载顺序导致的依赖失败。

只有一个http请求是很容易办到的。只需将一个模块的所有js文件放到一个js文件里即可。开发的时候是多个文件,开发完之后使用gulp,uglify,minify之后按依赖顺序合并到一个文件里即可。这个方法就是browserify在他的handbook里说的concatenate,对于这个他的解释是难以维护,很难发现错误发生在哪里。对于这个的话,在开发阶段是多个文件分开独立开发的,只是最后使用gulp合并在一起,发现问题出现在哪里没有多难吧!!!

让我们来看一下他编译后的js代码结构:

(function e(t, n, r) { //浏览器端的模块加载函数  function s(o, u) {   if (!n[o]) {    if (!t[o]) {     var a = typeof require == "function" && require;     if (!u && a)      return a(o, !0);     if (i)      return i(o, !0);     var f = new Error("Cannot find module '" + o + "'");     throw f.code = "MODULE_NOT_FOUND",     f    }    var l = n[o] = {     exports : {}     };    t[o][0].call(l.exports, function (e) {     var n = t[o][1][e];     return s(n ? n : e)    }, l, l.exports, e, t, n, r)   }   return n[o].exports  }  var i = typeof require == "function" && require;  for (var o = 0; o < r.length; o++)   s(r[o]);  return s })({  1 : [function (require, module, exports) {//传入的自定义模块     exports.say = function () {     console.log("Hello word");    }   }, {}   ] }, {}, [1]); 

编译后的代码和直接使用闭包编写模块组件并没有太大不同,只不过这个引入了版本控制。模块自己有自己的依赖,如果模块的依赖中引入的俩个同名的模块的版本不同,那么就会俩个版本都引入,不会造成版本冲突(封装在各自的作用域下),只是文件会稍大,如果你能容忍,那没关系。

另外就是维护和重构,合并到一个文件里面确实难以维护。但是browserify最终也是将文件合并成了一个,开发的时候是多个。对于这个,按照上面我提到的方法,我们开发的时候也是各个小模块独立开发,最终聚合在一起。 这个方法的好处还有我们在开发的时候不需要编译即可进行各个模块间的联调,而browserify还需要编译一下。我们的编译只发生在最终的产品发布阶段。这个方法另外的优点browserify自己也提到:

On the plus side, all browsers natively support this approach and no server-side tooling is required.

对于使用node的模块

browserify可以使在浏览器端用node自带的或者本来是为node设计的第三方模块,比如events,Buffer,url等。对于这个特性我迫不及待地尝试了一下:

  • w1.js
    var events=require("events").EventEmitter;  var e=new events(); e.on("data",function(d){    document.getElementById("t1").innerHTML=d; });  module.exports=e; 
  • w2.js
 var crypto=require("crypto");  var md5update=function(str){    return crypto.createHash("md5").update(str).digest("hex"); };  exports.md5Update=md5update;
  • tools.js
exports.eventer=require("./w1.js"); exports.md5=require("./w2.js").md5Update; window.tools=exports;
  • build.js
  var browserify=require("browserify"); var fs=require("fs"); var ws=fs.createWriteStream("./final.js"); var b=browserify(); b.add("./tools.js"); b.bundle().pipe(ws);
  • test.html
  <!DOCTYPE html> <html>   <head>     <style>    #t1{      width:200px;   height:100px;   background-color:skyblue;   margin-left:300px;    }  </style>   </head>   <body>     <div id="t1"></div>     <script type="text/javascript" src="./final.js"></script>  <script>     setInterval(function(){       var k='t'+Math.random();    tools.eventer.emit('data',tools.md5(k));     },5000)  </script>   </body> </html>

然后: cmd>node build.js 编译出final.js 。使用浏览器打开test.html ,结果如预期:

browserify总结

可以看到md5加密后的字符串。

但是有一点令人无法接受,这个final.js 大小是549kb ,js.format之后是2w多行。 若非必要,还是不要用,d3的文件大小才300多kb,这才只用了crypto和events.....

final

我们可以选择性地使用browserify的功能,如果喜欢require()的方式的话,只要不嫌编译麻烦还是可以的。对于使用node本地的模块这一点,我们可以单独提出来,使用browserify做成对应项目的一个工具库。

正文到此结束
Loading...