vue.js 如何将Google Maps JS API与Inertia.js服务器端渲染结合使用?

5jdjgkvh  于 2023-11-21  发布在  Vue.js
关注(0)|答案(1)|浏览(147)

我正在尝试为使用Inertia和Laravel构建的Vue.js SPA设置服务器端渲染。每当我尝试加载包含Map的页面时,我都会从SSR服务器进程中获得如下错误:

[Vue warn]: Unhandled error during execution of setup function 
  at <Map errors= {} venues= [
  {
    name: 'Some Hall',
    lat: '45.492480',
    lng: '0.336327',
    address: '1 Interesting Street',
    url: 'http://localhost/venues/some-hall'
  },
**** Lots more prop data elements here ****
 }
] key=null >
TypeError: Loader is not a constructor
    at setup (file:///var/www/html/bootstrap/ssr/ssr.js:510:20)
    at _sfc_main$4.setup (file:///var/www/html/bootstrap/ssr/ssr.js:613:25)
    at callWithErrorHandling (/var/www/html/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:156:18)
    at setupStatefulComponent (/var/www/html/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7244:25)
    at setupComponent (/var/www/html/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7205:36)
    at renderComponentVNode (/var/www/html/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:614:15)
    at renderVNode (/var/www/html/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:743:14)
    at renderComponentSubTree (/var/www/html/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:698:7)
    at renderComponentVNode (/var/www/html/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:631:12)
    at renderVNode (/var/www/html/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:743:14)

字符串
该网站使用composer包laravel/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection)inertiajs/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection)。我的package.json看起来像这样:

{
    "private": true,
    "type": "module",
    "scripts": {
        "dev": "vite",
        "build": "vite build && vite build --ssr"
    },
    "devDependencies": {
        "axios": "^1.1.2",
        "laravel-vite-plugin": "^0.8.0",
        "vite": "^4.0.0"
    },
    "dependencies": {
        "@googlemaps/js-api-loader": "^1.16.2",
        "@inertiajs/vue3": "^1.0.12",
        "@vitejs/plugin-vue": "^4.4.0",
        "@vue/server-renderer": "^3.3.7",
        "bootstrap": "^5.3.2",
        "vue": "^3.3.6"
    }
}


我的resources/js/app.js看起来像这样:

import {createSSRApp, h} from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';

createInertiaApp({
    resolve: name => {
        const pages = import.meta.glob('./Pages/**/*.vue', { eager: true });
        return pages[`./Pages/${name}.vue`];
    },
    setup({ el, App, props, plugin }) {
        createSSRApp({ render: () => h(App, props) })
            .use(plugin)
            .mount(el);
    },
});


我的resources/js/ssr.js看起来像这样:

import { createInertiaApp } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import { renderToString } from '@vue/server-renderer'
import { createSSRApp, h } from 'vue'

createServer(page =>
    createInertiaApp({
        page,
        render: renderToString,
        resolve: name => {
            const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
            return pages[`./Pages/${name}.vue`]
        },
        setup({ App, props, plugin }) {
            return createSSRApp({
                render: () => h(App, props),
            }).use(plugin)
        },
    }),
)


到目前为止,我一直在寻找答案,这是否是一个CommonJS/ESM兼容性问题(尽管我并不完全理解这一点),所以在导入js-api-loader模块时,我尝试了以下两种方法:

// Initially this...

import { Loader } from "@googlemaps/js-api-loader";

// And also this...

import * as GMaps from '@googlemaps/js-api-loader'
const { Loader } = GMaps


据我所知,第二个选择是处理CJS模块,但我不认为Google模块使用CommonJS标准,据我所知。
在我的*.vue页面中,似乎导致错误的代码是:

const loader = new Loader({
    apiKey: env.google_maps_api_key,
    version: "weekly",
    libraries: ['places'],
});


真的很感激一些指导!

更新

我在报告错误的地方放了一些console.log()行:

const { Loader } = GMaps;
    const props = __props;
console.log(GMaps);
console.log(Loader);
    const loader = new Loader({
      apiKey: env.google_maps_api_key,
      version: "weekly",
      libraries: ["places"]
    });


输出为:

[Module: null prototype] {
  default: {
    LoaderStatus: {
      '0': 'INITIALIZED',
      '1': 'LOADING',
      '2': 'SUCCESS',
      '3': 'FAILURE',
      INITIALIZED: 0,
      LOADING: 1,
      SUCCESS: 2,
      FAILURE: 3
    },
    DEFAULT_ID: '__googleMapsScriptId',
    Loader: [Function: o]
  }
}
undefined

vdzxcuhz

vdzxcuhz1#

好吧,我现在已经解决了这个问题,但我真的不明白发生了什么。如果有人能提供一个更好的解释,在模块类型,导入,节点和浏览器方面,我很乐意改变接受的答案。
基本上,我的工作导入现在看起来像这样:

import * as GMaps from '@googlemaps/js-api-loader';
const { Loader } = GMaps.default ?? GMaps;

字符串
似乎在一个示例中(我想是浏览器?),模块被导入为包含模块导出属性的对象(即{ LoaderStatus: ..., DEFAULT_ID: ..., Loader: ... }),而在另一个示例中(我想是服务器上的节点),模块被导入 Package 在父对象的default属性(即{ default: { LoaderStatus: ..., DEFAULT_ID: ..., Loader: ... }})中。我不知道为什么。
上面的解决方案基本上使用??操作符首先尝试解构default属性,如果它存在,如果不存在,则返回到解构父对象本身。
这些链接帮助我走了这么远。

相关问题