当前位置: 首页 > Web前端 > vue.js

Vue项目中publicPath的二三事

时间:2023-04-01 12:46:57 vue.js

简介在Vue项目中,vue.config.js是项目中用于启动和打包的配置文件。其中一个重要参数是publicPath。这个配置的作用是开发阶段和生产阶段,为静态资源配置一个统一的资源标识。然而,有时相对路径、绝对路径和次要路径会愚蠢地不清楚。否则,应用在开发阶段运行良好,但一旦到了生产环境,要么黑屏,要么图片资源丢失。简而言之,存在各种问题。今天就来好好一战,看看在各种场景下如何配置这个参数。绝对和相对的区别在说配置之前,先明确两个概念:绝对路径'/'和相对路径'./'。这两个概念之间的区别在于使用哪个目录作为起点。可以这么理解,绝对路径就是永远不会出错的路径,总是以一个固定的目录为起点。相对路径容易出错,可以以任意目录节点为起点。在网站的访问中,可以认为如果静态资源使用的是绝对路径,那么他总是以当前网站作为访问的根节点。在vue.config.js中,publicPath可以配置为绝对路径或相对路径。绝对路径:publicPath:'/',//或者有二级路径的网站,比如访问地址是http://my-app.com/sub/publicPath:'/sub/'相对路径:publicPath:'./',//orpublicPath:'.',//orpublicPath:''以上三者是等价的,都是相对路径。关于publicPath,先用@vue/cli的脚手架生成一个vue项目。我们看看publicPath的默认配置是什么?以下代码均来自@vue/cli@5.0.8。生成的vue.config.js可以看到在生成的项目中,publicPath这个参数值是不存在的,那么默认值是多少呢?打开@vue/cli的源码,在packages/@vue/cli-service/lib/options.js文件下找到答案。可以看到脚手架默认给的publicPath的值为'/',也就是说@vue/cli默认使用绝对路径。关于router中的base参数,除了publicPath参数外,还有一个与其密切相关的参数,就是router中的base。打开vue-router的官方文档可以看到相应的解释。base是应用的基路径,即当前应用的所有路由地址都会自动与这个基路径拼接。一般用于部署了二级目录的网站。.router/index.js中base的默认值为process.env.BASE_URL,那么初始值是多少呢?继续查找@vue/cli的源码,找到答案目录在如下文件:packages/@vue/cli-service/lib/config/base.js这个文件就是@vue/cli的配置文件对于webpack,可以看到脚手架中的环境变量来自实用函数util/resolveClientEnv,然后调用webpack的插件DefinePlugin为这些环境变量生成最终可访问的常量。目录:packages/@vue/cli-service/lib/util/resolveClientEnv.js该文件是@vue/cli用来生成环境变量的工具函数。可以看到BASE_URL的值来自函数getBaseUrl,参数options是我们vue.config.js导出的json文件。另外可以看到脚手架中@vue/cli默认只能识别VUE_APP_、NODE_ENV、BASE_URL这三个环境变量。目录:packages/@vue/cli-service/lib/util/.js可以看到当publicPath设置为'auto'时,它的值为'',其他情况下这个值为我们配置的publicPath,那么基本上可以这么理解,实际项目开发中router中的publicPath和base参数应该取相同的值。这里将'auto'单独处理,以适配webpack,因为webpack的output.publicPath可以设置为'auto',有自己的处理逻辑。但是一旦使用了'auto'的值,在启动serve之后,auto会被认为是二级路径比如http://localhost:8080/auto/,所以@vue/cli这里必须强制为空。本期讨论地址:[https://github.com/vuejs/vue-...](https://github.com/vuejs/vue-...)webpack在publicPath上的文档:https://webpack.docschina.org/configuration/output/#outputpublicpath好了,了解了默认值之后,终于可以进入正题了,如何分别在绝对路径和相对路径下使用publicPath。publicPath:'/',使用绝对路径,即默认配置开发环境生产环境结论:使用默认配置,无论是开发阶段还是生产阶段,静态资源都会链接到'/',这样静态资源会以当前网站作为根节点,然后加载相应的静态资源。本地静态访问和这样打出来的dist/index.html是不能直接访问的,因为使用了绝对路径。直接用浏览器打开,会直接到根目录的盘符作为访问的根路径,导致静态资源加载失败。当然,生产包通常是使用服务端部署的,因为大部分应用还是和后台界面交互,只有服务端启动后才能正常访问。那么有没有什么方法可以不用服务器就可以开始访问呢?这个时候,你可能需要的是一个相对路径。publicPath:'./',使用相对路径开发环境生产环境结论:使用相对路径,可以看到访问静态资源只比绝对路径少了'/'。这样做的好处是可以将当前应用部署到任意目录,而不用担心静态资源丢失。比如本地访问。可以看到用相对路径打包后,可以在本地直接访问index.html,静态资源全部加载成功,页面上显示了一些东西,但是首页的内容丢失了。这其实是因为我们使用的路由模式是history。虽然资源加载没有问题,但是由于地址栏路径和前端设置的访问路由不一致导致前端路由无法正确加载,导致页面无法正确显示。将路由更改为散列模式。可以看到修改路由为hash方式并重新打包后,index.html即使在本地也能顺利访问,路由切换也没有问题。publicPath:'/sub/',在开发环境和生产环境使用二级路径(也是绝对路径)结论:可以看到,二级路径其实是绝对路径,只是'/sub/被拼接了在所有静态资源之前'.该配置可以将不同的项目部署在同一个域下,依靠二级路径实现逻辑划分。网站配置二级访问路径为什么要在前端加上相应的资源标识?使用绝对路径时,所谓的根路径其实就是从当前域名+端口号后面的位置开始。例如,以网址http://localhost:8080/test为例,如果前端配置的publicPath:'/'为默认值。那么加载前端静态资源的时候就会变成http://localhost:8080/js/xxxx...,因为当前网站的根目录在端口之后。导致在物理层面无法再访问静态资源,导致资源加载失败、白屏等。因此,当网站设置二级目录时,前端此时需要注意,并且有不同的解决方案来防止白屏。设置一个二级目录的绝对路径,publicPath:'/test/',这样打包的静态资源可以和当前网站配置保持一致,避免资源加载失败。设置相对路径,publicPath:'./'。但是这样的话,此时如果使用history模式的路由配置,由于网站添加了二级目录,前端路由地址会匹配失败,所以还需要设置router的base为'/test/'来匹配网站目录的二级目录保持不变。或者直接采用hash路由方式,这样base参数的配置可以忽略,更省心。vue-cli官方文档对publicPath字段进行了说明。该值在开发环境中同样生效。如果你想在根路径设置开发服务器,你可以使用一个条件值:module.exports={publicPath:process.env.NODE_ENV==='production'?'/production-sub-path/':'/'}官方文档写的很清楚,为了方便记忆总结了以下几种配置方式:傻瓜模式:路由采用hash方式,publicPath采用相对路径'。/'模式。这种组合配置操作简单,可以部署到任意路径,并且可以支持二级目录,更省心。即使直接访问打包后的index.html,也能看到效果。应用场景可能是:一个不需要和后台界面交互,支持本地静态展示的纯前端应用。它只是部署到githubgh-page分支的纯前端展示应用。比如使用vue开发的h5项目,然后使用hbuilder打包hybridapp。部署在具有辅助路径的网站上。高级模式:路由采用history模式,publicPath采用绝对路径'/'模式。该模式需要服务器部署前端资源。同时还需要在服务器上配置404重定向到index.html。升级方式:路由采用history方式,publicPath采用'/sub/'副路径,对应的routerbase参数也要设置为'/sub/'(通常是默认的process.env.BASE_URL脚手架就足够了)。这种模式是指当多个项目同时部署在同一个域名和端口下时,使用不同的二级路径对项目进行逻辑划分。服务部署方式同高级模式。