Razzle: كيف يمكنني استكشاف أخطاء عرض الخادم وإصلاحها؟

تم إنشاؤها على ٥ فبراير ٢٠١٩  ·  9تعليقات  ·  مصدر: jaredpalmer/razzle

أهلا،

لقد لاحظنا مشكلة حيث إذا قمت بتسجيل الدخول إلى وحدة تحكم بحث Google ، وجلبت مثل Google ، فسيتم عرض موقع الويب كصفحة فارغة.

لقد أجريت بعض الأبحاث ، وقادني بعضها إلى هذا المقال:

https://medium.com/@gajus/react -application-see-a-blank-page-via-fetch-as-google-afb11dff8562

من المحتمل جدًا أن محرك البحث والجلب مثل google نفسه لا يتصرفان بنفس الطريقة ، وإلا فقدنا الترتيب الآن ، ومع ذلك أود حل هذه المشكلة ، لأنها ستبقي أي مالك موقع مستيقظًا.

لقد قمت بتنزيل phantomjs ، بافتراض أنه مماثل لجلب Google ، ومحاولة عرضه يُرجع عددًا من الأخطاء:

image

قد يكون حل هذه المشكلة بسيطًا مثل تغيير المتصفحات المستهدفة التي يتم تجميعها ، ولكن مجرد تثبيت babel / polyfil والاستيراد لا يعمل.

هل يمكن لأي شخص أن يوجهني في الاتجاه الصحيح هنا؟

stale

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

لذا فإن اقتراحي (وربما نحتاج إلى دليل استكشاف الأخطاء وإصلاحها في المستندات حول هذا الأمر) هو التعليق بقدر ما تستطيع من server.js ، client.js ، App.js ، وربما تتخطى جوانب حزمة الويب الخاصة بك (إذا كان لديك أي منها) لإعادة تطبيق Razzle إلى حالة تشبه "hello world". أود أيضًا أن أقترح نسخ قالب HTML الخاص بـ Razzle مرة أخرى إلى ملف server.js فقط للتأكد من تحميل جميع البرامج النصية بشكل صحيح خارج الصندوق. بمجرد تشغيله ، افتح Chrome dev tools وانتقل إلى علامة التبويب "الأداء" ، وحدد مربع الاختيار "لقطات الشاشة" ، ثم اضغط على أيقونة التحديث. انظر GIF أدناه.

kapture 2019-02-05 at 8 33 42

الهدف هو التأكد من عدم وجود إطار أبيض فارغ في منطقة الخط الزمني. بعد الحصول على عرض مناسب بدون ومضات ، يجب إعادة إضافة المزيد والمزيد من التعليمات البرمجية القديمة. خذ خطوات صغيرة. هذا من السهل جدًا إفساده إذا لم تكن حريصًا.

بالنسبة إلى حالتك المحددة ، سأبدأ بإزالة كل عناصر إدارة علامات Google ، وجميع CSS ، بالإضافة إلى أي تقسيم للرمز تقوم به. فقط احصل عليه للعرض واعمل بشكل عكسي. بعد ذلك ، احصل على عمل Redux. ثم أضف خوذة رد الفعل مرة أخرى ، وبعد ذلك ، بمجرد أن تعتقد أنك حصلت عليها بشكل صحيح ، تحقق مرة أخرى من خلال إجراء اختبار Lighthouse أيضًا (علامة التبويب Audits). قم بإلزام هذه الحالة بفرع جديد حتى تتمكن من العودة إليها في المستقبل. بعد ذلك ، أضف البرامج النصية للتحليلات مرة أخرى وتحقق من العرض مرة أخرى. أخيرًا ، حاول إضافة تقسيم الشفرة مرة أخرى.

ملاحظة: إذا احتفظت بـ css وقمت بالتحليل أعلاه باستخدام Razzle في وضع التطوير ، فقد تحصل على FOUC لأن Razzle لا يعالج أنماط .css على الخادم أثناء التطوير (فقط على العميل). وبالتالي ، لاختبار أنك تقوم بعمل SSR مناسب مع ترطيب النمط إذا كنت تستخدم ملفات .css ، يجب عليك إنشاء Razzle للإنتاج وتشغيل خادم الإنتاج محليًا. ومع ذلك ، إذا كنت تتحقق ببساطة من وجود HTML الخاص بك من الخادم ، فيمكنك تشغيل هذا في وضع التطوير.

ال 9 كومينتر

إذا كنت تجلب الصفحة فارغة ، فهذا يعني أنك كسرت نظام SSR أو نظام الترطيب. لا يعاني Razzle مما وصفته خارج الصندوق ، في الواقع ، يتم استخدامه على المواقع التي تركز على تحسين محركات البحث مثل BBC.com. هل يمكنك لصق ملف server.js الخاص بك؟ هل تقوم بإحضار بياناتك على الخادم؟

مرحبا جاريد ،

شكرًا على الرد السريع ، نعم ، نقوم بإحضار البيانات من الخادم.

هنا هو الخادم الخاص بي

import App from './App';
import React from 'react';
import Helmet from 'react-helmet';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import express from 'express';
import compression from 'compression';
import { renderToString } from 'react-dom/server';

import configureStore from './store/configureStore';
import { remoteLoader } from './api/remoteLoader';
import serialize from 'serialize-javascript';

import { Capture } from 'react-loadable';
import { getBundles } from 'react-loadable/webpack';
import stats from '../build/react-loadable.json';

import { IS_PRODUCTION } from './components/shared/constants';

const assets = require(process.env.RAZZLE_ASSETS_MANIFEST);

const server = express();
server.use(compression());

if (!IS_PRODUCTION) {
    server.set('cache', false);
}

server
    .disable('x-powered-by')
    .use(express.static(process.env.RAZZLE_PUBLIC_DIR, { Expires: '30d' }))
    .get('/*', (req, res) => {
        //Ensures clients with old css paths are served the current file
        if (req.path.indexOf('/static/css') > -1 && assets.client.css) {
            const currentCssFile = `${process.env.RAZZLE_PUBLIC_DIR}${assets.client.css}`;
            return res.sendFile(currentCssFile);
        }

        remoteLoader(apiResult => {
            const responseCode = typeof apiResult.status === 'undefined' ? 404 : apiResult.status;

            if (responseCode === 301) {
                return res.redirect(responseCode, apiResult.headers.location);
            }

            // Compile an initial state
            const initialState = {
                remote: {
                    cms: {
                        result: apiResult ? apiResult.data : false,
                        loading: false
                    },
                    myDrewberry: {
                        searchResults: null,
                        loading: false,
                        failed: false
                    }
                }
            };
            // Create a new Redux store instance
            const store = configureStore(initialState);

            const context = {};
            const modules = [];
            const markup = renderToString(
                <Capture report={moduleName => modules.push(moduleName)}>
                    <StaticRouter context={context} location={req.url}>
                        <Provider store={store}>
                            <App />
                        </Provider>
                    </StaticRouter>
                </Capture>
            );
            const helmet = Helmet.renderStatic();

            if (context.url) {
                res.redirect(context.url);
            } else {
                const bundles = getBundles(stats, modules);
                const chunks = bundles.filter(bundle => bundle.file.endsWith('.js'));

                res.status(responseCode).send(
                    `<!doctype html>
                    <html ${helmet.htmlAttributes.toString()}>
                    <head>

                        ${assets.client.css ? `<link rel="stylesheet" href="${assets.client.css}">` : ''}
                        ${helmet.title.toString()}
                        ${helmet.meta.toString()}
                        ${helmet.link.toString()}
                        <link rel="icon" type="image/png" href="/favicon16.png" sizes="16x16"/>
                        <link rel="icon" type="image/png" href="/favicon32.png" sizes="32x32"/>
                        <link rel="icon" type="image/png" href="/favicon96.png" sizes="96x96"/>
                        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> <!--320-->
                        <meta http-equiv="expires" content="0">
                    </head>
                    <body class="drewberry-preload">

                        <!-- Google Tag Manager -->
                            <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
                            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
                            j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
                            'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
                            })(window,document,'script','dataLayer','GTM-TKPXWB');</script>
                        <!-- End Google Tag Manager -->

                        <div id="root">${markup}</div>
                        <script>
                            window.__PRELOADED_STATE__ = ${serialize(initialState)}
                        </script>
                        ${
                            IS_PRODUCTION
                                ? `<script src="${assets.client.js}"></script>`
                                : `<script src="${assets.client.js}" crossorigin></script>`
                        }
                          ${chunks
                              .map(chunk =>
                                  IS_PRODUCTION
                                      ? `<script src="/${chunk.file}"></script>`
                                      : `<script src="http://${process.env.HOST}:${parseInt(process.env.PORT, 10) + 1}/${
                                            chunk.file
                                        }"></script>`
                              )
                              .join('\n')}
                          <script>window.main();</script>
                    </body>
                </html>`
                );
            }
        }, req.path);
    });

export default server;

أستطيع أن أؤكد أن Razzle لا يعاني منه ، فقط حملت تثبيتًا نظيفًا واستخدام phantomjs ، لم يظهر أي من التحذير ، مما يعني أنه من المحتمل أنه شيء قمنا بتثبيته في بعض المكتبات.

هل ترى أي شيء واضح في ما سبق؟

يبدو الأمر وكأنه مطاردة أوزة برية في الوقت الحالي! :-)

لذا فإن اقتراحي (وربما نحتاج إلى دليل استكشاف الأخطاء وإصلاحها في المستندات حول هذا الأمر) هو التعليق بقدر ما تستطيع من server.js ، client.js ، App.js ، وربما تتخطى جوانب حزمة الويب الخاصة بك (إذا كان لديك أي منها) لإعادة تطبيق Razzle إلى حالة تشبه "hello world". أود أيضًا أن أقترح نسخ قالب HTML الخاص بـ Razzle مرة أخرى إلى ملف server.js فقط للتأكد من تحميل جميع البرامج النصية بشكل صحيح خارج الصندوق. بمجرد تشغيله ، افتح Chrome dev tools وانتقل إلى علامة التبويب "الأداء" ، وحدد مربع الاختيار "لقطات الشاشة" ، ثم اضغط على أيقونة التحديث. انظر GIF أدناه.

kapture 2019-02-05 at 8 33 42

الهدف هو التأكد من عدم وجود إطار أبيض فارغ في منطقة الخط الزمني. بعد الحصول على عرض مناسب بدون ومضات ، يجب إعادة إضافة المزيد والمزيد من التعليمات البرمجية القديمة. خذ خطوات صغيرة. هذا من السهل جدًا إفساده إذا لم تكن حريصًا.

بالنسبة إلى حالتك المحددة ، سأبدأ بإزالة كل عناصر إدارة علامات Google ، وجميع CSS ، بالإضافة إلى أي تقسيم للرمز تقوم به. فقط احصل عليه للعرض واعمل بشكل عكسي. بعد ذلك ، احصل على عمل Redux. ثم أضف خوذة رد الفعل مرة أخرى ، وبعد ذلك ، بمجرد أن تعتقد أنك حصلت عليها بشكل صحيح ، تحقق مرة أخرى من خلال إجراء اختبار Lighthouse أيضًا (علامة التبويب Audits). قم بإلزام هذه الحالة بفرع جديد حتى تتمكن من العودة إليها في المستقبل. بعد ذلك ، أضف البرامج النصية للتحليلات مرة أخرى وتحقق من العرض مرة أخرى. أخيرًا ، حاول إضافة تقسيم الشفرة مرة أخرى.

ملاحظة: إذا احتفظت بـ css وقمت بالتحليل أعلاه باستخدام Razzle في وضع التطوير ، فقد تحصل على FOUC لأن Razzle لا يعالج أنماط .css على الخادم أثناء التطوير (فقط على العميل). وبالتالي ، لاختبار أنك تقوم بعمل SSR مناسب مع ترطيب النمط إذا كنت تستخدم ملفات .css ، يجب عليك إنشاء Razzle للإنتاج وتشغيل خادم الإنتاج محليًا. ومع ذلك ، إذا كنت تتحقق ببساطة من وجود HTML الخاص بك من الخادم ، فيمكنك تشغيل هذا في وضع التطوير.

حسنًا ، شكرًا على العمل الرائع مع Razzle ، والآن على هذا. سأقوم بتدقيقه بشكل جيد وتقديم تقرير.

بالطبع ، أول شيء يجب التحقق منه في أي صفحة SEO "فارغة" (ليست فارغة ، هذا خطأ) هو: هل تعتمد صفحتك على componentDidMount لتحميل البيانات ليتم عرضها. يمكنك استخدام curl للتحقق بسرعة. إذا كانت الإجابة بنعم ، فأنت بحاجة إلى شيء مثل After.js للتحميل المسبق.

هل يمكنك تقديم المشورة لكيفية تصحيح الأخطاء باستخدام علامة تبويب الأداء ، إذا كانت هناك صفحة فارغة حول علامة 1000 مللي ثانية؟ أعلم أن مشكلتي تتعلق بمكتبة خطوط الأيقونات التي لم يتم تحميلها على الخادم ، وبالتالي فهي تعرض هذه المربعات الفارغة الفارغة عند التحميل الأولي ...

screen shot 2019-02-11 at 9 57 30 am

آه ، لا يتم تحميل جميع الخطوط المخصصة الخاصة بي حتى وقت لاحق. أقوم بتحميل الخطوط الخاصة بي من خلال CSS '@ font-face {}.

@font-face {
  font-family: 'SFProText';
  font-display: auto;
  src: url('fonts/SFPro/SF-Pro-Display-Regular.otf') format('truetype');
  font-weight: normal;
  font-style: normal;
}

jaredpalmer لدي نفس المشكلة أيضًا. لم يتم تحميل الخطوط والأصول في صفحة العميل الخاصة بي.

لم أقم بإضافة أي ملف webpack.config في إعداد التطبيق الخاص بي ، والذي قمت باستنساخه من الريبو الخاص بك. لقد أخذت النسخة من الريبو الخاص بك وقمت بتثبيت وحدات npm ، ثم بدأت في استخدام التطبيق عن طريق تشغيل أمر بدء npm.
هل فاتني أي شيء لتكوين أو يجب استخدام ملف webpack الجديد الخاص بي لحل هذه المشكلة؟

الرجاء مساعدتي لحل هذه المشكلة.

يبدو ملف App.css الخاص بي بهذا الشكل ..
@ font-face {
عائلة الخطوط: "Roboto-medium" ؛
src: url ("./ static / Fonts / Roboto-Medium-webfont.eot") ؛
src: url ("./ static / Fonts / Roboto-Medium-webfont.eot؟ #iefix") تنسيق ("embedded-opentype") ، url ("./ static / Fonts / Roboto-Medium-webfont.woff") تنسيق ("woff") ، تنسيق url ("./ ثابت / خطوط / Roboto-Medium-webfont.ttf") ("truetype") ؛ }

@ font-face {
عائلة الخطوط: "Roboto-normal" ؛
src: url ("./ static / Fonts / roboto-normal-webfont.eot") ؛
src: url ("./ static / Fonts / roboto-normal-webfont.eot؟ #iefix") تنسيق ("embedded-opentype") ، url ("./ static / Fonts / roboto-normal-webfont.woff") تنسيق ("woff") ، تنسيق url ("./ ثابت / خطوط / roboto-normal-webfont.ttf") ("truetype") ؛ }

شكرا غير متعمد :)

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