我正在重构一个大量使用 vue 组件的网络应用程序。
目前,vue 组件是使用 twig 模板语言在服务器端呈现的。组件作为静态 html 呈现给页面......没有使用 webpack 或 vue cli。数据是动态的...(产品目录)。
您可以将每个页面视为呈现为静态 html 的“单页应用程序”。模板是 twig 和 vue 的混合体。
长期目标是将后端移至 Phoenix,因此我试图使组件尽可能可移植,因此它们不会与 twig 紧密耦合。
我想在重构中使用 vue cli、vuex、webpack 等。我想在服务器端渲染组件...但是,我无法使用 vue SSR,因为我们无法在服务器上运行节点。
我是否可以构建我的组件(使用 webpack 等),将它们上传到服务器 - 并让它们在服务器端预填充数据?
我有一个想法(但无法开始工作)是尝试将 vuex 存储放在我编译的 vue 应用程序之外......作为一个美化的字符串。然后我可以将数据写入此(使用 Twig )并将应用程序嵌入到发送的 html 中。
它仍然会使用 twig - 但只用于填充 vuex 状态对象......其余的将作为 html 字符串发送......理论上,我认为这不应该杀死搜索引擎阅读页数?
最佳答案
好的....所以这是我设法做到的:
像往常一样使用 vue cli 和所有很酷的工具来构建 vue SPA
使用 https://github.com/SolarLiner/vue-cli-plugin-prerender-spa 通过 vue cli 轻松配置 prerender-spa-plugin。
在 store.js 中 - 设置你的状态....这需要类似于你的数据的形状。
例如:
const state = {
isLoading: false,
products: [
{
name: 'Product 10',
sku: '12345',
price: 300,
stock: 100
}
],
cart: {
}
}
此“应用”具有动态数据。所以我们需要用正确的数据更新状态客户端。通过 mounted
中的 Ajax 调用来执行此操作会很疯狂,因为我们将从服务器发送它,并可以访问服务器上的初始数据...
在你的 main.js 文件中,添加一个挂载的钩子(Hook):
new Vue({
store,
render: h => h(App),
mounted () {
const configElement = document.getElementById('config')
const config = JSON.parse(configElement && configElement.innerHTML)
const initialState = (config && config.initialState)
if (initialState) {
// Set our initial state here - this will overwrite the state
// in our store with the data we want
this.$store.commit('INIT_STATE', initialState)
}
// You'll need this for renderAfterDocumentEvent.
document.dispatchEvent(new Event('render-event'))
}
}).$mount('#app')
并在您的 store.mutations 中添加“INIT_STATE”突变。例如:
INIT_STATE (state, initialState) {
state.products = initialState
},
您可能想在挂载中使用一个action
- 但由于该操作不是异步的,我决定直接进行突变。
当你构建你的项目时——你最终会得到一个 index.html 文件。在 index.html 中,在 app.js 之上添加一个 JSON 脚本标签(我们这样做是因为我们不希望浏览器认为它是 JavaScript)。
使用您的服务器端模板将初始状态“丢弃”为 JSON 对象。例如
<script id="config" type="application/json">
{{get_my_initial_data_as_JSON()}}
</script>
<script src="/js/app.67487567.js"></script>
变成:
<script id="config" type="application/json">
{"initialState":[{"name":"Product 1","sku":"123","price":300,"stock":10},{"name":"Product 2","sku":"234","price":300,"stock":10},{"name":"Product 3","sku":"456","price":300,"stock":10},{"name":"Product 4","sku":"678","price":300,"stock":10}]}
</script>
<script src="/js/app.67487567.js"></script>
如果您查看 index.html 的源代码,您会看到您的 html 包含您在构建时存储的初始数据({name: product10}
等)
但是,商店会在挂载的 Hook 中自动更新为正确的数据。
我已经测试过,google 看到并爬取了挂载的数据。
好处:
以这种方式更新初始状态意味着不需要 Ajax 调用来获取初始数据...因此,交互时间和页面加载速度更快。
此方法将服务器端的硬接线 vue 模板删除到服务器端模板中。您不必使用两种模板语言(例如 vue 和 twig,或者混合使用 twig 来输出 vue)来复制您的模板。它从后端解开你的 vue 应用程序。
最大的好处是能够使用 Vue Cli 的工具和 Webpack - 由于这个服务器端汤,这在以前几乎不可能使用。
** 编辑 **
考虑一下 - 您可以进入/public/index.html 并在行上方插入 JSON 脚本标记
如果您在此处添加打算用于编写 JSON 的服务器端方法 - 例如:
<script id="config" type="application/json">
{{get_my_initial_data_as_JSON()}}
</script>
您没有任何要编辑的客户端文件 :) 您只需从您的服务器获取该文件 - 并让您的 get_my_initial_data_as_JSON()
准备好填充它。
关于javascript - 没有节点的Vue SSR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58319135/