Quasar CLI with Webpack - @quasar/app-webpack
SSR配置

quasar.config.js

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

return {
  // ...
  ssr: {
    pwa: true/false, // PWA应该接管(默认值:false)还是SPA?

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

    /**
     * 手动注入存储状态到ssrContext.state中
     * (需要@quasar/app-webpack v3.5+)
     */
    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,就会被取代)

    maxAge: 1000 * 60 * 60 * 24 * 30,
        // 告诉浏览器,服务器上的文件何时应该从缓存中过期
        // (默认值,单位:毫秒)
        // 只有在使用server.static()时才有效。

    // SSR中间件文件的列表(src-ssr/middlewares/*)。顺序很重要。
    middlewares: [
      // ...
      'render' // 不应缺失,而且应在列表的最后。
    ],

    // 可选; 添加/删除/更改生产版本
    // 生成的package.json的属性
    extendPackageJson (pkg) {
      // 直接更改pkg的属性;
      // 不需要返回任何东西
    },

    // 可选的;
    // 仅处理Webserver webpack配置
    // 其中包括SSR中间件
    extendWebpackWebserver (cfg) {
      // 直接更改cfg的属性;
      // 无需返回任何内容
    },

    // 可选的;  等同于 extendWebpack() ,但使用 webpack-chain;
    // 仅处理Webserver webpack配置
    // 其中包括SSR中间件
    chainWebpackWebserver (chain) {
      // chain是Webpack配置的
      // webpack-chain实例
    }
  }
}

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

在构建时,extendWebpack()chainWebpack()将再接收一个参数(对象),该参数当前包含isServer或isClient布尔属性,因为将有两个Webpack构建(一个用于服务器端,另一个用于客户端)。

// quasar.config.js
build: {
  extendWebpack(cfg, { isServer, isClient }) { ... }
}

如果您需要更多信息,请参阅此页面,该页面详细介绍了在quasar.config.js文件中的Webpack处理

手动触发存储水化

默认情况下,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
    ├── directives/   # SSR transformations for Vue directives
    └── production-export.js # SSR webserver production export

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

注意几件事:

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

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

  3. /src-ssr/middlewares是通过一个单独的Webpack配置构建的。**当Quasar App CLI构建你的应用程序时,你会看到它被标记为 “Webserver”。**你可以通过quasar.config.js连锁/扩展这些文件的Webpack配置。

return {
  // ...
  ssr: {
    // ...

    // 可选的; 仅用于生产环境下调用的Web服务器部分
    // 的webpack config对象(/src-ssr/)
    //(不适用于开发环境)
    extendWebpackWebserver (cfg) {
      // 直接更改cfg的属性;
      // 无需返回任何内容
    },

    // 可选的; 等效于extendWebpack(),但使用webpack-chain;
    // 仅用于生产环境下调用的Web服务器部分(/src-ssr/)
    //(不适用于开发环境)
    chainWebpackWebserver (chain) {
      // chain是Webpack配置的
      // webpack-chain实例
    }
  }
}
  1. /src-ssr/production-export.js文件详见SSR生产输出页面。如果你需要支持无服务器功能,请特别阅读它。

帮助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中,然后在src/index.template.html中使用它们。
  // 示例-假设我们ssrContext.someProp ='some value',那么在index模板中我们可以引用它:
  // {{ someProp }}
}

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

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