React - Menampilkan layar pemuatan saat DOM sedang merender?


150

Ini adalah contoh dari halaman aplikasi Google Adsense. Layar memuat ditampilkan sebelum halaman utama muncul setelah.

masukkan deskripsi gambar di sini

Saya tidak tahu bagaimana melakukan hal yang sama dengan Bereaksi karena jika saya membuat layar pemuatan yang dibuat oleh komponen Bereaksi, itu tidak ditampilkan saat halaman sedang memuat karena harus menunggu DOM yang diberikan sebelumnya.

Diperbarui :

Saya membuat contoh pendekatan saya dengan memasukkan screen loader index.htmldan menghapusnya di ReactcomponentDidMount() metode siklus hidup .

Contoh dan bereaksi memuat layar .


Perlihatkan apa yang ingin Anda perlihatkan dalam js polos, lalu jadikan itu disembunyikan atau dihapus dari DOM saat reaksi telah dipasang. Yang perlu Anda lakukan adalah menyembunyikannya dari kode reaksi.
FurkanO

Ini sungguh luar biasa! Terima kasih.
Arman Karimi

Jawaban:


100

Ini dapat dilakukan dengan menempatkan ikon memuat di file html Anda (index.html untuk ex), sehingga pengguna melihat ikon segera setelah file html dimuat.

Saat aplikasi Anda selesai memuat, Anda bisa menghapus ikon memuat itu di hook siklus hidup, saya biasanya melakukannya componentDidMount.


11
Jika Anda memasang komponen root ke simpul induk ikon itu, bahkan tidak perlu menghapusnya secara manual. Bereaksi akan membersihkan anak-anak dari simpul gunung dan menempatkan DOM sendiri yang baru dibuat di sana.
rishat

6
Saya tidak meletakkan ikon di dalam simpul akar aplikasi Bereaksi, hanya saja rasanya tidak cocok untuk saya
kkkkkkk

171

Hasil

Ketika halaman html di-render, segera tampilkan spinner (saat React memuat), dan sembunyikan setelah React siap.

Karena spinner dirender dalam HTML / CSS murni (di luar domain Bereaksi), Bereaksi seharusnya tidak mengontrol proses menampilkan / menyembunyikan secara langsung, dan implementasinya harus transparan untuk Bereaksi.

Solusi 1 -: pseudo-class kosong

Karena Anda membuat reaksi ke dalam wadah DOM - <div id="app"></div> , Anda dapat menambahkan pemintal ke wadah itu, dan ketika reaksi akan memuat dan merender, pemintal akan menghilang.

Anda tidak dapat menambahkan elemen DOM (misalnya div) di dalam root reaksi, karena Bereaksi akan mengganti konten wadah segera setelah ReactDOM.render()dipanggil. Bahkan jika Anda membuat null, konten masih akan digantikan oleh komentar - <!-- react-empty: 1 -->. Ini berarti bahwa jika Anda ingin menampilkan pemuat sementara komponen utama dipasang, data dimuat, tetapi tidak ada yang benar-benar ditampilkan, markup pemuat ditempatkan di dalam wadah (<div id="app"><div class="loader"></div></div> misalnya) tidak akan berfungsi.

Solusinya adalah menambahkan kelas pemintal ke wadah reaksi, dan menggunakan :emptykelas pseudo . Pemintal akan terlihat, selama tidak ada yang dirender ke dalam wadah (komentar tidak masuk hitungan). Segera setelah reaksi membuat sesuatu selain komentar, pemuat akan hilang.

Contoh 1

Dalam contoh Anda dapat melihat komponen yang merender nullhingga siap. Kontainer adalah loader juga - <div id="app" class="app"></div>, dan kelas loader hanya akan berfungsi jika :empty(lihat komentar dalam kode):

Contoh 2

Variasi dalam menggunakan :emptykelas pseudo untuk menunjukkan / menyembunyikan pemilih, adalah mengatur pemintal sebagai elemen saudara ke wadah aplikasi, dan menunjukkannya selama wadah kosong menggunakan kombinator saudara yang berdekatan ( +):


Solusi 2 - Lulus "penangan" pemintal sebagai alat peraga

Untuk memiliki kontrol berbutir halus atas kondisi tampilan pemintal, buat dua fungsi showSpinner dan hideSpinner, dan meneruskannya ke wadah root melalui alat peraga. Fungsi dapat memanipulasi DOM, atau melakukan apa pun yang diperlukan untuk mengendalikan pemintal. Dengan cara ini, Bereaksi tidak menyadari "dunia luar", juga tidak perlu mengendalikan DOM secara langsung. Anda dapat dengan mudah mengganti fungsi untuk pengujian, atau jika Anda perlu mengubah logika, dan Anda bisa meneruskannya ke komponen lain di pohon Bereaksi.

Contoh 1

Contoh 2 - kait

Contoh ini menggunakan useEffectkait untuk menyembunyikan pemintal setelah komponen dipasang.


Bisakah Anda menjelaskan di mana bagian 2 kode terakhir harus? Yang pertama jelas dalam file src javascript untuk komponen reaksi, yang ketiga saya kira masuk dalam template html yang akan diberikan oleh file js tersebut, tetapi kemana yang kedua pergi?
levraininjaneer

1
Yang ke-2 adalah CSS. Saya telah menggunakan CSS global, tetapi Anda dapat menggunakan Modul CSS atau CSS di JS. Yang ke-3 adalah file HTML, yang mungkin menyertakan markup spinner jika diperlukan (contoh ke-2).
Ori Drori

Batas waktu itu tidak baik ketika kinerja dipertimbangkan.
dryleaf

4
@dryleaf - setTimeout bukan bagian dari solusi. Itu mensimulasikan menunggu tindakan async sebelum merender konten.
Ori Drori

Saya menggunakan pendekatan serupa. Saya tidak dapat menemukan apa pun di webpack yang dapat membantu saya menemukan cache untuk file css yang diperlukan untuk loader. Bisakah kamu menolong?
hamza-jutt

40

Solusi untuk ini adalah:

Dalam fungsi render Anda, lakukan sesuatu seperti ini:

constructor() {
    this.state = { isLoading: true }
}

componentDidMount() {
    this.setState({isLoading: false})
}

render() {
    return(
        this.state.isLoading ? *showLoadingScreen* : *yourPage()*
    )
}

Menginisialisasi isLoading sebagai true dalam konstruktor dan false pada componentDidMount


Ketika kami telah memanggil metode ajax untuk memuat data ke komponen anak. componentDidMount dipanggil sebelum data komponen anak terisi. Bagaimana kita mengatasi masalah semacam ini?
dush88c

2
Untuk Mounting Life cyle tidak masalah, apakah Anda ingin menambahkan sesuatu untuk siklus hidup pembaruan?
zakir

saya harus melakukan ini di semua halaman atau hanya di entri aplikasi
Pedro JR

16

Jika ada orang yang mencari pustaka drop-in, zero-config dan dependensi-nol untuk case-use di atas, coba pace.js ( http://github.hubspot.com/pace/docs/welcome/ ).

Secara otomatis menghubungkan ke acara (ajax, readyState, pushstate riwayat, js event loop dll) dan menunjukkan loader disesuaikan.

Bekerja dengan baik dengan proyek reaksi / relai kami (menangani perubahan navigasi menggunakan router reaksi, permintaan relai) (Tidak terafiliasi; telah menggunakan pace.js untuk proyek kami dan ini bekerja sangat baik)


Hei! Bisakah Anda memberi tahu saya bagaimana menggunakannya dengan reaksi?
uneet7

cukup lampirkan skrip ke public/index.htmldan pilih gaya. ini adalah plugin sederhana yang luar biasa. Terima kasih.
PJ3

Saya tidak akan menemukan langkah tanpa jawaban ini. Itu sangat mudah untuk dimasukkan, dan dengan sedikit keajaiban CSS dan beberapa lampiran acara saya dapat memblokir / menonaktifkan aplikasi selama transisi dan menyesuaikan pemintal.
invertedSpear

12

Ketika aplikasi Bereaksi Anda sangat besar, itu benar-benar membutuhkan waktu untuk bangkit dan berjalan setelah halaman dimuat. Katakanlah, Anda me-mount Anda Bereaksi bagian dari aplikasi untuk #app. Biasanya, elemen ini di index.html Anda hanyalah sebuah div kosong:

<div id="app"></div>

Apa yang dapat Anda lakukan adalah meletakkan beberapa gaya dan banyak gambar di sana untuk membuatnya terlihat lebih baik antara memuat halaman dan rendering aplikasi Bereaksi awal ke DOM:

<div id="app">
  <div class="logo">
    <img src="/my/cool/examplelogo.svg" />
  </div>
  <div class="preload-title">
    Hold on, it's loading!
  </div>
</div>

Setelah halaman dimuat, pengguna akan segera melihat konten asli index.html. Tak lama setelah itu, ketika Bereaksi siap untuk memasang seluruh hirarki komponen yang diberikan ke simpul DOM ini, pengguna akan melihat aplikasi yang sebenarnya.

Perhatikan class, tidak className. Itu karena Anda perlu memasukkan ini ke file html Anda.


Jika Anda menggunakan SSR, hal-hal yang tidak terlalu rumit karena pengguna akan benar-benar melihat aplikasi yang sebenarnya setelah halaman dimuat.


Ini berfungsi juga saya memiliki dua tempat di mana memuat terjadi. Salah satunya adalah aplikasi besar. dan selanjutnya adalah persiapan (pemasangan berbagai komponen.) Jadi saya mendapatkan langkah flashing karena app.render mengambil alih dan animasi diatur ulang ( diganti benar-benar.) Apakah akan ada cara untuk menghindari flash itu? Akankah React membandingkan DOM secara langsung? Tapi dari apa yang saya mengerti React menambahkan semua jenis data pribadi di dalam tag ...
Alexis Wilke

12

Ini akan terjadi sebelum ReactDOM.render()mengendalikan root <div> . Yaitu Aplikasi Anda tidak akan dipasang hingga saat itu.

Jadi Anda dapat menambahkan loader Anda di index.htmlfile Anda di dalam root <div>. Dan itu akan terlihat di layar sampai React mengambil alih.

Anda dapat menggunakan elemen pemuat apa pun yang paling cocok untuk Anda ( svgdengan animasi misalnya).

Anda tidak perlu menghapusnya dengan metode siklus hidup apa pun. Bereaksi akan mengganti anak-anak dari akarnya <div> dengan yang Anda render <App/>, seperti yang dapat kita lihat di GIF di bawah.

Contoh di CodeSandbox

masukkan deskripsi gambar di sini

index.html

<head>
  <style>
    .svgLoader {
      animation: spin 0.5s linear infinite;
      margin: auto;
    }
    .divLoader {
      width: 100vw;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
  </style>
</head>

<body>
  <div id="root">
    <div class="divLoader">
      <svg class="svgLoader" viewBox="0 0 1024 1024" width="10em" height="10em">
        <path fill="lightblue"
          d="PATH FOR THE LOADER ICON"
        />
      </svg>
    </div>
  </div>
</body>

index.js

Menggunakan debuggeruntuk memeriksa halaman sebelum ReactDOM.render()dijalankan.

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

debugger; // TO INSPECT THE PAGE BEFORE 1ST RENDER

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

solusi yang cantik dan elegan
Gal Margalit

1
Saya senang ini membantu!
cbdeveloper

9

Saat ini kita dapat menggunakan kait juga di Bereaksi 16.8:

import React, { useState, useEffect } from 'react';

const App = () => {
  const [ spinner, setSpinner ] = useState(true);

  // It will be executed before rendering

  useEffect(() => {
    setTimeout(() => setSpinner(false), 1000)
  }, []);

  // [] means like componentDidMount

  return !spinner && <div>Your content</div>;
};

export default App;

5

Mengatur batas waktu dalam componentDidMount berfungsi tetapi dalam aplikasi saya, saya menerima peringatan kebocoran memori. Coba sesuatu seperti ini.

constructor(props) {
    super(props)
    this.state = { 
      loading: true,
    }
  }
  componentDidMount() {
    this.timerHandle = setTimeout(() => this.setState({ loading: false }), 3500); 
  }

  componentWillUnmount(){
    if (this.timerHandle) {
      clearTimeout(this.timerHandle);
      this.timerHandle = 0;
    }
  }

4

Saya harus berurusan dengan masalah itu baru-baru ini dan datang dengan solusi, yang berfungsi dengan baik untuk saya. Namun, saya sudah mencoba solusi @Ori Drori di atas dan sayangnya itu tidak berfungsi dengan baik (ada beberapa penundaan + saya tidak suka penggunaansetTimeout fungsi di sana).

Inilah yang saya pikirkan:

index.html mengajukan

headTag di dalam - gaya untuk indikator:

<style media="screen" type="text/css">

.loading {
  -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  background-color: black;
  border-radius: 100%;
  height: 6em;
  width: 6em;
}

.container {
  align-items: center;
  background-color: white;
  display: flex;
  height: 100vh;
  justify-content: center;
  width: 100vw;
}

@keyframes sk-scaleout {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
  }
  100% {
    -webkit-transform: scale(1.0);
    opacity: 0;
    transform: scale(1.0);
  }
}

</style>

Sekarang ini bodytag:

<div id="spinner" class="container">
  <div class="loading"></div>
</div>

<div id="app"></div>

Dan kemudian muncul logika yang sangat sederhana, di dalam app.jsfile (dalam fungsi render):

const spinner = document.getElementById('spinner');

if (spinner && !spinner.hasAttribute('hidden')) {
  spinner.setAttribute('hidden', 'true');
}

Bagaimana cara kerjanya?

Ketika komponen pertama (dalam aplikasi saya app.jsjuga dalam kebanyakan kasus) mount dengan benar, spinnersedang disembunyikan dengan menerapkan hiddenatribut padanya.

Apa yang lebih penting untuk ditambahkan - !spinner.hasAttribute('hidden')kondisi mencegah untuk menambahkan hiddenatribut ke pemintal dengan setiap komponen mount, jadi sebenarnya itu akan ditambahkan hanya satu kali, ketika seluruh aplikasi dimuat.


4

Saya menggunakan paket react-progress-2 npm, yang merupakan ketergantungan nol dan bekerja sangat baik di ReactJS.

https://github.com/milworm/react-progress-2

Instalasi:

npm install react-progress-2

Sertakan reaksi-kemajuan-2 / main.css ke proyek Anda.

import "node_modules/react-progress-2/main.css";

Sertakan react-progress-2dan letakkan di suatu tempat di komponen-atas, misalnya:

import React from "react";
import Progress from "react-progress-2";

var Layout = React.createClass({
render: function() {
    return (
        <div className="layout">
            <Progress.Component/>
                {/* other components go here*/}
            </div>
        );
    }
});

Sekarang, setiap kali Anda perlu menunjukkan indikator, panggil saja Progress.show(), misalnya:

loadFeed: function() {
    Progress.show();
    // do your ajax thing.
},

onLoadFeedCallback: function() {
    Progress.hide();
    // render feed.
}

Harap dicatat, itu showdan hidepanggilan ditumpuk, jadi setelah n-berturut-turut menunjukkan panggilan, Anda perlu melakukan dan menyembunyikan panggilan untuk menyembunyikan indikator atau Anda dapat menggunakan Progress.hideAll().


4

Saya juga menggunakan Bereaksi di aplikasi saya. Untuk permintaan saya menggunakan interseptor axios, cara terbaik untuk membuat layar loader (halaman penuh seperti yang Anda tunjukkan contoh) adalah dengan menambahkan kelas atau id ke tubuh contoh di dalam interceptor (di sini kode dari dokumentasi resmi dengan beberapa kode khusus):

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
     document.body.classList.add('custom-loader');
     return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
       document.body.classList.remove('custom-loader');
       return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  }); 

Dan kemudian implementasikan saja di CSS loader Anda dengan elemen semu (atau tambahkan kelas atau id ke elemen lain, bukan isi yang diinginkan) - Anda dapat mengatur warna latar belakang menjadi buram atau transparan, dll ... Contoh:

custom-loader:before {
    background: #000000;
    content: "";
    position: fixed;
    ...
}

custom-loader:after {
    background: #000000;
    content: "Loading content...";
    position: fixed;
    color: white;
    ...
}

3

Edit lokasi file index.html Anda di folder publik . Salin gambar Anda ke lokasi yang sama dengan index.html di folder publik. Dan kemudian ganti bagian dari isi index.html yang berisi <div id="root"> </div>tag ke kode html yang diberikan di bawah ini.

<div id="root">  <img src="logo-dark300w.png" alt="Spideren" style="vertical-align: middle; position: absolute;
   top: 50%;
   left: 50%;
   margin-top: -100px; /* Half the height */
   margin-left: -250px; /* Half the width */" />  </div>

Logo sekarang akan muncul di tengah halaman selama proses pemuatan. Dan kemudian akan diganti setelah beberapa detik oleh Bereaksi.


2

Anda tidak perlu banyak usaha, inilah contoh dasar.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="theme-color" content="#000000" />
  <meta name="description" content="Web site created using create-react-app" />
  <link rel="apple-touch-icon" href="logo192.png" />
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  <title>Title</title>
  <style>
    body {
      margin: 0;
    }

    .loader-container {
      width: 100vw;
      height: 100vh;
      display: flex;
      overflow: hidden;
    }

    .loader {
      margin: auto;
      border: 5px dotted #dadada;
      border-top: 5px solid #3498db;
      border-radius: 50%;
      width: 100px;
      height: 100px;
      -webkit-animation: spin 2s linear infinite;
      animation: spin 2s linear infinite;
    }

    @-webkit-keyframes spin {
      0% {
        -webkit-transform: rotate(0deg);
      }

      100% {
        -webkit-transform: rotate(360deg);
      }
    }

    @keyframes spin {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(360deg);
      }
    }

  </style>
</head>

<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root">
    <div class="loader-container">
      <div class="loader"></div>
    </div>
  </div>
</body>

</html>

Anda dapat bermain-main dengan HTMLdan CSSmembuatnya terlihat seperti contoh Anda.


1

Pertanyaan yang paling penting adalah: apa yang Anda maksud dengan 'memuat'? Jika Anda berbicara tentang elemen fisik yang dipasang, beberapa jawaban pertama di sini sangat bagus. Namun, jika hal pertama yang dilakukan aplikasi Anda adalah memeriksa keaslian, yang sebenarnya Anda muat adalah data dari backend apakah pengguna melewati cookie yang memberi label mereka pengguna yang sah atau tidak sah.

Ini didasarkan pada redux, tetapi Anda dapat dengan mudah mengubahnya menjadi model keadaan reaksi polos.

pembuat aksi:

export const getTodos = () => {
  return async dispatch => {
    let res;
    try {
      res = await axios.get('/todos/get');

      dispatch({
        type: AUTH,
        auth: true
      });
      dispatch({
        type: GET_TODOS,
        todos: res.data.todos
      });
    } catch (e) {
    } finally {
      dispatch({
        type: LOADING,
        loading: false
      });
    }
  };
};

Bagian terakhir berarti apakah pengguna diotorisasi atau tidak, layar pemuatan hilang setelah respons diterima.

Berikut komponen yang memuatnya:

class App extends Component {
  renderLayout() {
    const {
      loading,
      auth,
      username,
      error,
      handleSidebarClick,
      handleCloseModal
    } = this.props;
    if (loading) {
      return <Loading />;
    }
    return (
      ...
    );
  }

  ...

  componentDidMount() {
    this.props.getTodos();
  }

...

  render() {
    return this.renderLayout();
 }

}

Jika state.loading benar, kami akan selalu melihat layar pemuatan. Pada componentDidMount, kami memanggil fungsi getTodos kami, yang merupakan pembuat tindakan yang mengubah state.loading falsy ketika kami mendapat respons (yang bisa menjadi kesalahan). Pembaruan komponen kami, panggilan render lagi, dan kali ini tidak ada layar pemuatan karena pernyataan if.


1

Awal aplikasi reaksi didasarkan pada unduhan bundel utama. Bereaksi aplikasi hanya dimulai setelah bundel utama diunduh di browser. Ini bahkan berlaku dalam kasus arsitektur pemuatan malas. Tetapi faktanya adalah kita tidak dapat secara tepat menyebutkan nama bundel apa pun. Karena webpack akan menambahkan nilai hash di akhir setiap bundel pada saat Anda menjalankan perintah 'npm run build'. Tentu saja kita dapat menghindarinya dengan mengubah pengaturan hash, tetapi itu akan sangat memengaruhi masalah data cache di Browser. Browser mungkin tidak mengambil versi baru karena nama bundel yang sama. . kita membutuhkan pendekatan webpack + js + CSS untuk menangani situasi ini.

ubah public / index.html seperti di bawah ini

<!DOCTYPE html>
<html lang="en" xml:lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=3.0, shrink-to-fit=no">
  <meta name="theme-color" content="#000000">
  <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
  <style>
 .percentage {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 150px;
      height: 150px;
      border: 1px solid #ccc;
      background-color: #f3f3f3;
      -webkit-transform: translate(-50%, -50%);
          -ms-transform: translate(-50%, -50%);
              transform: translate(-50%, -50%);
      border: 1.1em solid rgba(0, 0, 0, 0.2);
      border-radius: 50%;
      overflow: hidden;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
          -ms-flex-pack: center;
              justify-content: center;
      -webkit-box-align: center;
          -ms-flex-align: center;
              align-items: center;
    }

    .innerpercentage {
      font-size: 20px;
    }
  </style>
  <script>
    function showPercentage(value) {
      document.getElementById('percentage').innerHTML = (value * 100).toFixed() + "%";
    }
    var req = new XMLHttpRequest();
    req.addEventListener("progress", function (event) {
      if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total;
        showPercentage(percentComplete)
        // ...
      } else {
        document.getElementById('percentage').innerHTML = "Loading..";
      }
    }, false);

    // load responseText into a new script element
    req.addEventListener("load", function (event) {
      var e = event.target;
      var s = document.createElement("script");
      s.innerHTML = e.responseText;
      document.documentElement.appendChild(s);
      document.getElementById('parentDiv').style.display = 'none';

    }, false);

    var bundleName = "<%= htmlWebpackPlugin.files.chunks.main.entry %>";
    req.open("GET", bundleName);
    req.send();

  </script>
  <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

  <title>App Name</title>
  <link href="<%= htmlWebpackPlugin.files.chunks.main.css[0] %>" rel="stylesheet">
</head>

<body>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <div id="parentDiv" class="percentage">
    <div id="percentage" class="innerpercentage">loading</div>
  </div>
  <div id="root"></div>
  <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
</body>

</html>

Dalam konfigurasi webpack produksi Anda, ubah opsi HtmlWebpackPlugin ke bawah

 new HtmlWebpackPlugin({
          inject: false,
...

Anda mungkin perlu menggunakan perintah 'eject' untuk mendapatkan file konfigurasi. webpack terbaru mungkin memiliki opsi untuk mengkonfigurasi HtmlWebpackPlugin tanpa mengeluarkan proyek. masukkan deskripsi gambar di sini


1

Saya juga menggunakan jawaban @Ori Drori dan berhasil membuatnya bekerja. Ketika kode Bereaksi Anda tumbuh, bundel akan dikompilasi sehingga browser klien harus mengunduh pada akses pertama kali. Ini membebankan masalah pengalaman pengguna jika Anda tidak menanganinya dengan baik.

Apa yang saya tambahkan ke jawaban @Ori adalah menambahkan dan menjalankan fungsi onload di index.html pada atribut onload dari tag body, sehingga loader hilang setelah semuanya dimuat penuh di dalam browse, lihat cuplikan di bawah ini:

<html>
  <head>
     <style>
       .loader:empty {
          position: absolute;
          top: calc(50% - 4em);
          left: calc(50% - 4em);
          width: 6em;
          height: 6em;
          border: 1.1em solid rgba(0, 0, 0, 0.2);
          border-left: 1.1em solid #000000;
          border-radius: 50%;
          animation: load8 1.1s infinite linear;
        }
        @keyframes load8 {
          0% {
           transform: rotate(0deg);
          }
          100% {
           transform: rotate(360deg);
          }
        }
     </style>
     <script>
       function onLoad() {
         var loader = document.getElementById("cpay_loader");loader.className = "";}
     </script>
   </head>
   <body onload="onLoad();">
     more html here.....
   </body>
</html>

1

Bagaimana dengan menggunakan Pace

Gunakan alamat tautan ini di sini.

https://github.hubspot.com/pace/docs/welcome/

1. Di situs web mereka pilih gaya yang Anda inginkan dan tempel di index.css

2. pergi ke cdnjs Salin tautan untuk Pace Js dan tambahkan ke tag skrip Anda di public / index.html

3. Secara otomatis mendeteksi beban web dan menampilkan langkah di browser Top.

Anda juga dapat memodifikasi ketinggian dan animasi di css.


Luar biasa dan dapat diintegrasikan dalam waktu singkat.
UzumakiL
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.