自动导入工具先推荐两个干货。关于正则regexr和regexper,前者验证正则是否符合预期,后者将正则以图形的形式表达出来,有助于理解别人写的正则。作为前端打字员,一个经常遇到的场景是在路由文件中引入模块,比如这样写importVuefrom'vue'importRouterfrom'vue-router'constAbout=()=>import('../pages/About.vue')constHome=()=>import('../pages/Home.vue')Vue.use(Router)...如果修改模块名称,则增加或删除一个模块如果安装了模块,需要重新修改路由文件。老是做这种机械的事情,无异于消耗前端打字员的生命。实在受不了,于是自己写了一个工具整理思路如下。API中,fs.watch(filename[,options][,listener])替换目标文件中导入模块的部分,通过正则化实现。这里五颗星推荐一个验证正则化是否正确的网站。regexr代码实现了对包含模块的监控。Directoryfs.watch(dir,{recursive:true//目录下的子目录也被监控},(event,filename)=>{//event是文件变化的类型,添加文件、删除文件和修改文件名都是all'rename'event//filename为改变的文件或目录if(event==='rename'){//判断文件改变的类型}})当rename事件发生时,需要重新获得所有模块在目录中(from),包括模块名moduleName,模块文件相对于引用模块文件的相对路径modulePath(to),并将它们存放在实际项目中的变量modules中。模块通常是.vue文件或.jsx文件,所以只将这些作为模块使用,在路由文件中引用一些其他模块文件。由于各种原因,我希望在不被监视的情况下手动导入它们。这些文件存储在excludeArrconst_=require('lodash')letexcludeArr=[...]letmodules=[]letextname='.vue'letfrom='./src/pages'letto='./src/router/index.js"'constmapDir=d=>{//获取当前文件夹All文件夹和文件const[dirs,files]=_(fs.readdirSync(d)).partition(p=>fs.statSync(path.join(d,p)).isDirectory())//映射文件夹dirs.forEach(dir=>{modules.concat(mapDir(path.join(d,dir)))})//映射文件files.forEach(file=>{//文件扩展名letfilename=path.join(d,file)if(path.extname(file)===extname){if(!excludeArr.includes(path.resolve(__dirname,filename))){letmoduleName=path.basename(file,extname)//如果存在-if(moduleName.match('-')){moduleName=moduleName.replace(/(-)(.{1})/,(match,p1,p2,offset,string)=>p2.toUpperCase())}模块。push({模块名称,modulePath:path.relative(path.dirname(to),filename)})}}})}生成新的要导入的模块后,下一步就是替换路由文件中的相应内容,所以需要读写文件和常规替换constregex=/\/\*\sautoImport(.*\n)*\/\*\sautoImport\s\*\//gletimportStr=''modules.forEach((m,index)=>{importStr=importStr+fillTemplate(template,m.moduleName,m.modulePath)+(cache.length-1===index?'':'\n')})fs.readFile(to,'utf8',(err,data)=>{if(err)returnconsole.log(err)letresult=''if(data.match(regex)){result=data.replace(regex,`/*自动导入*/${importStr}/*自动导入*/`)}else{/*第一次在文件末尾插入导入*/result=data.replace(/(.*import.*)(\n)([^(import)])/,(match,p1,p2,p3,offset,string)=>{return`${p1}/*autoImport*/${importStr}/*autoImport*/${p3}`})}fs.writeFile(to,result,'utf8',err=>{if(err)returnconsole.log(err)})})其中/\/\*\sautoImport(.*\n)*\/\*\sautoImport\s\*\//g是用于匹配两段Comments/*autoImport*/和importVuefrom'vue'importRouterfrom'vue-router'/*autoImport*/constAbout=()=>import('../pages/About.vue')constHome=()=>import('../pages/Home.vue')/*autoImport*/Vue.use(Router)第一次使用时,没有/*autoImport*/,它需要在最后import后插入导入的模块data.replace(/(.*import.*)(\n)([^(import)])/,(match,p1,p2,p3,offset,string)=>{return`${p1}/*autoImport*/${importStr}/*autoImport*/${p3}`这里也可以自定义导入模块了方式,比如延迟加载,"constmoduleName=()=>import(modulePath)"consttemplate="constmoduleName=()=>import(modulePath)"constfillTemplate=(template,moduleName,modulePath)=>template。replace('moduleName',moduleName).replace('modulePath',`'${modulePath}'`)为了工具的灵活性,将可配置项写成json文件的形式{"extname":".vue","from":"src/pages","to":"src/router/index.js","template":"constmoduleName=()=>import(modulePath)","exclude":["./src/pages/login.vue","./src/pages/404.vue","./src/pages/overall/**","./src/pages/account-result/**"]}然后获取constconfig=fs.readFileSync('./autoImport.json')const{extname,from,to,template,exclude}=JSON.parse(config)Postscript接下来就是把这个工具写成webpack插件,我已经给它命名了,AutoImportPlugin,先在github上占个坑,给个star,不用修bug,同时准备用一个更成熟的模块chokidar代替原来的watch工具。
