Vite插件可以理解为遵循一定规范,实现一定功能的程序。Vite插件是为了赋予Vite更强大的功能。与Webpack不同,Webpack有Loader和Plugin的区别。在Vite中,Loader也是作为Plugin实现的。这也是因为Vite使用Rollup来实现编译。之前说过,在生产环境中,Vite使用Rollup来打包源码。但是,在开发环境中,Vite只是模拟了Rollup的行为。之所以在开发环境中不直接调用Rollup的API,是为了提高性能。和Rollup一样,可以解析插件对象,正确执行和处理插件的钩子。开发插件最重要的部分是了解钩子以及它们何时被调用。Vite支持Rollup的大部分hooks,并且基于一些优化的考虑,增加了一些独特的hooks,并预置了多个Rollup插件。使用Vite插件插件的使用非常简单,只需要三步:找到一个具有所需功能的Vite插件。在寻找技术栈相关的周边工具时,我一般会在github上搜索awesomexxx。下载。添加到项目的devDependencies。npmivite-plugin-banner-D在vite.config.js配置文件的plugins数组中引入,可以根据插件的API配置相关参数。//vite.config.jsimport{defineConfig}from"vite";importbannerfrom'vite-plugin-banner';exportdefaultdefineConfig({plugins:[banner('Thisisthebannercontent.')]})实现一个插件需求分析目标:想直观的看到线上代码是哪个版本方案:timestamp。版本号。结合ONES版本规划,Gittag或releaseGit分支管理。Git的commithash表示:通过控制台打印,最终输出的文件名用于表示文件注释。这里我们选择Git的commithash结合console打印的方案(当然不是这样的,所以不需要Git版本管理)。Vite插件的结构很简单,就是一个对象,这个对象有一些必须的属性(name)和可选的属性(hookfunction),例如://vite.config.jsimport{defineConfig}from"vite";exportdefaultdefineConfig({plugins:[{name:"my-plugin",//命名要遵循约定transform(code,id){//钩子函数返回码+"vara=1;console.log(a)"}},],});实现要求://vite.config.jsimport{defineConfig}from"vite";import{execSync}from"child_process";exportdefaultdefineConfig({plugins:[{name:"my-plugin",apply:"build",transformIndexHtml(html){consthash=runGit("gitrev-parseHEAD");constbranch=runGit("gitrev-parse--abbrev-refHEAD");constdate=runGit("gitlog-1--format=%ci");functionrunGit(str){returnexecSync(str).toString().replace("\n","");}return[{tag:"script",children:`console.info("branch:${branch}")console.info("hash:${hash}")console.info("date:${date}")`,注入:“头”,},];},},],});打包发布前的插件内容直接写在vite.config.js中。当插件很多或者你想贡献插件到社区时,显然这样维护起来很不方便。接下来,插件将以最简洁的形式发布到Coding私有镜像库:新建一个项目,命名为vite-plugin-git-log。插件使用Vite特有的hooks,则使用vite-plugin-xxx的格式命名,如果用于特定的框架(如Vue),则使用vite-plugin-vue-xxx的格式命名.如果插件兼容Rollup,添加格式为rollup-plugin-xxx的package.json:{"name":"vite-git-log","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo\"Error:notestspecified\"&&exit1"},"peerDependencies":{"vite":"^3.1.0"},"engines":{"node":"^14.18.0||>=16.0.0"},"author":"xxx","license":"MIT"}Newindex.js:从“child_process”导入{execSync};导出默认函数(pluginOptions){consthash=runGit("gitrev-parseHEAD");constbranch=runGit("gitrev-parse--abbrev-refHEAD");constdate=runGit("gitlog-1--format=%ci");functionrunGit(str){returnexecSync(str).toString().replace("\n","");}return{name:"vite-plugin-git-log",apply:"build",transformIndexHtml(html){return[{tag:"script",children:`console.info("branch:${branch}")console.info("hash:${hash}")console.info("date:${date}")`,injectTo:"head",},];},};}找到管理员开启推送权限,按照操作指南配置好,就可以推送了。在项目中可以通过npminstallvite-plugin-git-log-D等命令安装使用。插件挂钩的内容主要是先写个插件体验。不谈Vite插件的API。比如上面写的两个插件,为什么配置的钩子函数不一样,不同的钩子有什么区别?对于插件开发者来说,最重要的是知道选择哪个(某些)hook,并在相应的hook中实现不同的服务,从而达到目的。以下是hooks的总结:calltimingBuildHooksconstchunks=rollup.rollup()buildhook函数执行期间OutputGenerationHookschunks.generator(write)outputhook函数执行期间WatchChangeHooksrollup.watch()在执行期间监控文件变化并重新执行构建的钩子函数调用形式异步:钩子也可能返回一个解析为相同类型值的Promise;否则,钩子被标记为同步。first:如果多个插件实现了同一个钩子函数,会依次执行,从头到尾。但是,如果其中一个返回值不为null或undefined,则后续插件将直接终止。Sequential:如果多个插件实现了同一个钩子函数,则顺序执行,按照插件的使用顺序从头到尾执行。如果是异步的,会等待前面的处理完成,然后再执行下一个插件。parallel:同上,但是如果一个插件是异步的,后续的插件不会等待,而是并行执行,也就是我们在rollup.rollup()阶段看到的。插件的常用hook和sequence先运行一下看看执行效果:pnpmdev:pnpmbuild:DevelopedhookHook类型说明Vite是否独占configasync,sequential在解析Vite配置之前调用。可以返回一个部分的配置对象,深度合并到现有的配置中,或者直接改变配置(如果默认合并没有达到预期的结果)是configResolvedasync,它在解析Vite配置后并行调用。使用此挂钩读取和存储最终解析的配置。当插件需要根据命令运行做不同的事情时,它也很有用。是optionsasync,sequential替换或操作传递给rollup.rollup的选项对象否configureServerasync,sequential是用于配置开发服务器的钩子。在连接应用程序中添加自定义中间件的最常见用例是buildStartasync,它在每次rollup.rollup构建时并行调用。当您需要访问传递给rollup.rollup()的选项时。没有transformIndexHtmlasync,顺序转换index.html的专用挂钩。是resolveIdasync,首先定义一个自定义解析器。例如,可以使用解析器来定位第三方依赖项。没有loadasync,首先定义一个自定义加载器。没有transformasync,sequential可以用来改造单个模块。没有buildEndasync,在并行服务器关闭时调用。汇总完成捆绑时调用的挂钩,但在生成或写入之前调用NoHook以构建输出挂钩类型描述outputOptionssync,sequential替换或操作传递给bundle.generate()或bundle.write()的输出选项对象。每次调用bundle.generate()或bundle.write()时,最初都会调用renderStartasync,parallel。augmentChunkHashsync,sequential用于增加单个chunk的hash。renderChunkasync,sequential用于转换单个chunk。generateBundleasync,sequential在bundle.generate()结束时或在将文件写入bundle.write()之前立即调用。transformIndexHtmlasync,用于转换index.html的顺序专用钩子。writeBundleasync,parallel仅在bundle.write()结束时调用,所有文件都已写入。closeBundleasync,parallel整个构建输出完成后调用插件的顺序Vite插件可以额外指定一个enforce属性(类似于webpackloader)来调整其应用顺序。enforce的值可以是前或后。解析后的插件会按照以下顺序排列:AliasUserpluginswithenforce:'pre'ViteCorepluginsUserpluginswithoutenforcevaluesViteBuildpluginsUserpluginswithenforce:'post'VitePostbuildplugins(minimize,清单,报告)
