Razzle: Bagaimana cara memecahkan masalah rendering server?

Dibuat pada 5 Feb 2019  ·  9Komentar  ·  Sumber: jaredpalmer/razzle

Halo,

Kami telah melihat masalah di mana jika Anda masuk ke konsol Pencarian Google, dan mengambil sebagai Google, situs web ditampilkan sebagai halaman kosong.

Saya telah melakukan beberapa penelitian, dan beberapa di antaranya membawa saya ke artikel ini:

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

Sangat mungkin mesin pencari, dan mengambil karena google sendiri tidak berperilaku dengan cara yang sama, atau kita akan kehilangan peringkat sekarang, namun saya ingin menyelesaikan masalah ini, karena akan membuat pemilik situs web tetap terjaga.

Saya telah mengunduh phantomjs, dengan asumsi itu sama dengan mengambil seperti Google, dan mencoba merendernya mengembalikan sejumlah kesalahan:

image

Masalah ini mungkin mudah diselesaikan seperti mengubah browser target yang sedang dikompilasi, namun menginstal babel/polyfil dan mengimpor saja tidak akan berhasil.

Adakah yang bisa mengarahkan saya ke arah yang benar di sini?

stale

Komentar yang paling membantu

Jadi saran saya (dan mungkin kita memerlukan panduan pemecahan masalah dalam dokumen tentang ini) adalah berkomentar sebanyak mungkin dari server.js , client.js , App.js , dan berpotensi aspek penggantian webpack Anda (jika ada) untuk mengembalikan aplikasi Razzle Anda ke status seperti "hello world". Saya juga menyarankan untuk menyalin kembali template HTML Razzle ke file server.js hanya untuk memastikan bahwa semua skrip dimuat dengan benar di luar kotak. Setelah dijalankan, buka alat pengembang Chrome dan buka tab "Kinerja", centang kotak "Tampilan Layar", lalu tekan ikon Segarkan. Lihat GIF di bawah ini.

kapture 2019-02-05 at 8 33 42

Tujuannya adalah untuk memastikan tidak ada bingkai putih kosong di area timeline. Setelah Anda mendapatkan render yang tepat tanpa berkedip, Anda harus menambahkan kembali lebih banyak dan lebih banyak kode lama Anda. Ambil langkah kecil. Ini cukup mudah untuk mengacaukan jika Anda tidak hati-hati.

Adapun kasus spesifik Anda, saya akan mulai dengan menghapus semua hal pengelola tag google, semua CSS Anda, serta pemecahan kode apa pun yang Anda lakukan. Cukup buat untuk dirender dan bekerja mundur. Selanjutnya, buat Redux berfungsi. Kemudian tambahkan kembali react-helm, dan kemudian, setelah Anda merasa sudah melakukannya dengan benar, periksa kembali dengan melakukan tes Lighthouse juga (tab Audit). Komit status ini ke cabang baru sehingga Anda dapat kembali ke sana di masa mendatang. Selanjutnya, tambahkan kembali skrip analitik Anda dan periksa rendering lagi. Terakhir, coba tambahkan kembali pemecahan kode.

Catatan: Jika Anda menyimpan css dan melakukan analisis di atas dengan Razzle dalam mode pengembangan, Anda mungkin mendapatkan FOUC karena Razzle tidak memproses gaya .css di server selama pengembangan (hanya pada klien). Jadi, untuk sepenuhnya menguji apakah Anda melakukan SSR yang tepat dengan hidrasi gaya jika Anda menggunakan file .css , Anda harus membuat Razzle untuk produksi dan menjalankan server produksi secara lokal. Namun, jika Anda hanya memeriksa keberadaan HTML Anda dari server, Anda dapat menjalankannya dalam mode pengembangan.

Semua 9 komentar

Jika halaman Anda kosong maka Anda telah merusak skema SSR atau hidrasi Anda. Razzle tidak mengalami apa yang telah Anda jelaskan di luar kotak, pada kenyataannya, ini digunakan di situs yang berfokus pada SEO seperti BBC.com. dapatkah Anda menempelkan file server.js Anda? Apakah Anda mengambil data Anda di server?

Hai Jared,

Terima kasih atas balasan yang cepat, ya kami mengambil data dari server.

Ini server saya.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;

Saya dapat mengonfirmasi bahwa di luar kotak Razzle tidak menderita karenanya, hanya memuat instalasi yang bersih dan menggunakan phantomjs tidak ada peringatan yang muncul, yang berarti itu mungkin sesuatu yang kami instal di perpustakaan.

Apakah Anda melihat sesuatu yang jelas di atas?

Rasanya seperti mengejar angsa liar saat ini! :-)

Jadi saran saya (dan mungkin kita memerlukan panduan pemecahan masalah dalam dokumen tentang ini) adalah berkomentar sebanyak mungkin dari server.js , client.js , App.js , dan berpotensi aspek penggantian webpack Anda (jika ada) untuk mengembalikan aplikasi Razzle Anda ke status seperti "hello world". Saya juga menyarankan untuk menyalin kembali template HTML Razzle ke file server.js hanya untuk memastikan bahwa semua skrip dimuat dengan benar di luar kotak. Setelah dijalankan, buka alat pengembang Chrome dan buka tab "Kinerja", centang kotak "Tampilan Layar", lalu tekan ikon Segarkan. Lihat GIF di bawah ini.

kapture 2019-02-05 at 8 33 42

Tujuannya adalah untuk memastikan tidak ada bingkai putih kosong di area timeline. Setelah Anda mendapatkan render yang tepat tanpa berkedip, Anda harus menambahkan kembali lebih banyak dan lebih banyak kode lama Anda. Ambil langkah kecil. Ini cukup mudah untuk mengacaukan jika Anda tidak hati-hati.

Adapun kasus spesifik Anda, saya akan mulai dengan menghapus semua hal pengelola tag google, semua CSS Anda, serta pemecahan kode apa pun yang Anda lakukan. Cukup buat untuk dirender dan bekerja mundur. Selanjutnya, buat Redux berfungsi. Kemudian tambahkan kembali react-helm, dan kemudian, setelah Anda merasa sudah melakukannya dengan benar, periksa kembali dengan melakukan tes Lighthouse juga (tab Audit). Komit status ini ke cabang baru sehingga Anda dapat kembali ke sana di masa mendatang. Selanjutnya, tambahkan kembali skrip analitik Anda dan periksa rendering lagi. Terakhir, coba tambahkan kembali pemecahan kode.

Catatan: Jika Anda menyimpan css dan melakukan analisis di atas dengan Razzle dalam mode pengembangan, Anda mungkin mendapatkan FOUC karena Razzle tidak memproses gaya .css di server selama pengembangan (hanya pada klien). Jadi, untuk sepenuhnya menguji apakah Anda melakukan SSR yang tepat dengan hidrasi gaya jika Anda menggunakan file .css , Anda harus membuat Razzle untuk produksi dan menjalankan server produksi secara lokal. Namun, jika Anda hanya memeriksa keberadaan HTML Anda dari server, Anda dapat menjalankannya dalam mode pengembangan.

Oke, terima kasih atas kerja luar biasa dengan Razzle, dan sekarang untuk ini. Saya akan mengauditnya dengan baik dan melaporkan kembali.

Tentu saja, hal pertama yang harus diperiksa pada halaman seo yang "kosong" (bukan kosong, itu adalah kesalahan), adalah: apakah halaman Anda bergantung pada componentDidMount untuk memuat data yang akan ditampilkan. Anda dapat menggunakan curl untuk memeriksa dengan cepat. Jika ya, Anda memerlukan sesuatu seperti After.js untuk dimuat sebelumnya.

bisakah Anda memberi saran cara men-debug menggunakan tab Performance, jika ada halaman kosong di sekitar tanda 1000ms? Saya tahu masalah saya adalah seputar pustaka font ikon yang tidak dimuat di server dan dengan demikian ini menunjukkan kotak kosong kosong ini pada pemuatan awal ...

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

Ah, semua font kustom saya tidak dimuat sampai lama kemudian. Saya memuat font saya melalui @font-face {} CSS.

@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 Saya juga memiliki masalah yang sama. Font dan aset tidak dimuat di halaman klien saya.

Saya belum menambahkan file webpack.config dalam pengaturan aplikasi saya, yang saya kloning dari repo Anda. Saya baru saja mengambil salinan dari repo Anda dan menginstal modul npm, kemudian saya mulai menggunakan aplikasi dengan menjalankan perintah npm start.
adakah yang saya lewatkan untuk mengonfigurasi atau harus menggunakan file webpack baru saya untuk menyelesaikan masalah ini?

Tolong bantu saya untuk menyelesaikan masalah ini.

File App.css saya terlihat seperti ini..
@font-wajah {
font-family: 'Roboto-medium';
src: url("./static/fonts/Roboto-Medium-webfont.eot");
src: url("./static/fonts/Roboto-Medium-webfont.eot?#iefix") format("embedded-opentype"), url("./static/fonts/Roboto-Medium-webfont.woff") format("woff"), url("./static/fonts/Roboto-Medium-webfont.ttf") format("truetype"); }

@font-wajah {
font-family: 'Roboto-reguler';
src: url("./static/fonts/roboto-regular-webfont.eot");
src: url("./static/fonts/roboto-regular-webfont.eot?#iefix") format("embedded-opentype"), url("./static/fonts/roboto-regular-webfont.woff") format("woff"), url("./static/fonts/roboto-regular-webfont.ttf") format("truetype"); }

terima kasih inadvane :)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

knipferrc picture knipferrc  ·  5Komentar

Jayphen picture Jayphen  ·  4Komentar

gabimor picture gabimor  ·  3Komentar

dizzyn picture dizzyn  ·  3Komentar

alexjoyner picture alexjoyner  ·  3Komentar