浏览器加载react/vue组件时,遇到es6转es5,jsx转js...时,一种方法是用webpack离线编译,一种方法是用babel在线热编译(为了效率部署前可以预热)。
我比较喜欢在线热编译,好处是发布时快,不经过build直接源码发布,并可以避免忘记编译步骤导致bug。
为了提供效率,把热编译结果保存为文件缓存起来。先检查是否有编译后缓存文件,有就直接读取,否者编译,再读取。
let fs=require('fs');
let babel = require("@babel/core");
let babel_preset_env=require('@babel/preset-env');
function transform(f,cb){
let fc=f+'.js';
fs.access(fc,function(err){
if (err){
fs.readFile(f,'utf8',function(err,code){
if (err){cb(err)}
else{
let r=babel.transformSync(code,{presets:[babel_preset_env]});
code=r.code;
cb(null,code);
fs.writeFile(fc,code,function(err){
});
}
});
}
else{
fs.readFile(f,'utf8',function(err,code){
cb(err,code);
});
}
});
}
transform('a.jsx',function(err,code){console.log(err,code});
但在多并发时,问题来了:多个并发任务可能会同时都检查到缓存不存在,然后开始编译.......很浪费,其实只需要一个任务来编译,其它任务等待编译结束后再读取缓存。
其实有点复杂,涉及到文件锁机制,阿里“通义千问”建议用proper-lockfile,我没用。模拟一下:
/**
* 测试多进程下,判断一个文件是否存在,不存在才生成内容创建文件
* 难点:
* (1)避免多个进程在生成文件内容。
* (2)一个进程如何等待正在生成文件的进程生成完成再读取。
* (3)等待的效率,降低cpu占用
*/
let path=require('path');
let fs=require('fs');
let fn=path.join(__dirname,'a.txt');
function rw5(task){
let fnlock=fn+'.lock';
//递归获取锁
function lock(cb){
fs.open(fnlock,'wx',function(err,fhandle){
if (err){
console.log(task,' locked,try again...');
setTimeout(function(){
lock(cb);
},1);
}
else{
fs.close(fhandle,function(err){
if (err) console.log(err);
console.log(task,' got lock');
cb();
});
}
});
}
function unlock(){
fs.unlink(fnlock,function(err){if (err) console.log(err)});
}
function read(cb){
fs.readFile(fn,'utf8',function(err,data){
//读不到正在写入的内容
if (err) console.log(err);
else console.log(task,' readed:',data);
if (cb) cb();
});
}
function write(cb){
let content='hello';
//用setTimeout模拟一个长时间的content计算过程,比如babel转码
setTimeout(function(){
fs.writeFile(fn,content,function(err,data){
console.log(task,' writed:',content);
if (cb) cb();
});
}, 1000);
}
fs.access(fn,function(err,data){
if (err){
console.log(task,' not exists');
lock(function(){
fs.access(fn,function(err,data){
if (err){
console.log(task,' not exists');
write(function(){
unlock();
});
}
else{
read(function(){
unlock();
});
}
});
});
}
else{
read();
}
});
}
rw5(1);
rw5(2);
看到的运行记录,可能如下:
D:\work\Source\yujiang.Foil.Node\test\filerw>node multirw.js
1 not exists
2 not exists
1 got lock
2 locked,try again...
1 not exists
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
2 locked,try again...
1 writed: hello
2 locked,try again...
2 got lock
2 readed: hello