javascript - 没有节点的Vue SSR

标签 javascript vue.js vuejs2

我正在重构一个大量使用 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/

相关文章:

javascript - Vuetify v-select 菜单覆盖文本字段输入

javascript - 在日历中为特定日期显示背景颜色的问题,在除移动 Safari 之外的所有浏览器上工作正常

vue.js - vue-html 不以 html 实体格式打印

javascript - react Hook : new state value not reflecting in setInterval callback

JavaScript 文件以日语(或其他亚洲语言)显示

javascript - 如何使用Vue-Carousel在点击元素上滑动?

unit-testing - 未找到转换选项中的模块 <rootDir>/node_modules/vue-jest

javascript - 如何在 Vue.js 中设置 optgroup 选择标签?

javascript - JS defineProperty 和原型(prototype)

JavaScript 测验获得正确和错误答案不起作用