其实如何打包网站模板源码分享的问题并不复杂,但是又很多的朋友都不太了解专业的网站打包app平台,因此呢,今天小编就来为大家分享如何打包网站模板源码分享的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!
本文为Varlet组件库源码主题阅读系列第二篇,读完本篇,你可以了解到如何将一个Vue3组件库打包成各种格式
上一篇里提到了启动服务前会先进行一下组件库的打包,运行的命令为:
varlet-clicompile
显然是varlet-cli提供的一个命令:
处理函数为compile,接下来我们详细看一下这个函数都做了什么。
//varlet-cli/src/commands/compile.ts\nexportasyncfunctioncompile(cmd:{noUmd:boolean}){\nprocess.env.NODE_ENV=&39;\nawaitremoveDir()\n//…\n}\n\n//varlet-cli/src/commands/compile.ts\nexportfunctionremoveDir(){\n//ES_DIR:varlet-ui/es\n//LIB_DIR:varlet-ui/lib\n//HL_DIR:varlet-ui/highlight\n//UMD_DIR:varlet-ui/umd\nreturnPromise.all([remove(ES_DIR),remove(LIB_DIR),remove(HL_DIR),remove(UMD_DIR)])\n}
首先设置了一下当前的环境变量,然后清空相关的输出目录。
//varlet-cli/src/commands/compile.ts\nexportasyncfunctioncompile(cmd:{noUmd:boolean}){\n//…\nprocess.env.TARGET_MODULE=&39;\nawaitrunTask(&39;,compileModule)\n\nprocess.env.TARGET_MODULE=&39;\nawaitrunTask(&39;,()=>compileModule(&39;))\n\nprocess.env.TARGET_MODULE=&39;\nawaitrunTask(&39;,()=>compileModule(&39;))\n\nprocess.env.TARGET_MODULE=&39;\n!cmd.noUmd&&(awaitrunTask(&39;,()=>compileModule(&39;)))\n}
接下来依次打包了四种类型的产物,方法都是同一个compileModule,这个方法后面会详细分析。
组件的基本组成
以Button组件为例看一下未打包前的组件结构:
一个典型组件的构成主要是四个文件:
.less:样式
.vue:组件
index.ts:导出组件,提供组件注册方法
props.ts:组件的props定义
样式部分Varlet使用的是less语言,样式比较少的话会直接内联写到Vue单文件的style块中,否则会单独创建一个样式文件,比如图中的button.less,每个组件除了引入自己本身的样式外,还会引入一些基本样式、其他组件的样式:
index.ts文件用来导出组件,提供组件的注册方法:
props.ts文件用来声明组件的props类型:
有的组件没有使用.vue,而是.tsx,也有些组件会存在其他文件,比如有些组件就还存在一个provide.ts文件,用于向子孙组件注入数据。
打包的整体流程
首先大致过一遍整体的打包流程,主要函数为compileModule:
//varlet-cli/src/compiler/compileModule.ts\nexportasyncfunctioncompileModule(modules:&39;|&39;|&39;|boolean=false){\nif(modules===&39;){\n//打包umd格式\nawaitcompileUMD()\nreturn\n}\n\nif(modules===&39;){\n//打包esm-bundle格式\nawaitcompileESMBundle()\nreturn\n}\n\n//打包commonjs和module格式\n//打包前设置一下环境变量\nprocess.env.BABEL_MODULE=modules===&39;?&39;:&39;\n//输出目录\n//ES_DIR:varlet-ui/es\n//LIB_DIR:varlet-ui/lib\nconstdest=modules===&39;?LIB_DIR:ES_DIR\n//SRC_DIR:varlet-ui/src,直接将组件的源码目录复制到输出目录\nawaitcopy(SRC_DIR,dest)\n//读取输出目录\nconstmoduleDir:string[]=awaitreaddir(dest)\n//遍历打包每个组件\nawaitPromise.all(\n//遍历每个组件目录\nmoduleDir.map((filename:string)=>{\nconstfile:string=resolve(dest,filename)\nif(isDir(file)){\n//在每个组件目录下新建两个样式入口文件\nensureFileSync(resolve(file,&39;))\nensureFileSync(resolve(file,&39;))\n}\n//打包组件\nreturnisDir(file)?compileDir(file):null\n})\n)\n//遍历varlet-ui/src/目录,找出所有存在[&39;,&39;,&39;,&39;,&39;]这些文件之一的目录\nconstpublicDirs=awaitgetPublicDirs()\n//生成整体的入口文件\nawait(modules===&39;?compileCommonJSEntry(dest,publicDirs):compileESEntry(dest,publicDirs))\n}
umd和esm-bundle两种格式都会把所有内容都打包到一个文件,用的是Vite提供的方法进行打包。
commonjs和module是单独打包每个组件,不会把所有组件的内容都打包到一起,Vite没有提供这个能力,所以需要自行处理,具体操作为:
先把组件源码目录varlet/src/下的所有组件文件都复制到对应的输出目录下;然后在输出目录遍历每个组件目录:创建两个样式的导出文件;删除不需要的目录、文件(测试、示例、文档);分别编译Vue单文件、ts文件、less文件;全部打包完成后,遍历所有组件,动态生成整体的导出文件;
以compileESEntry方法为例看一下整体导出文件的生成:
//varlet-cli/src/compiler/compileScript.ts\nexportasyncfunctioncompileESEntry(dir:string,publicDirs:string[]){\nconstimports:string[]=[]\nconstplugins:string[]=[]\nconstconstInternalComponents:string[]=[]\nconstcssImports:string[]=[]\nconstlessImports:string[]=[]\nconstpublicComponents:string[]=[]\n//遍历组件目录名称\npublicDirs.forEach((dirname:string)=>{\n//连字符转驼峰式\nconstpublicComponent=bigCamelize(dirname)\n//收集组件名称\npublicComponents.push(publicComponent)\n//收集组件导入语句\nimports.push(`import${publicComponent},*as${publicComponent}Modulefrom&39;`)\n//收集内部组件导入语句\nconstInternalComponents.push(\n`exportconst_${publicComponent}Component=${publicComponent}Module._${publicComponent}Component||{}`\n)\n//收集插件注册语句\nplugins.push(`${publicComponent}.install&&app.use(${publicComponent})`)\n//收集样式导入语句\ncssImports.push(`import&39;`)\nlessImports.push(`import&39;`)\n})\n\n//拼接组件注册方法\nconstinstall=`\nfunctioninstall(app){\n${plugins.join(&39;)}\n}\n`\n\n//拼接导出入口index.js文件的内容,注意它是不包含样式的\nconstindexTemplate=`\\\n${imports.join(&39;)}\\n\n${constInternalComponents.join(&39;)}\\n\n${install}\nexport{\ninstall,\n${publicComponents.join(&39;)}\n}\n\nexportdefault{\ninstall,\n${publicComponents.join(&39;)}\n}\n`\n\n//拼接css导入语句\nconststyleTemplate=`\\\n${cssImports.join(&39;)}\n`\n\n//拼接umdIndex.js文件,这个文件是用于后续打包umd和esm-bundle格式时作为打包入口,注意它是包含样式导入语句的\nconstumdTemplate=`\\\n${imports.join(&39;)}\\n\n${cssImports.join(&39;)}\\n\n${install}\nexport{\ninstall,\n${publicComponents.join(&39;)}\n}\n\nexportdefault{\ninstall,\n${publicComponents.join(&39;)}\n}\n`\n\n//拼接less导入语句\nconstlessTemplate=`\\\n${lessImports.join(&39;)}\n`\n//将拼接的内容写入到对应文件\nawaitPromise.all([\nwriteFile(resolve(dir,&39;),indexTemplate,&39;),\nwriteFile(resolve(dir,&39;),umdTemplate,&39;),\nwriteFile(resolve(dir,&39;),styleTemplate,&39;),\nwriteFile(resolve(dir,&39;),lessTemplate,&39;),\n])\n}
打包成module和commonjs格式
打包成umd和esm-bundle两种格式依赖module格式的打包产物,而打包成module和commonjs两种格式是同一套逻辑,所以我们先来看看是如何打包成这两种格式的。
这两种格式就是单独打包每个组件,生成单独的入口文件和样式文件,然后再生成一个统一的导出入口,不会把所有组件的内容都打包到同一个文件,方便按需引入,去除不需要的内容,减少文件体积。
打包每个组件的compileDir方法:
//varlet-cli/src/compiler/compileModule.ts\nexportasyncfunctioncompileDir(dir:string){\n//读取组件目录\nconstdirs=awaitreaddir(dir)\n//遍历组件目录下的文件\nawaitPromise.all(\ndirs.map((filename)=>{\nconstfile=resolve(dir,filename)\n//删除组件目录下的__test__目录、example目录、docs目录\n;[TESTS_DIR_NAME,EXAMPLE_DIR_NAME,DOCS_DIR_NAME].includes(filename)&&removeSync(file)\n//如果是.d.ts文件或者是style目录(前面为样式入口文件创建的目录)直接返回\nif(isDTS(file)||filename===STYLE_DIR_NAME){\nreturnPromise.resolve()\n}\n//编译文件\nreturncompileFile(file)\n})\n)\n}
删除了不需要的目录,然后针对需要编译的文件调用了compileFile方法:
//varlet-cli/src/compiler/compileModule.ts\nexportasyncfunctioncompileFile(file:string){\nisSFC(file)&&(awaitcompileSFC(file))//编译vue文件\nisScript(file)&&(awaitcompileScriptFile(file))//编译js文件\nisLess(file)&&(awaitcompileLess(file))//编译less文件\nisDir(file)&&(awaitcompileDir(file))//如果是目录则进行递归\n}
分别处理三种文件,让我们一一来看。
编译Vue单文件
//varlet-cli/src/compiler/compileSFC.ts\nimport{parse}from&39;\n\nexportasyncfunctioncompileSFC(sfc:string){\n//读取Vue单文件内容\nconstsources:string=awaitreadFile(sfc,&39;)\n//使用@vue/compiler-sfc包解析单文件\nconst{descriptor}=parse(sources,{sourceMap:false})\n//取出单文件的每部分内容\nconst{script,scriptSetup,template,styles}=descriptor\n//Varlet暂时不支持setup语法\nif(scriptSetup){\nlogger.warning(\n`\\nVarletClidoesnotsupportcompilingscriptsetupsyntax\\\n\\nTheerrorin${sfc}`\n)\nreturn\n}\n//…\n}
使用@vue/compiler-sfc包来解析Vue单文件,parse方法可以解析出Vue单文件中的各个块,针对各个块,@vue/compiler-sfc包都提供了相应的编译方法,后续都会涉及到。
//varlet-cli/src/compiler/compileSFC.ts\nimporthashfrom&39;\n\nexportasyncfunctioncompileSFC(sfc:string){\n//…\n//scoped\n//检查是否存在scoped作用域的样式块\nconsthasScope=styles.some((style)=>style.scoped)\n//将单文件的内容进行hash生成id\nconstid=hash(sources)\n//生成样式的scopeId\nconstscopeId=hasScope?`data-v-${id}`:&39;\n//…\n}
这一步主要是检查style块是否存在作用域块,存在的话会生成一个作用域id,作为css的作用域,防止和其他样式冲突,这两个id相关的编译方法需要用到。
//varlet-cli/src/compiler/compileSFC.ts\nimport{compileTemplate}from&39;\n\nexportasyncfunctioncompileSFC(sfc:string){\n//…\nif(script){\n//template\n//编译模板为渲染函数\nconstrender=\ntemplate&&\ncompileTemplate({\nid,\nsource:template.content,\nfilename:sfc,\ncompilerOptions:{\nscopeId,\n},\n})\n//注入render函数\nlet{content}=script\nif(render){\nconst{code}=render\ncontent=injectRender(content,code)\n}\n//…\n}\n}
使用@vue/compiler-sfc包的compileTemplate方法将解析出的模板部分编译为渲染函数,然后调用injectRender方法将渲染函数注入到script中:
//varlet-cli/src/compiler/compileSFC.ts\nconstNORMAL_EXPORT_START_RE=/export\\s+default\\s+{/\nconstDEFINE_EXPORT_START_RE=/export\\s+default\\s+defineComponent\\s*\\(\\s*{/\n\nexportfunctioninjectRender(script:string,render:string):string{\nif(DEFINE_EXPORT_START_RE.test(script.trim())){\nreturnscript.trim().replace(\nDEFINE_EXPORT_START_RE,\n`${render}\\nexportdefaultdefineComponent({\nrender,\\\n`\n)\n}\nif(NORMAL_EXPORT_START_RE.test(script.trim())){\nreturnscript.trim().replace(\nNORMAL_EXPORT_START_RE,\n`${render}\\nexportdefault{\nrender,\\\n`\n)\n}\nreturnscript\n}
兼容两种导出方式,以一个小例子来看一下,比如生成的渲染函数为:
exportfunctionrender(_ctx,_cache){\n//…\n}
script的内容为:
exportdefaultdefineComponent({\nname:&39;,\n//…\n})
注入render后script的内容变成了:
exportfunctionrender(_ctx,_cache){\n//…\n}\nexportdefaultdefineComponent({\nrender,\nname:&39;,\n///…\n})
其实就是把渲染函数的内容和script的内容合并了,script其实就是组件的选项对象,所以同时也把组件的渲染函数添加到组件对象上。
继续compileSFC方法:
//varlet-cli/src/compiler/compileSFC.ts\nimport{compileStyle}from&39;\n\nexportasyncfunctioncompileSFC(sfc:string){\n//…\nif(script){\n//…\n//script\n//编译js\nawaitcompileScript(content,sfc)\n//style\n//编译样式\nfor(letindex=0;index<styles.length;index++){\nconststyle:SFCStyleBlock=styles[index]\n//replaceExt方法接收文件名称,比如xxx.vue,然后使用第二个参数替换文件名称的扩展名,比如处理完会返回xxxSfc.less\nconstfile=replaceExt(sfc,`Sfc${index||&39;}.${style.lang||&39;}`)\n//编译样式块\nlet{code}=compileStyle({\nsource:style.content,\nfilename:file,\nid:scopeId,\nscoped:style.scoped,\n})\n//去除样式中的导入语句\ncode=extractStyleDependencies(file,code,STYLE_IMPORT_RE,style.langas&39;|&39;,true)\n//将解析后的样式写入文件\nwriteFileSync(file,clearEmptyLine(code),&39;)\n//如果样式块是less语言,那么同时也编译成css文件\nstyle.lang===&39;&&(awaitcompileLess(file))\n}\n}\n}
调用了compileScript方法编译script内容,这个方法我们下一小节再说。然后遍历style块,每个块都会生成相应的样式文件,比如Button.vue组件存在一个less语言的style块
那么会生成一个ButtonSfc.less,因为是less,所以同时也会再编译生成一个ButtonSfc.css文件,当然这两个样式文件里只包括内联在Vue单文件中的样式,不包括使用@import导入的样式,所以生成的这两个样式文件都是空的:
编译样式块使用的是@vue/compiler-sfc的compileStyle方法,它会帮我们处理<stylescoped>,<stylemodule>以及css变量注入的问题。
extractStyleDependencies方法会提取并去除样式中的导入语句:
//varlet-cli/src/compiler/compileStyle.ts\nimport{parse,resolve}from&39;\n\nexportfunctionextractStyleDependencies(\nfile:string,\ncode:string,\nreg:RegExp,///@import\\s+[&34;](.+)[&34;]\\s*;/g\nexpect:&39;|&39;,\nself:boolean\n){\nconst{dir,base}=parse(file)\n//用正则匹配出样式导入语句\nconststyleImports=code.match(reg)??[]\n//这两个文件是之前创建的\nconstcssFile=resolve(dir,&39;)\nconstlessFile=resolve(dir,&39;)\nconstmodules=process.env.BABEL_MODULE\n//遍历导入语句\nstyleImports.forEach((styleImport:string)=>{\n//去除导入源的扩展名及处理导入的路径,因为index.js和less.js两个文件和Vue单文件不在同一个层级,所以导入的相对路径需要修改一下\nconstnormalizedPath=normalizeStyleDependency(styleImport,reg)\n//将导入语句写入创建的两个文件中\nsmartAppendFileSync(\ncssFile,\nmodules===&39;?`require(&39;)\\n`:`import&39;\\n`\n)\nsmartAppendFileSync(\nlessFile,\nmodules===&39;?`require(&39;)\\n`:`import&39;\\n`\n)\n})\n//上面已经把Vue单文件中style块内的导入语句提取出去了,另外之前也提到了每个style块本身也会创建一个样式文件,所以导入这个文件的语句也需要追加进去:\nif(self){\nsmartAppendFileSync(\ncssFile,\nmodules===&39;\n?`require(&39;)\\n`\n:`import&39;\\n`\n)\nsmartAppendFileSync(\nlessFile,\nmodules===&39;\n?`require(&39;)\\n`\n:`import&39;\\n`\n)\n}\n//去除样式中的导入语句\nreturncode.replace(reg,&39;)\n}
到这里,一共生成了四个文件:
编译less文件
script部分的编译比较复杂,我们最后再看,先看一下less文件的处理。
//varlet-cli/src/compiler/compileStyle.ts\nimport{render}from&39;\n\nexportasyncfunctioncompileLess(file:string){\nconstsource=readFileSync(file,&39;)\nconst{css}=awaitrender(source,{filename:file})\n\nwriteFileSync(replaceExt(file,&39;),clearEmptyLine(css),&39;)\n}
很简单,使用less包将less编译成css,然后写入文件即可,到这里又生成了一个css文件:
编译script文件
script部分,主要是ts、tsx文件,Varlet大部分组件是使用Vue单文件编写的,不过也有少数组件使用的是tsx,编译调用了compileScriptFile方法:
//varlet-cli/src/compiler/compileScript.ts\nexportasyncfunctioncompileScriptFile(file:string){\nconstsources=readFileSync(file,&39;)\n\nawaitcompileScript(sources,file)\n}
读取文件,然后调用compileScript方法,前面Vue单文件中解析出来的script部分内容调用的也是这个方法。
兼容模块导入
//varlet-cli/src/compiler/compileScript.ts\nexportasyncfunctioncompileScript(script:string,file:string){\nconstmodules=process.env.BABEL_MODULE\n//兼容模块导入\nif(modules===&39;){\nscript=moduleCompatible(script)\n}\n//…\n}
首先针对commonjs做了一下兼容处理:
//varlet-cli/src/compiler/compileScript.ts\nexportconstmoduleCompatible=(script:string):string=>{\nconstmoduleCompatible=get(getVarletConfig(),&39;,{})\nObject.keys(moduleCompatible).forEach((esm)=>{\nconstcommonjs=moduleCompatible[esm]\nscript=script.replace(esm,commonjs)\n})\nreturnscript\n}
替换一些导入语句,Varlet组件开发是基于ESM规范的,使用其他库时导入的肯定也是ESM版本,所以编译成commonjs模块时需要修改成对应的commonjs版本,Varlet引入的第三方库不多,主要就是dayjs:
使用babel编译
继续compileScript方法:
//varlet-cli/src/compiler/compileScript.ts\nimport{transformAsync}from&39;\n\nexportasyncfunctioncompileScript(script:string,file:string){\n//…\n//使用babel编译js\nlet{code}=(awaittransformAsync(script,{\nfilename:file,//js内容对应的文件名,babel插件会用到\n}))asBabelFileResult\n//…\n}
接下来使用@babel/core包编译js内容,transformAsync方法会使用本地的配置文件,因为打包命令是在varlet-ui/目录下运行的,所以babel会在这个目录下寻找配置文件:
编译成module还是commonjs格式的判断也在这个配置中,有关配置的详解,有兴趣的可以阅读最后的附录小节。
提取样式导入语句
继续compileScript方法:
//varlet-cli/src/compiler/compileScript.ts\nexportconstREQUIRE_CSS_RE=/(?<![&34;`])require\\(\\s*[&34;](\\.{1,2}\\/.+\\.css)[&34;]\\s*\\);?(?!\\s*[&34;`])/g\nexportconstREQUIRE_LESS_RE=/(?<![&34;`])require\\(\\s*[&34;](\\.{1,2}\\/.+\\.less)[&34;]\\s*\\);?(?!\\s*[&34;`])/g\nexportconstIMPORT_CSS_RE=/(?<![&34;`])import\\s+[&34;](\\.{1,2}\\/.+\\.css)[&34;]\\s*;?(?!\\s*[&34;`])/g\nexportconstIMPORT_LESS_RE=/(?<![&34;`])import\\s+[&34;](\\.{1,2}\\/.+\\.less)[&34;]\\s*;?(?!\\s*[&34;`])/g\n\nexportasyncfunctioncompileScript(script:string,file:string){\n//…\ncode=extractStyleDependencies(\nfile,\ncodeasstring,\nmodules===&39;?REQUIRE_CSS_RE:IMPORT_CSS_RE,\n&39;\n)\ncode=extractStyleDependencies(\nfile,\ncodeasstring,\nmodules===&39;?REQUIRE_LESS_RE:IMPORT_LESS_RE,\n&39;\n)\n//…\n}
extractStyleDependencies方法前面已经介绍了,所以这一步的操作就是提取并去除script内的样式导入语句。
转换其他导入语句
//varlet-cli/src/compiler/compileScript.ts\nexportasyncfunctioncompileScript(script:string,file:string){\n//…\ncode=replaceVueExt(codeasstring)\ncode=replaceTSXExt(codeasstring)\ncode=replaceJSXExt(codeasstring)\ncode=replaceTSExt(codeasstring)\n//…\n}
这一步的操作是把script中的各种类型的导入语句都修改为导入.js文件,因为这些文件最后都会被编译成js文件,比如button/index.ts文件内导入了Button.vue组件:
importButtonfrom&39;\n//…
转换后会变成:
importButtonfrom&39;\n//…
继续:
//varlet-cli/src/compiler/compileScript.ts\nexportasyncfunctioncompileScript(script:string,file:string){\n//…\nremoveSync(file)\nwriteFileSync(replaceExt(file,&39;),code,&39;)\n}
最后就是把处理完的script内容写入文件。
到这里.vue,.ts、.tsx文件都已处理完毕:
小节
到这里,打包成module和commonjs格式就完成了,总结一下所做的事情:
less文件直接使用less包编译成同名的css文件;ts、tsx等文件使用babel编译成js文件;提取并去除其中的样式导入语句,并将该样式导入语句写入单独的文件、修改.vue、.ts等类型的导入语句为对应的编译后的js;Vue单文件使用@vue/compiler-sfc解析并对各个块分别使用对应的函数进行编译;每个style块也会提取并去除其中的样式导入语句,并将该导入语句写入单独的文件,剩下的样式内容会分别创建一个对应的样式文件,如果是less块,同时会编译并创建一个同名的css文件;template的编译结果会合并到script内,然后script的内容会重复上一步ts文件的处理逻辑;所有组件都编译完了,再动态创建整体的导出文件,一共生成了四个文件:
打包成esm-bundle
打包成esm-bundle格式调用的是compileESMBundle方法:
//varlet-cli/src/compiler/compileModule.ts\nimport{build}from&39;\n\nexportfunctioncompileESMBundle(){\nreturnnewPromise<void>((resolve,reject)=>{\nconstconfig=getESMBundleConfig(getVarletConfig())\n\nbuild(config)\n.then(()=>resolve())\n.catch(reject)\n})\n}
getVarletConfig方法会把varlet-cli/varlet.default.config.js和varlet-ui/varlet.config.js两个配置进行合并,看一下getESMBundleConfig方法:
//varlet-cli/src/config/vite.config.js\nexportfunctiongetESMBundleConfig(varletConfig:Record<string,any>):InlineConfig{\nconstname=get(varletConfig,&39;)//name默认为Varlet\nconstfileName=`${kebabCase(name)}.esm.js`//输出文件名,varlet.esm.js\n\nreturn{\nlogLevel:&39;,\nbuild:{\nemptyOutDir:true,//清空输出目录\nlib:{//指定构建为库\nname,//库暴露的全局变量\nformats:[&39;],//构建格式\nfileName:()=>fileName,//打包出口\nentry:resolve(ES_DIR,&39;),//打包入口\n},\nrollupOptions:{//传给rollup的配置\nexternal:[&39;],//外部化处理不需要打包进库的依赖\noutput:{\ndir:ES_DIR,//输出目录,ES_DIR:varlet-ui/es\nexports:&39;,//既存在命名导出,也存在默认导出,所以设置为named,详情:https://rollupjs.org/guide/en/39;Vue&39;vite&39;name&39;silent&39;umd&39;umdIndex.js&39;vue&39;named&39;Vue&39;varlet-inline-css-vite-plugin&39;build&39;style.css&39;utf-8&39;utf-8&39;style&39;text/css&39;stylesheet&39;\\\\\\\\&39;head&39;style.css&39;test&39;commonjs&39;@babel/preset-env&39;commonjs&39;@babel/preset-typescript&39;./babel.sfc.transform&39;@vue/babel-plugin-jsx&39;fs&39;@babel/helper-plugin-utils&39;utf8&39;lang=&34;&34;lang=&39;&39;@babel/plugin-transform-typescript'],\n},\n],\n}))
通过babel的overrides选项来根据条件注入配置,当处理的是Vue单文件的内容,并且使用的是ts语法,那么就会注入一个插件@babel/plugin-transform-typescript,用于转换ts语法,非Vue单文件会忽略这个配置,进入下一个preset:@babel/preset-typescript,这个预设也包含了前面的@babel/plugin-transform-typescript插件,但是这个预设只会在.ts文件才会启用ts插件,所以前面才需要自行判断Vue单文件并手动配置ts插件,ts语法转换完毕后最后会进入@babel/preset-env,进行js语法的转换。
END,本文到此结束,如果可以帮助到大家,还望关注本站哦!
