使用node.js开发前端打包程序

我们在做前端开发的时候经常会在部署上线的时候做程序的打包和合并,我们接下来就会对如何使用 node.js 开发前端打包程序做非常深入的讲解,希望能够帮到有需要的同学。

柴桑网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、自适应网站建设等网站项目制作,到程序开发,运营维护。创新互联从2013年创立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联。

我们现在做前端开发更多的是多人共同协作开发,每个人负责不同的模块,便于开发和调试。这样就导致我们***部署上线的时候需要把所有人开发的模块进行合并,生成单个或多个文件上线。如果手动合并的话肯定是费时又费力,而且非常容易出错,所以我们一般都是通过一些工具来实现自动合并的功能。

打包程序的原理非常简单,入口文件->寻找依赖关系->替换依赖关系->生成文件,其中中间的两个步骤是递归执行的。
我们先来看一下使用 node.js 如何完成一个简单的文件合并功能:

 
 
 
  1. // 打包文件内容
  2. var contentList = [];
  3. // 排重列表
  4. var loadedFileList = {};
  5. // 打包主程序
  6. function combine(filePath){
  7.     // 这里获取入口文件的内容
  8.     var fileContent = fs.readFileSync(filePath);
  9.     // 遍历文件内容
  10.     fileContent.forEach(function(value){
  11.         // 这里的findImport是需要你来实现的方法,用正则来匹配依赖关系
  12.         var matchFile = findImport(value);
  13.         if(matchFile){
  14.             //如果匹配到依赖关系
  15.             If(!loadedFileList[matchFile]){
  16.                 //如果依赖关系不在排重列表中,递归调用combine
  17.                 combine(matchFile);
  18.                 contentList.push(‘\n’);
  19.             }
  20.         }else{
  21.             contentList.push(value);
  22.         }
  23.     });
  24. }

***只要根据 contentList 里面的内容来生成文件就可以了,怎么样,是不是很简单呢?下面我们就要介绍另外一种方式,使用流来完成我们的打包程序。

在 node.js 中,流(Stream)是一个由不同对象实现的抽象接口。流可以是可读的、可写的、或者既可读又可写的。所有的流都是 EventEmitter 的实例。我们可以通过继承接口来构造我们自己所需要的流。在我们的打包程序里面需要两个流,一个负责按行输出文件内容,另外一个负责处理依赖关系。所有的文件内容都在这两个流里面循环流动,当所有的依赖关系都处理完毕之后就结束流动并生成对应的文件,这样就达到我们的目的了。

让我们先来看一下负责按行输出文件内容的流是怎么样的:

 
 
 
  1. var Stream = require('stream').Stream,
  2.     util = require('util'),
  3.     path = require('path'),
  4.     fs = require('fs');
  5. // 构造函数
  6. function LineStream() {
  7.     this.writable = true;
  8.     this.readable = true;
  9.     this.buffer = '';
  10. }
  11. module.exports = LineStream;
  12. // 继承流接口
  13. util.inherits(LineStream, Stream);
  14. // 重写write方法,所有pipe过来的数据都会调用此方法
  15. LineStream.prototype.write = function(data, encoding) {
  16.     var that = this;
  17.     // 把buffer转换为string类型
  18.     if (Buffer.isBuffer(data)) {
  19.         data = data.toString(encoding || 'utf8');
  20.     }
  21.     var parts = data.split(/\n/g);
  22.     // 如果有上一次的buffer存在就添加到最前面
  23.     if (this.buffer.length > 0) {
  24.         parts[0] = this.buffer + parts[0];
  25.     }
  26.     // 遍历并发送数据
  27.     for (var i = 0; i < parts.length - 1; i++) {
  28.         this.emit('data', parts[i]);
  29.     }
  30.     // 把***一行数据保存到buffer,使传递过来的数据保持连续和完整。
  31.     this.buffer = parts[parts.length - 1];
  32. };
  33. // end方法,在流结束时调用
  34. LineStream.prototype.end = function() {
  35.     // 如果还有buffer,发送出去
  36.     if(this.buffer.length > 0){
  37.         this.emit('data',this.buffer);
  38.         this.buffer = '';
  39.     }
  40.     this.emit('end');
  41. };

这样我们的 lineStream 就完成了,我们看到在 write 方法里面就做了一件事,分解传递过来的数据并按行发送出去,然后我们看下处理依赖关系的流 DepsStream。

 
 
 
  1. var stream = require('stream').Stream;
  2. var util = require('util');
  3. var fs = require('fs');
  4. var path = require('path');
  5. module.exports = DepsStream;
  6. util.inherits(DepsStream,stream);
  7. function DepsStream(){
  8.     this.writable = true;
  9.     this.readable = true;
  10.     this.buffer = '';
  11.     this.depsList = [];
  12. };
  13. // 这里的write方法只发送数据,不对数据做任何的处理
  14. DepsStream.prototype.write = function(data){
  15.     this.emit('data',data);
  16. };
  17. // 我们在这里重新pipe方法,使其能够处理依赖关系和生成最终文件
  18. DepsStream.prototype.pipe = function(dest,opt){
  19.     var that = this;
  20.     function ondata(chunk){
  21.         var matches = findImport(chunk);
  22.         if(matches){
  23.             if(this.depsList.indexOf(matches) >= 0){
  24.                 // 我们在这里把处理过后的数据pipe回lineStream
  25.                 dest.write('\n');
  26.             }else{
  27.                 this.depsList.push(matches);
  28.                 var code = getFileContent(matches);
  29.                 // 我们在这里把处理过后的数据pipe回lineStream
  30.                 dest.write('\n' + code);
  31.             }
  32.         }else{
  33.             this.buffer += chunk + '\n';
  34.         }
  35.     }
  36.     function onend(){
  37.         // 生成最终文件
  38.         var code = this.buffer;
  39.         fs.writeFileSync(filePublishUrl,code);
  40.         console.log(filePublishUrl + ' combine done.');
  41.     }
  42.     // 监听end事件
  43.     that.on('end',onend);
  44.     // 监听data事件
  45.     that.on('data',ondata);
  46. };
  47. // end方法
  48. DepsStream.prototype.end = function(){
  49.     this.emit('end');
  50. };

我们看到上面的程序里面我们在 pipe 方法里面监听了 end 事件和 data 事件,ondata 方法主要用来对数据进行处理,发现有依赖关系的话就获取对应依赖关系的文件并重新发回给 LineStream 进行处理。onend 方法用来生成最终的文件,我们来看一下最终的调用方法:

 
 
 
  1. var fileStream = fs.createReadStream(filepath);
  2. var lineStream = new LineStream();
  3. var depsStream = new DepsStream();
  4. fileStream.pipe(lineStream);
  5. lineStream.pipe(depsStream);
  6. depsStream.pipe(lineStream);

怎么样,是不是非常简单,感兴趣的同学赶快尝试一下吧。

网页名称:使用node.js开发前端打包程序
网页地址:http://www.36103.cn/qtweb/news49/11799.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联