nodejs分割js大文件
他们做音频处理时候遇到一个js文件ffmpeg-asm.js
——17.6M。想尝试压缩下,看看能压缩多少。
由于之前一直使用fis进行前端开发,于是把ffmpeg-asm.js拿到fis工程项目中,进行压缩。
悲剧的是,报错——文件太大,爆内存了:
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
那行吧,我直接使用ugligy-js
进行压缩。于是npm install ugligy-js
安装,再进行压缩,同样依然爆内存。
这个时候打开源文件,发现文件中绝大部分都是用于内存初始化的二进制数据(%……@¥#%¥%¥),js部分并不是很多,而二进制部分没有办法压缩。然后就用了一个最笨的方法手动把二进制部分拿出来,剩下的只有100多K,然后使用fis压缩,发现100多K的js压缩后有40多K 。
然并卵。还是不能直接压缩原始文件。这么大压缩不掉,那就把文件变小去压缩,到这儿就跑到本文的主题:分割js文件。思路就是读取源文件,设定一个界限值,每个界限值大小的内容都平均分到其他文件中去。
使用nodejs分割文件,那就是用fs
模块对文件进行处理。
首先不能使用readFile
,因为这样也是把文件内容全部读到内存中再进行算进行计算的,同样会爆内存。
只能使用createReadStream, createWriteSteam
对文件进行边读、边计算,边写文件。就是stream的操作。问题是并不能仅仅如读一个文件一样边读边操作(会造成写入失败,虽然文件数目是对的),这个需要对stream
进行精确控制。于是用到了through模块的帮助。这样便可以分割文件了:
var fs = require('fs');
var readstream = fs.createReadStream('source.js');
var through = require('through');
var size = 0;
var dest = null;
var file = 0;
readstream.setEncoding('utf-8');
readstream.on('data', function (chunk) {
size += chunk.length / 1000;
if (size > 500) { //每个文件左右
dest.pause();
dest = null;
size = 0;
file ++;
}
if (!dest) {
dest = through();
dest.pipe(fs.createWriteStream('aim/aim' + file +'.js'));
}
dest.queue(chunk);
}).on('end', function () {
// dest.emit('end');
})
需要注意的是,最后监听到end
时,不能理解结束stream(不理解,如果非要有的话,就是结束时候stream中仍有数据没有完全写入,此时结束的话不能写入了).
好。分割文件结束,那就分别去压缩吧。可是到这个时候才发现——ugligy-js不能压缩有语法错误的js文件。而分割文件的时候却没有办法做到刚刚截取到语句的正常结束。
那行,就按照这个思路在读取流的时候,拿到流数据,进行处理后去好拿到没有问题的语句,再写入文件!于是代码就变成这样:
var fs = require('fs');
var readstream = fs.createReadStream('test.js');
var through = require('through');
var size = 0;
var dest = null;
var file = 0;
var cacheData = '';
readstream.setEncoding('utf-8');
readstream.on('data', function (chunk) {
size += chunk.length / 1000;
cacheData += chunk;
if (size > 100) {
// console.log(size, cacheData);
dest.pause();
fs.writeFileSync('tet/aim' + file +'.js', cacheData)
size = 0;
cacheData = '';
dest = null;
file ++;
}
if (!dest) {
dest = through();
dest.pipe(fs.createWriteStream('aim/aim' + file +'.js'));
// dest.pipe();
}
dest.queue(chunk);
}).on('end', function () {
// dest.emit('end');
fs.writeFile('tet/aim' + file +'.js', cacheData, function (err){
})
})
可以成功的拿到各个数据段进行不怎么随心所欲的处理了(这也就是为什么另外写入文件而不是直接写入stream)。
好吧,剩下的怎么从一段js文件中怎么去拿没有问题的语句了.....
→ →。目前我也没思路。补下正则再回头想!!想的还有其他,如果截取css呢,其他语言呢?
顺便还有几个思路可以进行:
调整js运行的内存 压缩二进制 stream的何时结束
测试代码地址:nodejs-split-file. 另外文本严重参考:stackoverflow