Apollo-link-rest: "@ rest" التوجيه لا يعمل في بيئة SSR

تم إنشاؤها على ٧ يناير ٢٠١٩  ·  9تعليقات  ·  مصدر: apollographql/apollo-link-rest

مرحبا!

لدي استعلام @rest graphql يعمل بشكل مثالي في التطوير / المتصفح ، ولكن عندما أقوم بتشغيل نفس الكود على الخادم (SSR) ، فإنه يفشل مع ظهور رسالة خطأ مشفرة طويلة.

(إذا قمت بتعطيل التوجيه @rest ، فإن كل شيء آخر يعمل بشكل لا تشوبه شائبة ، سواء في المتصفح أو في SSR).

تتبع المكدس:

(node:26034) UnhandledPromiseRejectionWarning: Error: Network error: current.forEach is not a function
    at new ApolloError (.../demo-component/node_modules/src/errors/ApolloError.ts:56:5)
    at .../demo-component/node_modules/src/core/QueryManager.ts:512:31
    at .../demo-component/node_modules/src/core/QueryManager.ts:1046:11
    at Array.forEach (<anonymous>)
    at .../demo-component/node_modules/src/core/QueryManager.ts:1045:10
    at Map.forEach (<anonymous>)
    at QueryManager.broadcastQueries (.../demo-component/node_modules/src/core/QueryManager.ts:1039:18)
    at .../demo-component/node_modules/src/core/QueryManager.ts:411:18
(node:26034) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
(node:26034) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

من فضلك النصيحة :/

التعليق الأكثر فائدة

أدت إضافة هذا في ملف التمهيد الخاص بي إلى حل جميع مشاكلي: د

if (global.Headers == null) {
    const fetch = require('node-fetch');
    global.Headers = fetch.Headers;
}

لاحظ باستخدام node-fetch بدلاً من fetch-headers حل المشكلة!

ال 9 كومينتر

مزيد من البحث ، أحاول فقط تنفيذ الاستعلام في NodeJS ، دون القلق بشأن SSR وما إلى ذلك ،

ويكون لديك هذا الرمز:

            client
                .query({query: Site, variables: {domain: "demo.example.com"}})
                .then(
                    () => console.log("Fullfilled"),
                    ({graphQLErrors, networkError, message, extraInfo}) =>
                        console.error("Rejected", graphQLErrors, networkError, message,extraInfo)
                )

بهذه النتيجة:

Rejected [] TypeError: current.forEach is not a function
    at /home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:671:13
    at Array.reduce (<anonymous>)
    at concatHeadersMergePolicy (/home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:664:23)
    at RestLink.request (/home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:1235:21)
    at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:76:19)
    at /home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:78:26
    at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/src/ApolloClient.ts:139:16)
    at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:76:19)
    at /home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:78:26
    at DedupLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link-dedup/src/dedupLink.ts:39:30) Network error: current.forEach is not a function undefined

restLink.ts:671 هو هذا الجزء من الكود:

export const concatHeadersMergePolicy: RestLink.HeadersMergePolicy = (
  ...headerGroups: Headers[]
): Headers => {
  return headerGroups.reduce((accumulator, current) => {
    if (!current) {
      return accumulator;
    }
    if (!current.forEach) {
      current = normalizeHeaders(current);
    }
    current.forEach((value, key) => {    // <-- This line here
      accumulator.append(key, value);
    });

    return accumulator;
  }, new Headers());
};

https://github.com/apollographql/apollo-link-rest/blob/master/src/restLink.ts#L671

أيضًا ، إذا قمت باستبدال forEach الذي فشل في ذلك:

    Object.keys(current).forEach(key => {
      accumulator.append(key, current[key])
    })

كل شيء يعمل من جديد ...

التحدي ، أنا لا أفهم الغرض من الأسطر أعلاه:

    if (!current.forEach) {
      current = normalizeHeaders(current);
    }

نظرًا لأن هذا سيفشل دائمًا ، ودائمًا ما يتم تنفيذ normalizeHeaders() ؟

سأخرج على أحد الأطراف هنا وأعتقد أن Node تنزعج من استخدام new Headers() . مثيل الرؤوس الجديد يحتوي على طريقة forEach في النموذج الأولي. إذا كان الكائن الموفر إلى تقليل يفتقد إلى طريقة forEach ، فإننا ننفذ normalizeHeaders . يحدد هذا ما إذا كان المتغير مثيلاً للرؤوس. إذا لم يكن الأمر كذلك ، فسيؤدي ذلك إلى إنشاء مجموعة جديدة من الرؤوس ، مرة أخرى ، باستخدام new Headers() ، مما يتسبب في حدوث المشكلة التي تراها هنا.

يعمل المثال Object.keys(current).forEach() الخاص بك لأنه نجح في تحويل كائن عادي إلى مصفوفة ، مما يسمح لك باستدعاء .forEach() عليه.

الخطوة التالية هي تصحيح الأخطاء ... ما هي نتيجة normalizeHeaders() في تطبيق SSR الخاص بك؟ ألقِ نظرة على ما ينتج عنه وأعتقد أنك ستجد أنه كائن عادي ، وليس مثيلًا للرؤوس.

على حد علمي ، لا أعتقد أنه قد تم اختبار SSR بالكامل (انظر # 155) ولكن من المحتمل أن يلقي fbartho مزيدًا من الضوء على هذا الأمر.

SSR ليست ميزة تم اختبارها أو دعمها بشكل مباشر في الوقت الحالي. الأساس المنطقي: إذا كان لديك SSR ، فيمكنك نشر خادم Apollo GraphQL الخاص بك ، ولا تحتاج إلى ارتباط-راحة

لكن بعض الناس اكتشفوا ذلك. وأنا لا أعترض على العلاقات العامة التي تعمل على تحسين حالة العالم هناك. يبدو لي أننا ربما نحتاج فقط إلى برنامج تعليمي لـ SSR.

بالإضافة إلى ذلك ، من الشائع نسبيًا أن تحتاج إلى تعبئة الرؤوس اعتمادًا على بيئة وقت التشغيل. هل حاولت حتى الان؟ @ ريتشارد87

استجابة @ tombarton صحيحة: الغرض من هذا الرمز هو تحويل تجزئات الرأس إلى فئة الرؤوس المناسبة.

أهلا بكم!

شكرا للاهتمام لمشكلتي ؛)

الجزء السفلي من index.js الخاص بي هو هذا:

if (global.Headers == null) {
    global.Headers = require("fetch-headers");
}

// Set up babel to do its thing... env for the latest toys, react-app for CRA
// Notice three plugins: the first two allow us to use import rather than require, the third is for code splitting
// Polyfill is required for Babel 7, polyfill includes a custom regenerator runtime and core-js
require('@babel/polyfill');
require('@babel/register')({
    ignore: [/\/(build|node_modules)\//],
    presets: ['@babel/preset-env', '@babel/preset-react'],
    plugins: [
        '@babel/plugin-syntax-dynamic-import',
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-transform-instanceof',
    ]
});

// Now that the nonsense is over... load up the server entry point
require('./server');

لذلك أنا متأكد من أن لديّ Header polyfill (أيضًا بدون global.Headers حصلت على مجموعة من المشكلات الأخرى) ...

لدي بالفعل خادم GraphQL يعمل بشكل متكامل تمامًا في تطبيق PHP الخاص بي (API-Platform + https://webonyx.github.io/graphql-php/) لذلك لا أريد تثبيت خادم Apollo GraphQL إضافي ، أريد فقط لتحميل تطبيق React بشكل أسرع: د

أجد صعوبة في تصحيح أخطاء restLink.ts ، لكنني وضعت القليل من الاستراتيجيات console.log ولكن يبدو أن current _ يبدو ككائن خطة ، لكن console.log قد يفوتني بعض المعلومات ...

تعديل...

export const concatHeadersMergePolicy: RestLink.HeadersMergePolicy = (
  ...headerGroups: Headers[]
): Headers => {
  return headerGroups.reduce((accumulator, current) => {
    if (!current) {
      return accumulator;
    }

    console.log(current.constructor.name)
    if (!current.forEach) {
      current = normalizeHeaders(current);
    }
    console.log(current.constructor.name)

    Object.keys(current).forEach(key => {
      accumulator.append(key, current[key])
    })

    return accumulator;
  }, new Headers());
};

يطبع "رأس" مرتين ...

console.log(current.forEach) يطبع غير محدد بغض النظر عن أي شيء ، يبدو أن متعدد تعبئة الرؤوس الخاص بي لا يحتوي على خاصية forEach ؟

يخبرني PHPStorm أن لدى headers طريقة forEach ، لكن عند تشغيل هذا الرمز في العقدة أحصل على headers.forEach is not a function :

const Headers = require("fetch-headers");
const headers = new Headers();

console.log(headers)
console.log(headers.forEach)
console.log(!headers.forEach)

headers.forEach(h => console.log(h))

انتاج:

node /home/richard/Projects/demo-component/src/test.js 
Headers {}
undefined
true
/home/richard/Projects/demo-component/src/test.js:10
headers.forEach(h => console.log(h))
        ^

TypeError: headers.forEach is not a function
    at Object.<anonymous> (/home/richard/Projects/demo-component/src/test.js:10:9)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
    at startup (internal/bootstrap/node.js:285:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)

أدت إضافة هذا في ملف التمهيد الخاص بي إلى حل جميع مشاكلي: د

if (global.Headers == null) {
    const fetch = require('node-fetch');
    global.Headers = fetch.Headers;
}

لاحظ باستخدام node-fetch بدلاً من fetch-headers حل المشكلة!

يجب إضافة هذا إلى مستندات Apollo-link-rest. إلى أي ملف يجب أن أرفع مستوى العلاقات العامة؟ https://github.com/apollographql/apollo-link-rest/blob/master/README.md ، https://github.com/apollographql/apollo-link-rest/blob/master/docs/rest.md أو https://github.com/apollographql/apollo-link/blob/master/docs/source/links/rest.md ؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات