使用 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' }"
来引用路径名称,而不是直接引用路径,以防您更改路由路径。
我想要实现的是将 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()
函数
在 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' }"
来引用路径名称,而不是直接引用路径,以防您更改路由路径。