react-rating
react-rating copied to clipboard
Feature request: Lighter DOM Size
I'm using a pretty simple SVG with 1 path for fullSymbol & emptySymbol, for example:
const StarFull = props =>
<svg width="1em" height="1em" viewBox="0 0 19 19" {...props}>
<path d="M3.844 18.458a.507.507 0 01-.302-.097.524.524 0 01-.206-.506l.983-5.76L.156 8.018a.51.51 0 01-.129-.53.517.517 0 01.415-.352l5.752-.841 2.573-5.239A.513.513 0 019.23.77a.52.52 0 01.463.287l2.572 5.239 5.756.841a.517.517 0 01.282.882l-4.162 4.077.982 5.76a.521.521 0 01-.205.506.509.509 0 01-.544.04l-5.148-2.718-5.15 2.718a.51.51 0 01-.233.057z" />
</svg>;
const StarEmpty = (props) =>
<svg width="1em" height="1em" viewBox="0 0 19 19" {...props}>
<path d="M15.148 18.462a.494.494 0 01-.237-.061l-5.143-2.718L4.622 18.4a.509.509 0 01-.543-.04.521.521 0 01-.206-.506l.982-5.76-4.16-4.077a.51.51 0 01-.13-.53.517.517 0 01.415-.352l5.754-.841L9.31 1.056A.513.513 0 019.772.77a.52.52 0 01.463.287l2.571 5.239 5.754.84a.517.517 0 01.286.883l-4.16 4.077.98 5.76a.521.521 0 01-.518.607zM2.077 7.892l3.65 3.553c.123.118.18.293.151.46l-.863 5.018 4.514-2.37a.511.511 0 01.484 0l4.51 2.37-.863-5.018a.518.518 0 01.15-.46l3.652-3.554-5.043-.732a.51.51 0 01-.39-.285L9.772 2.308 7.514 6.874a.516.516 0 01-.39.285l-5.047.732z" />
</svg>;
<Rating
initialRating={3.5}
emptySymbol={<StarEmpty />}
fullSymbol={<StarFull />}
fractions={2}
readonly
/>
This RatingStars component outputs 45 nodes into the DOM 😮 Let's say you have a page of 30 items that each displayed a rating — the total DOM size is already 1,350 nodes without anything else on the page. You're page will get flagged every time by Lighthouse because it's going to exceed the recommended 1500 nodes.
Amazon uses image sprites but they get away with just 5 nodes per rating element.
Hi @rpastorelle!
I see your point and it seems a fair concern.
This component aimed to be as the most flexible rating. But with flexibility probably comes less efficiency, or in our specific case, more elements/nodes 😄.
I am open to optimizations and I can spot some options, specially for read-only ratings. So I will keep this issue open just in case someone (or myself) had desire and time to contribute.
Now some insights and discoveries...
Rating structure
The rating symbols are composed by:
- A parent
spanelement that wraps the entire symbol. Used as a container of each symbol - Two children
spanelements that wrap the empty and the full symbols. Basically used to manage the visibility and the fraction of the symbol being shown - The variable number of elements of the empty and full elements
There are 3 extra wrapper elements for each symbol.
The formula to know the exact number of elements generated for a rating of n symbols would be something like this:
n symbols * (wrapper elements + number of elements emptySymbol + number of elements fullSymbol)
In your example:
5 * (3 + 2 + 2) = 35
(I don't know how you got 45 😅)
Amazon rating structure
I checked two types of star ratings, let's say the input and the read-only.
In the input rating each symbol is composed by two elements (a label and an input). So for a 5 star rating we have 10 elements.
<div class="a-section rating">
<label name="star1" class="emptyStar" tabindex="1" aria-label="seleccionar para valorar vendedor con una estrella">
<input name="star-rating" type="radio" value="1" class="radio-btn hide">
</label>
<label name="star2" class="emptyStar" tabindex="1" aria-label="seleccionar para valorar vendedor con dos estrellas">
<input name="star-rating" type="radio" value="2" class="radio-btn hide">
</label>
<label name="star3" class="emptyStar" tabindex="1" aria-label="seleccionar para valorar vendedor con tres estrellas">
<input name="star-rating" type="radio" value="3" class="radio-btn hide">
</label>
<label name="star4" class="emptyStar" tabindex="1" aria-label="seleccionar para valorar vendedor con cuatro estrellas">
<input name="star-rating" type="radio" value="4" class="radio-btn hide">
</label>
<label name="star5" class="emptyStar" tabindex="1" aria-label="seleccionar para valorar vendedor con cinco estrellas">
<input name="star-rating" type="radio" value="5" class="radio-btn hide">
</label>
</div>
The read-only symbol is a pre-built image with the corresponding rating selected.
<i class="a-icon a-icon-star-small a-star-small-4-5 aok-align-bottom">
<span class="a-icon-alt">4.7 out of 5 stars</span>
</i>
It uses the following sprite:

As you can see in the image they have all ratings from 0 to 5 (with halves too 😉).
As a curiosity
I created a Lighthouse report on the same Amazon page I was looking into the read-only stars and here is what I got:

A code sandbox used for the investigation.