Vue history 资源路径处理问题

缘由

  • 使用Hash Mode开发的一套大系统,完全成型
  • 由于各种跳转的问题,nginx的转发会导致#后面的路径丢失
  • 想试试History Mode
  • 环境 Vue-Cli 早期版本,webpack 2.6

相关配置

基础配置

  • 将Vue Router mode设置为history,并将跳转路径中带#的hash路由改为history对应的方式
  • webpack-dev-middleware 不带dev-server相关内容,只处理内容的映射,需要配合connect-history-api-fallback来做,默认给了一个默认的映射,但多级路由页面刷新还是会出现404

historyApiFallback日志

  • 配置connect-history-api-fallback

    // handle fallback for HTML5 history http
    app.use(require('connect-history-api-fallback')({
        verbose:true  //开启日志信息
    }))
    

本地路由404

  • 即使配置了这样的情况,还是会出现路由点击跳转好使,刷新页面404的情况,原因是刷新页面的地址被proxyTable匹配到了,找去了服务端(因为ProxyMiddlewareconnect-history-api-fallback中间件前面),没有走Fallback,解决办法是把所有服务相关的转发都加上api后缀或者使用connect-history-api-fallbackrewrites配置来做,前提是中间件的加载位置要在代理中间件前面。

本地图片404

  • 原有图片是直接在Vue组件里面利用相对路径写的,对于history模式来说,总会根据当前路径加上莫须有的前缀,这里直接将所有图片路径写上绝对路径就好了 /static/xxx

Web Server 路由404

  • 将打包后的内容部署到Web Server根目录,刷新页面路由会出现404,根据Vue Router官网文档配置 Web Server即可解决相关问题,比如nginx 配置,就会再找不到的情况下转到 index.html 通过router 解析路由

    location / {
      try_files $uri $uri/ /index.html;
    }
    
  • 然而,更多时候我们的应用不是部署在根目录的,而是在某个路径下比如 app-test,这个时候最好的方式是我们引用的资源路径都跟着走相对路径,打包出来自带光环,但看看前面图片路径的情况则不尽然。这个时候我们加载相关页面各种图片资源404,刷新页面路由会报500,上面的nginx转发规则已经不适用了。

Web Server 路由500

  • 上面官方文档里面的nginx配置已经不适合带路径目录的项目了,需要干掉。

应用增加base /app-test/

  • 路由首先加上一个base ,这样路由跳转的时候才不会越界

    export default new Router({
        mode:'history',
        base:'/app-test/',
        routes
    })
    
  • build.assetsPublicPath 值改为 /app-test/,这样打包路径相关的资源会加上这个前缀

  • dev.assetsPublicPath 值改为 /app-test/,这样本地dev server 路径能跟服务端访问一致

  • 配置本地Server 转发

// handle fallback for HTML5 history http
app.use(require('connect-history-api-fallback')({
   verbose:true,
   index:'/app-test/index.html',
}))
  • Vue组件模板中使用@/../static/images/xxx.png引用图片, 其中 @src的别名 参考 vue-loader

  • Vue组件中SCSS style 使用~/../static/images/xxx.png引用图片,其中~使后面的解析为模块路径, ~@/代表src参考 sass-loader 或者 css-loader 或者 vue cli

  • 在 js 中使用的话,按相对于src的路径写,import或者require都ok,

  • 对应nginx配置需要改为

    location /app-test {
      try_files $uri $uri/ /app-test/index.html;
    }
    
  • 实例代码在 这 github

相对路径适配问题

  • 上面增加base的情况适用于固定的部署方式,换个路径需要改代码重新打包,我们希望有一种方式自动适配路径,改到什么路径改改ng配置就行,代码不用动

  • 首先修改config/index.js中的路径为相对路径

    @@ -9,7 +9,7 @@ module.exports = {
     
         // Paths
         assetsSubDirectory: 'static',
    -    assetsPublicPath: '/app-test/',
    +    assetsPublicPath: './',
         proxyTable: {},
     
         // Various Dev Server settings
    @@ -45,12 +45,12 @@ module.exports = {
     
       build: {
         // Template for index.html
    -    index: path.resolve(__dirname, '../app-test/index.html'),
    +    index: path.resolve(__dirname, '../dist/index.html'),
     
         // Paths
    -    assetsRoot: path.resolve(__dirname, '../app-test'),
    +    assetsRoot: path.resolve(__dirname, '../dist'),
         assetsSubDirectory: 'static',
    -    assetsPublicPath: '/app-test/',
    +    assetsPublicPath: './',
    
    
  • 然后修改build/utils.js调整css 抽取的路径

           return ExtractTextPlugin.extract({
             use: loaders,
              fallback: 'vue-style-loader'
             fallback: 'vue-style-loader',
    +        publicPath:'../../'
           })
    
    
  • 最后调整下src/router/index.js动态获取路由,这里面加了个标识,是为了解决目录名和路由名分不开的问题,比如/path/to/dir/dist/path/to/router, 就用中间这个dist来区分出那部分是部署的目录名哪部分是路由路径,这个也有局限,比如咱们的/output/output/就尴尬了

    +const identifier = 'dist/'
    +const getBasePath = () => {
    +  const path = location.pathname
    +  return path.substr(0, path.lastIndexOf(identifier) + identifier.length)
    +}
    +
     export default new Router({
       mode: 'history',
    -  base: '/app-test/',
    +  base: getBasePath(),
    
    

参考资料

  • Vue history模式下配置相对路径

你可能感兴趣的:(Vue)