自动导入工具作为前端打字员,一个常见的场景是在路由文件中引入模块,比如在router/index.js中写importVuefrom'vue'importRouterfrom'vue-router'const=()=>import('../pages/About.vue')constHome=()=>import('../pages/Home.vue')Vue.use(Router)...如果修改了名称模块,如果添加模块或删除模块,需要重新修改路由文件。老是做这种机械的事情,无异于消耗我这个前端打字员的生命。实在受不了,于是自己写了一个工具整理思路如下。目录下文件的变化依赖于nodeAPI中的fs.watch(filename[,options][,listener])来替换目标文件中导入模块的部分,通过正则化实现。这里五颗星推荐一个验证正则化是否正确的网站。,regexr代码实现监控包含模块的目录fs.watch(dir,{recursive:true//目录下的子目录也被监控},(event,filename)=>{//event是文件变化的类型,addedfiles,deleting文件名和修改后的文件名都是'rename'event//filename是被改变的文件或目录if(event==='rename'){//判断文件改变的类型}})当rename事件发生,需要重新获取目录下(from)所有模块,包括模块名moduleName,模块文件相对于引用模块文件的相对路径modulePath(to),并将它们存放在实际项目中可变模块。模块一般是.vue文件,或者.jsx文件,所以这些只作为模块使用,在路由文件中引用其他一些模块文件。由于各种原因,我希望在不被监视的情况下手动导入它们。此类文件存储在excludeArrconst_=require('lodash')letexcludeArr=[...]letmodules=[]letextname='.vue'letfrom='./src/pages'letto='。/源/路由器/index.js"'constmapDir=d=>{//获取当前文件夹下的所有文件夹和文件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())}modules.push({moduleName,modulePath:path.relative(path.dirname(to),文件名e)})}}})}待导入的新模块生成后,下一步就是替换路由文件中的相应内容,所以需要读写文件,替换constregex=/\/\*\sautoImport(.*\n)*\/\*\sautoImport\s\*\//gletimportStr=''modules.forEach((m,index)=>{importStr=importStr+fillTemplate(模板,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,`/*autoImport*/${importStr}/*autoImport*/`)}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)})})where/\/\*\sautoImport(.*\n)*\/\*\sautoImport\s\*\//g用于匹配两个注释/*autoImport*/及其中间内容importVuefrom'vue'importRouterfrom'vue-router'/*autoImport*/constAbout=()=>import('../pages/About.vue')constHome=()=>import('../pages/Home.vue')/*autoImport*/Vue.use(Router)没有/*autoImport*/第一次使用时,需要插入导入的模块data.replace(/(.*import.*)(\n)([^(导入)])/,(匹配,p1,p2,p3,偏移量,字符串)=>{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/**"]}然后getconstconfig=fs.readFileSync('./autoImport.json')const{extname,from,to,template,exinclude}=JSON.parse(config)后记接下来就是把这个工具写成webpack插件了。我已经将它命名为AutoImportPlugin。先在github上占个坑,给个star。我不需要更改错误,我已经准备好使用它了。如果用更成熟的模块chokidar替代原先的watch工具有问题,提issue
