本文介绍了如何在开发阶段将vite应用于vue2。x工程,从而提高研发的开发体验与效率。主要涉及如何兼容process变量,如何处理nodesass与dartsass冲突,以及路径别名的兼容处理等。通过这篇文章可以为读者在vite接入过程中遇到的问题提供一些解决方案,并帮助读者理清vue工程接入vite的具体思路。本文主要从整体介绍了新版会员徽章系统的设计方案以及未来规划,主要描述了等级模型的设计思路,读者可以通过本文对徽章系统的核心功能有初步的了解。01前言 随着H5项目迭代,项目的启动时长在慢慢增长,目前H5的首次启动时长约为1分钟;且文件的更新也可能触发大范围的依赖重新打包。vite、snowpack等bundless类型的打包工具的出现就是为了解决这个问题。本文将结合实际项目(京东快递H5)实现vite打包工具的无痛接入。由于目前未考虑在正式环境中使用vite进行构建,因此接入过程中需要考虑与现有打包方式的兼容问题。02徽章产品体系 首先解决vite需要的项目依赖,主要需要添加的项目依赖如下列出:vitevitepluginvue2:官方提供的vite插件,用于兼容vue2打包vitejspluginlegacy:用于配置需要适配的低版本浏览器vitepluginhtml:2。0。7:用于在模板文件中注入代码,注意版本高版本可能需要更改vuetemplatecompiler:vue单文件组件编译插件,要跟vue版本一致rolluppluginbabel:babel相关配置sass:css预处理语言所需基础库03模板文件index。html 1。相比vuecli构建的项目,模板文件的位置需要更改,为了同时兼容vuecli打包与vite打包,因此需要在根目录下新增index。html。 2。模板文件需要主动导入项目入口文件main。jsts【HTMLXML】04项目启动问题 1。vue中deep方式覆盖深层组件样式的方式不可用,需要替换为:: 2。所有的单文件组件导入必须包含。vue扩展; 3。style中通过~方式书写的路径需要额外的通过resolve。alias设置路径别名。【Javascript】:resolve(dirname,src) 4。提示global不存在,需要做兼容处理,通过模板文件(index。html)在全局添加global,当然也可以通过vite的插件(vitepluginglobalpolyfill)实现global变量的兼容,使用方式可参考源代码库说明。【HTMLXML】 5。运行时提示process不存在,vite中已经不通过process获取自定义的变量,需要使用import。meta,但是考虑到vite仅用于开发阶段,不应对项目进行破坏性兼容,因此考虑在全局自定义process。vite通过define配置自定义全局变量。【Javascript】define:{单独使用这种方式并不能在运行时获取env中设置的变量,process。env:process。env,} 通过实现简单的命令行工具来根据当前运行环境读取配置文件来对process进行数据的补充:【Javascript】env类型文件读取constdotenvrequire(dotenv)扩展processconst{expand}require(dotenvexpand)命令行参数拆分constminimistrequire(minimist);获取环境变量functionloadEnv(mode){constbasePathresolve(dirname,。env{mode?。{mode}:})constlocalPath{basePath}。localconstloadenvPath{根据当前命令行mode读取env中的参数配置constenvdotenv。config({path:envPath,debug:process。env。DEBUG})扩展processexpand(env)}load(localPath)load(basePath)}获取命令行中的参数constparmasminimist(process。argv。slice(2))目前只考虑modeloadEnv(parmas。mode)。。。exportdefaultdefineConfig({define:{process。env:process。env,}) 6。rollup中不支持动态require打包编译,而由于H5中多平台sdk冲突问题,目前必须通过动态导入的方式避免api冲突,因此会导致浏览器报错。解决方案在模板文件中对sdkAPI做兼容处理,防止报错。 另外有其它兼容思路,如通过import替换require,但是import为异步导入,需要配合顶层await方式才能比较优雅的实现sdk的动态导入,但是vuecli中目前没有通过配置实现顶层await的兼容。【HTMLXML】 7。jdpandoramobile(京东物流内部组件库)组件兼容问题,组件库默认导出方式与vite打包不兼容(具体原因可以参考viteissue),解决方案是通过路径别名将jdpandoramobile路径指定为commonjs包,或者可以通过vite中resolve。mainFields配置调整包搜索的优先级顺序来解决。【Javascript】resolve:{alias:{jdpandoramobile:resolve(dirname,nodemodulesjdpandoramobiledistpandoramobile。js),},mainFields:〔main,module,jsnext:main,jsnext〕} a。jdpandoramobile组件库样式文件导入不生效,解决方案有两种,一种是通过配置css预处理插件配置(preprocessorOptions)将组件库样式添加为额外的全局样式,但是这种方案可能存在样式优先级的问题;第二种是方案是通过vite插件vitepluginstyleimport,实现样式的按需导入。具体配置如下:【Javascript】import{createStyleImportPlugin}fromvitepluginstyleimportcreateStyleImportPlugin({libs:〔{libraryName:jdpandoramobile,esModule:true,resolveStyle:(name){returnjdpandoramobileescomponents{name}styleindex。css},}〕}),css:{preprocessorOptions:{scss:{additionalData:import{resolve(dirname,nodemodulesjdpandoramobiledistpandoramobile。css)};}}}, 8。sassloader中nodesass与sass兼容问题(与内部组件库pandora相关),vite中依赖sass(dartsass),而原项目中依赖nodesass。当两个依赖包同时存在时,由于vuecliservice(v3。8。4)中设置了sassloader优先依赖sass(dartsass),从而导致nodesass依赖被屏蔽,在通过原有的webpack方式进行打包时会由于pandora组件库与sass(dartsass)不兼容导致打包失败。解决方案是通过调整vue。config配置,将sassloader中对nodesass的依赖优先级提高,以防止安装sass后通过vuecli打包报错。【Javascript】vuecli3。8。4defaultSassLoaderOptions。implementationrequire(sass)调整vue。configcss:{。。。loaderOptions:{。。。sassloader优先使用sass,pandorasass兼容有问题implementation:require(nodesass),}} 05代码方面调整 常量的导入导出在文件之间存在循环依赖报错,需将常量统一导出处理。06总结 两种项目启动结果对比如下图: 图1vite启动H5工程 图2vuecli启动H5工程 1。就结果来说vite在项目启动上确实速度很快,但是由于运行时打包的方式,首次页面交互体验卡顿明显; 2。sdk兼容仍有待优化。【Javascript】import{defineConfig,ViteDevServer,PluginOption,createServer}fromviteimportlegacyfromvitejspluginlegacyimport{getBabelOutputPlugin}fromrolluppluginbabelimporthtmlfromvitepluginhtmlimport{createVuePlugin}fromvitepluginvue2import{createStyleImportPlugin}fromvitepluginstyleimportimport{envSwitchPlugin}import{globalPolyfill}fromvitepluginglobalpolyfillimport{green}frompicocolorsconstdotenvrequire(dotenv)constminimistrequire(minimist);const{resolve}require(path)获取环境变量functionloadEnv(mode){constbasePathresolve(dirname,。env{mode?。{mode}:})constlocalPath{basePath}。localconstloadenvPath{constenvdotenv。config({path:envPath,debug:process。env。DEBUG})process。envObject。assign({。。。process。env},env。parsed)}load(localPath)load(basePath)}constparmasminimist(process。argv。slice(2))loadEnv(parmas。mode)exportinterfacePluginConfig{envKey?:string,strGetter?:()string}https:vitejs。devconfigexportdefaultdefineConfig({base:expressvite,publicDir:public,resolve:{alias:{:resolve(dirname,src),:resolve(dirname,src),https:github。comvitejsviteissues1724issuecomment767619642vite读取的文件跟esbuild读取的文件不一致,vite读取的是commonjs,但是esbuild找到了esm类型的文件认为不需要转换,所以导致导出没有做兼容jdpandoramobile:resolve(dirname,nodemodulesjdpandoramobiledistpandoramobile。js),},用于更改包搜索的优先级具体原理见源码resolvePackageEntry方法等待新版本有config。optimizeDeps?。needsInterop配置,替换为该方案mainFields:〔main,module,jsnext:main,jsnext〕},server:{host:xxx。jd。com,https:true,port:443,open:true,},optimizeDeps:{},plugins:〔本地开发通过页面按钮动态切换项目环境https:github。comPengBoUESTCvitepluginenvswitchenvSwitchPlugin({wsProtocol:vitehmr,envs:〔prepare,development,production〕,wsPath:wss:xxx。jd。comexpressvite,root:dirname,eventName:envcheck}),globalPolyfill(),createStyleImportPlugin({libs:〔{libraryName:jdpandoramobile,esModule:true,resolveStyle:(name){returnjdpandoramobileescomponents{name}styleindex。css},}〕}),createVuePlugin({}),legacy({targets:〔defaults,notIE11〕,}),getBabelOutputPlugin({configFile:resolve(dirname,babel。config。js),}),html({inject:{injectData:{title:京东快递,},},minify:true,}),〕,css:{preprocessorOptions:{scss:{additionalData:import{resolve(dirname,nodemodulesjdpandoramobiledistpandoramobile。css)};}}},build:{outDir:dist,target:es2015,minify:terser,rollupOptions:{plugins:〔〕,},},define:{process。env:process。env,}}) 作者:杨博