Quasar CLI with Vite - @quasar/app-vite
SSR配置

quasar.config.js

在这里可以配置一些SSR选项。 就像您希望客户端以SPA(单页应用程序-默认行为)或PWA(渐进式Web应用程序)接管一样。

return {
  // ...
  ssr: {
    ssrPwaHtmlFilename: 'offline.html', // 不要使用index.html作为名称!
                                        // 会搞乱SSR

    extendSSRWebserverConf (esbuildConf) {},

    // 添加/删除/更改
    // 生产生成的package.json的属性
    extendPackageJson (pkg) {
      // 直接更换pkg属性;
      // 不需要归还任何东西
    },

    pwa: false,
    
    /**
     * 手动序列化存储状态,
     * 并且作为window.__INITIAL_STATE__自己提供给客户端(通过一个<script>标签)。
     * (需要@quasar/app-vite v1.0.0-beta.14+)
     */
    manualStoreSerialization: false,

    /**
     * 手动注入存储状态到ssrContext.state中
     * (需要@quasar/app-app-vite v1.0.0-beta.14+)
     */
    manualStoreSsrContextInjection: false,

    /**
     * 手动处理存储水化,而不是让Quasar CLI做。
     * Pinia: store.state.value = window.__INITIAL_STATE__
     * Vuex: store.replaceState(window.__INITIAL_STATE__)
     */
    manualStoreHydration: false,

    /**
     * 手动调用$q.onSSRHydrated()而不是让Quasar CLI来做。
     * 这宣布了客户端的代码应该接管。
     */ 
    manualPostHydrationTrigger: false,

    prodPort: 3000, // 生产服务器应该使用的默认端口
                    // (如果在运行时指定了 process.env.PORT,就会被取代)

    middlewares: [
      'render' //把这个作为最后一个
    ]
  }
}

如果您决定使用PWA客户端接管(这是一个杀手组合),那么也会安装Quasar CLI PWA模式。 您可能还想查看Quasar PWA指南。 但最重要的是,请确保您阅读了使用PWA的SSR页。

如果你想篡改/src中UI的Vite配置:

// quasar.config.js
module.exports = function (ctx) {
  return {
    build: {
      extendViteConf (viteConf, { isClient, isServer }) {
        if (ctx.mode.ssr) {
          // do something with ViteConf
        }
      }
    }
  }
}

手动触发存储水化

默认情况下,Quasar CLI会在客户端对Vuex存储(如果你使用它)进行水化。

然而,如果你希望自己手动进行水化,你需要设置quasar.config.js > ssr > manualStoreHydration: true。然后你需要自己调用store.replaceState(window.__INITIAL_STATE__)。一个很好的例子是在启动文件中进行。

// some_boot_file
// 确保配置这个启动文件
// 只在客户端运行

export default ({ store }) => {
  // Pinia写法
  store.state.value = window.__INITIAL_STATE__

  // Vuex写法
  store.replaceState(window.__INITIAL_STATE__)
}

手动触发水化后

默认情况下,Quasar CLI会包装你的App组件,并在这个包装组件被安装时在客户端调用$q.onSSRHydrated()。这是由客户端接管的时刻。你不需要配置任何东西来实现这一目标。

然而,如果你想覆盖这一时刻的发生,你需要设置quasar.config.js > ssr > manualPostHydrationTrigger: true。不管你的原因是什么(非常自定义的用例),这是一个手动触发水化后的例子。

// App.vue - Composition API

import { onMounted } from 'vue'
import { useQuasar } from 'quasar'
export default {
  // ....
  setup () {
    // ...
    const $q = useQuasar()
    onMounted(() => {
      $q.onSSRHydrated()
    })
  }
}
// App.vue - Options API
export default {
  mounted () {
    this.$q.onSSRHydrated()
  }
}

Nodejs服务器

在Quasar项目中添加SSR模式意味着将创建一个新文件夹:/src-ssr,其中包含SSR特定文件:

.
└── src-ssr/
    ├── middlewares/  # SSR middleware files
    └── server.js     # SSR webserver

你可以自由编辑这些文件。这两个文件夹中的每一个都在自己的文档页面中详细说明(查看左侧菜单)。

注意几件事:

  1. 这些文件在Node上下文中运行(Babel不会编译它们),因此请仅使用Node版本支持的ES6功能。 (https://node.green/)

  2. 如果从node_modules导入任何内容,请确保在package.json>“dependencies”中指定了该包,而在“devDependencies”中未指定。

  3. /src-ssr/middlewares是通过单独的Esbuild配置构建的。你可以通过quasar.config.js扩展这些文件的Esbuild配置。

return {
  // ...
  ssr: {
    // ...
    extendSSRWebserverConf (esbuildConf) {
      // tamper with esbuildConf here
    },
  }
}
  1. /src-ssr/server.js文件在SSR Webserver页面有详细介绍。如果你需要支持无服务器功能,请特别阅读它。

帮助SEO

开发SSR而不是SPA的主要原因之一是要注意SEO。 通过使用Quasar Meta插件管理搜索引擎所需的动态html标记,可以大大改善SEO。

启动文件

在SSR模式下运行时,您的应用程序代码必须是同构的或“通用的”,这意味着它必须同时在Node上下文和浏览器中运行。 这也适用于您的启动文件

但是,在某些情况下,您只希望某些引导文件仅在服务器上或仅在客户端上运行。 您可以通过指定以下内容来实现:

// quasar.config.js
return {
  // ...
  boot: [
    'some-boot-file', // 在服务器和客户端上运行
    { path: 'some-other', server: false } // 此启动文件仅嵌入在客户端
    { path: 'third', client: false } // 该启动文件仅嵌入在服务器端
  ]
}

不过,只需确保您的应用程序是一致的。

当引导文件在服务器上运行时,您将可以访问默认导出功能上的另一个参数(称为ssrContext):

// 一些启动文件
export default ({ app, ..., ssrContext }) => {
  // 您可以将属性添加到ssrContext中,然后在/index.html中使用它们。
  // 示例-假设我们ssrContext.someProp ='some value',那么在index模板中我们可以引用它:
  // {{ someProp }}
}

当您在/index.html中添加此类引用(上例中用括号括起来的someProp)时,请确保告诉Quasar它仅对SSR构建有效:

<!-- /index.html -->
<% if (ctx.mode.ssr) { %>{{ someProp }} <% } %>