使用 Webpacker 从 Rails 5 中的子路径服务 Vue.js 应用程序

Serve Vue.js app from a subpath in Rails 5 with Webpacker

我想要实现的是将 Vue 3 应用程序添加到现有的 Rails 应用程序中。因此,在加载路由 /spa/* 之前,我的应用程序将是一个典型的 Rails 应用程序。在那种情况下,Rails' 控制器将提供一个依赖于 Webpack 提供的 JS 的布局...

首先,我将路由 /spa/ 添加到我的 routes.rb 中,以便始终将其解析为控制器,该控制器提供使用 javascript_pack_tag

的正确布局

然后,我设法在我的 Rails 5.2 rails 应用程序中安装和设置了 Webpacker,它似乎工作正常,因为我已经构建了一个带有 Vue 路由器和一些简单应用程序的应用程序单击 link 时正确呈现的组件。嗯,差不多...

问题在于我在路径 /spa/ 而不是根目录 / 下提供 Vue 应用程序。当我加载 /spa/ URL 时,我的 header 组件(包含 links)被显示,但初始组件(Vue 路由器中的那个)直到我点击 Vue link。组件已呈现,但 URL 从 /spa/ 更改为 /q1。显然,如果我们重新加载浏览器,那条路由不是由 Vue“控制”的,而是由 Rails

我想要实现的是告诉 Webpack(er) 和 Vue 在任何 Vue 路由器 link.

之前添加 /spa/
<nav id="nav">
      <router-link to="/">Question 1</router-link>
      <router-link to="/q2">Question 2</router-link>
</nav>

我知道我可以将 /spa 硬编码到我正在使用的每个 link,但这感觉太脏了 :D

我的 Vue 路由器:

import { createWebHistory, createRouter } from "vue-router";
import Question1 from "@/vue/views/Question1.vue";
import Question2 from "@/vue/views/Question2.vue";
// import About from "@/views/About.vue";

const routes = [
  {
    path: "q1",
    name: "Question1",
    component: Question1,
  },
  {
    path: "q3",
    name: "Question2",
    component: Question2,
  },
  { 
    path: "", 
    redirect: { name: 'Question1' }
  }
];

const router = createRouter({
  history: createWebHistory(),
  // publicPath: '/spa',
  base: '/spa/',
  routes,
});

export default router;

根据 Vue 3 文档,通过将 base 参数添加到路由器配置中应该可以很容易地解决这个问题,但它不起作用:/ publicPath

也不起作用

我还在某个地方发现,使用 Webpack 和 Vue 可以通过将路径添加到 vue.config.js 来解决这个问题,但是使用 Webpacker gem 我不确定该怎么做。

问题是: 如何让我的 Vue 应用程序在调用路由 /spa/ 时得到服务,就好像 /spa/ 不存在一样?

最终编辑

跳转到@Excalibaard 的回答:)

就我而言,问题是我使用的 Vue 路由器 v4 与您在搜索路由器文档时通常看到的语法不同。

在路由器 v3 中,base: 是传递给 createRouter() 函数

的 object 的属性

在 v4 中,base 是给 createWebHistory("the-base-value")

的参数

所以,我的解决方案是

const router = createRouter({
  mode:history,
  history: createWebHistory( '/spa/' ),
  routes,
});

您正在使用 ~3.0 语法。

  • 在 vue-router 3.0 中,您可以通过 new Router 实例化一个路由器。您为新的 Router 实例提供 base option
  • 在 vue-router 4.0 中,您可以通过 createRouter 函数执行此操作。 routerOptions 不再接受 base 键; base 现在是 createHistory function 的可选参数。

试试这个:

const router = createRouter({
  history: createWebHistory('/spa/'),
  routes,
});

关于编辑您的 webpack 配置:

vue.config.js是配置Vue-CLI的文件。这与 webpacker gem 冲突,因为它们都有自己的方式来管理 webpack 和部署链。对于 webpacker,您应该通过在 config/webpack 文件夹中导入自定义规则并合并到默认配置来编辑 webpack 配置。


编辑:原始(不正确)答案

您必须删除路径开头的斜线。开头的斜杠告诉 vue-router 作为绝对路径处理。

https://router.vuejs.org/api/#route-object-properties

https://router.vuejs.org/guide/essentials/nested-routes.html

我还建议您在扩展时使用 :to="{ name:'Foo' }" 来引用路径名称,而不是直接引用路径,以防您更改路由路径。