Νοημοσύνη δεδομένων Πλάτωνα.
Κάθετη Αναζήτηση & Αι.

Γρήγορες ενσωματωμένες εικόνες με React και Webpack

Ημερομηνία:

Webpack είναι εξαιρετικό για τη δημιουργία εφαρμογών React, αλλά ξέρατε ότι μπορεί να σας βοηθήσει να βελτιστοποιήσετε και την απόδοση της εφαρμογής; Το Webpack μπορεί αυτόματα να ενσωματώσει δεδομένα εικόνας, βελτιώνοντας την απόδοση μειώνοντας τον αριθμό των αιτημάτων που χρειάζεται να κάνει η σελίδα σας. Ας μάθουμε πώς.

Επένδυση εικόνας

Κανονικά, κάθε εικόνα σε μια ιστοσελίδα είναι ένα μοναδικό αρχείο που το πρόγραμμα περιήγησης πρέπει να κάνει ένα αίτημα HTTP για να το εμφανίσει. Όσο περισσότερα αιτήματα χρειάζεται να κάνει το πρόγραμμα περιήγησης, τόσο περισσότερο θα διαρκέσει η φόρτωση της σελίδας. Αντίθετα, η μείωση του συνολικού αριθμού αιτημάτων θα βελτιώσει γενικά την απόδοση.

Η ενσωμάτωση εικόνας μειώνει τον αριθμό των πρόσθετων αιτημάτων που απαιτούνται για τη φόρτωση σελίδας ενσωματώνοντας δεδομένα εικόνας απευθείας στο πακέτο HTML ή Javascript. Όπως με οτιδήποτε άλλο, αυτή η βελτιστοποίηση δεν παρέχεται δωρεάν: Ο συνολικός αριθμός των αιτημάτων εικόνας μειώνεται στην τιμή ενός μεγαλύτερου αρχικού ωφέλιμου φορτίου. Αυτό έχει ως αποτέλεσμα ένα γλυκό σημείο απόδοσης όπου μικρές εικόνες είναι ενσωματωμένες, αλλά μεγαλύτερες εικόνες φορτώνονται κανονικά με πρόσθετα αιτήματα HTTP.

Γεια σου! Δεν θέλετε να διαβάσετε όλα τα μέσα και τα έξω για να λυγίσετε το Webpack σε σχήμα; Μετάβαση στην τελική διαμόρφωση του πακέτου ιστού.

Μια απλή εφαρμογή React

Για να δοκιμάσουμε την ενσωμάτωση εικόνας, δημιουργήσαμε μια απλή εφαρμογή React:

Βασικός κατάλογος πηγών εφαρμογής React

A index.html Το αρχείο χρησιμοποιείται για την εκκίνηση του μεμονωμένου (μεταγλωττισμένου) αρχείου JSX:

<html>
    <header>
        <title>React With Inline Images</title>
    </header>
    <body>
        <div class="images-container"></div>
    </body>
    <script src="index.js"></script>
</html>
import React from "react"
import ReactDOM from "react-dom/client"


import indexHtml from "./index.html"

function SomeImages(props) {
    return (
        <div>
            <h2>{props.title}</h2>
            <p>
                <h3>Some small images:</h3>
                <img src="images/small-bee.png" />
                <img src="images/small-chick.png" />
                <img src="images/small-puppy.png" />
                <img src="images/small-tree.png" />
            </p>
            <p>
                <h3>Some larger images:</h3>
                <img src="images/medium-duckling.jpg" /><br />
                <img src="images/medium-squirrel.jpg" />
            </p>
        </div>
    )
}

var containerDiv = document.querySelector(".images-container");
var root = ReactDOM.createRoot(containerDiv);
root.render(SomeImages({ title: "React with Inline Images" }));

Δημιουργία αρχείων React JSX με το Webpack

Πρώτον, οι εξαρτήσεις Webpack και React πρέπει να εγκατασταθούν με το NPM:

npm install react react-dom
npm install --save-dev webpack webpack-cli babel-loader @babel/preset-react

Το Webpack δεν μεταγλωττίζει το JSX out of the box. Προσθήκη κανόνα ενότητας σε webpack.config.js λέει στο Webpack να χρησιμοποιεί το Babel κατά τη μεταγλώττιση αρχείων JSX. Υπάρχει ένας επιπλέον κανόνας για την αντιγραφή του bootstrap html στον φάκελο εξόδου. Περισσότερα για τις "ενότητες ενεργητικού" αργότερα:

var path = require("path");

module.exports = {
    mode: "development",
    entry: "./src/index.jsx",
    output: {
        filename: "index.js",
        path: path.resolve("dist/"),
    },
    module: {
        rules: [
            {
                test: /.jsx?$/,
                loader: "babel-loader",
                options: {
                    "presets": ["@babel/preset-react"]
                }
            },
            {
                test: /.html$/i,
                type: "asset/resource",
                generator: {
                    filename: "[name][ext]"
                }
            }
        ]
    }
};

Τρέξιμο webpack από τη γραμμή εντολών μεταγλωττίζει το JSX μας σε έναν φάκελο εξόδου με το όνομα dist/, αλλά υπάρχουν ορισμένα ζητήματα που πρέπει να επιλυθούν.

Εισαγωγή/Απαίτηση εικόνων

Λοιπόν, τα πράγματα ΣΧΕΔΟΝ λειτουργούν. Όλες οι ετικέτες εικόνων μας σπάνε όταν φορτώνουμε τη μεταγλωττισμένη εφαρμογή:

Οι εικόνες συσκευασίας ιστού δεν λειτουργούν

Και δεν βγήκαν εικόνες στο δικό μας dist/ φάκελο:

Δεν υπάρχουν εικόνες στον κατάλογο εξόδου Webpack

Οι εικόνες δεν εμφανίζονται επειδή το Webpack δεν διαβάζει τις διευθύνσεις URL src γνωρίσματα. Κανένα από τα αρχεία εικόνας μας δεν αντιγράφεται στο dist/ φάκελο επειδή το Webpack υπέθεσε ότι αναφέρουμε μια εξωτερική εξάρτηση για την οποία δεν χρειάζεται να ανησυχεί. Το JSX πρέπει να εισάγει ή να απαιτεί τις εικόνες, ώστε το Webpack να γνωρίζει ότι χρειαζόμαστε αυτές τις εικόνες:

// BEFORE:
<p>
    <h3>Some small images:</h3>
    <img src="images/small-bee.png" />
    <img src="images/small-chick.png" />
    <img src="images/small-puppy.png" />
    <img src="images/small-tree.png" />
</p>
<p>
    <h3>Some larger images:</h3>
    <img src="images/medium-duckling.jpg" /><br />
    <img src="images/medium-squirrel.jpg" />
</p>

// AFTER:
<p>
    <h3>Some small images:</h3>
    <img src={require("./images/small-bee.png")} />
    <img src={require("./images/small-chick.png")} />
    <img src={require("./images/small-puppy.png")} />
    <img src={require("./images/small-tree.png")} />
</p>
<p>
    <h3>Some larger images:</h3>
    <img src={require("./images/medium-duckling.jpg")} /><br />
    <img src={require("./images/medium-squirrel.jpg")} />
</p>

Χρήση λειτουργικών μονάδων για αρχεία εικόνας

Και, τα πράγματα είναι ακόμα σπασμένα. Το Webpack γνωρίζει για τις εικόνες μας τώρα, αλλά κάνει λάθη:

ERROR in ./src/images/medium-duckling.jpg 1:0
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, /
    currently no loaders are configured to process this file. /
    See https://webpack.js.org/concepts
(Source code omitted for this binary file)
 @ ./src/index.jsx 16:9-48

Το Webpack αποτυγχάνει επειδή δεν ξέρει τι να κάνει με τα αρχεία εικόνας μας. Ακριβώς όπως με το JSX, χρειαζόμαστε έναν κανόνα ενότητας που λέει στο Webpack τι να κάνει όταν συναντήσει μια εικόνα.

Το Webpack 5 έχει μια νέα δυνατότητα που ονομάζεται Ενότητες ενεργητικού που προορίζεται να αντικαταστήσει το url-loader, file-loader, να raw-loaderχρησιμοποιείται στο Webpack 4 για αυτήν την κατάσταση. Απλώς για να λειτουργήσουν τα πράγματα, θα πούμε στο Webpack να αντιγράφει πάντα αρχεία εικόνας στον φάκελο εξόδου:


module: {
    rules: [
        
        {
            test: /.(png|jpg)$/i,
            type: 'asset/resource'
        }
    ]
}

Τέλος, το webpack περιλαμβάνει εικόνες στο μεταγλωττισμένο αποτέλεσμα:

Κατάλογος εξόδου Webpack με εικόνες

Και η σελίδα μας λειτουργεί:

Εφαρμογή React με εικόνες

Τοποθετήστε όλες τις εικόνες στον δικό τους φάκελο

Το Webpack αντιγράφει τα αρχεία εικόνων μας, αλλά όλες οι εικόνες βρίσκονται στη ρίζα του καταλόγου εξόδου με ακατάληπτους κατακερματισμούς για ονόματα. Οποιεσδήποτε περισσότερες εικόνες και το dist/ ο φάκελος θα γίνει χάος. Μπορούμε να πούμε στη λειτουργική μονάδα στοιχείου να ονομάσει καλύτερα τις εικόνες μας και να τις τοποθετήσει στον δικό της φάκελο:

{
    test: /.(png|jpg)$/i,
    type: 'asset/resource'
    // Added:
    generator: {
        filename: 'images/[name]-[hash][ext]'
    }
}

Τώρα οι εικόνες βρίσκονται όλες σε ξεχωριστό φάκελο με κατανοητά ονόματα. Η διατήρηση του κατακερματισμού βοηθά στην εξάλειψη της προσωρινής μνήμης:

Κατάλογος εξόδου Webpack με όλες τις εικόνες στον δικό τους φάκελο

Αυτόματος καθαρισμός του καταλόγου εξόδου του Webpack

Γιατί ο κατάλογός μου είναι τόσο γεμάτος; Καθώς η διαμόρφωση του πακέτου web έχει αλλάξει, καθαρίσαμε με μη αυτόματο τρόπο παλιά αρχεία από το dist/ Ευρετήριο. Από προεπιλογή, το Webpack δεν αφαιρεί ποτέ παλιά αρχεία που δεν χρειάζονται πλέον. Μπορούμε να διαμορφώσουμε το Webpack ώστε να καθαρίζει αυτόματα τον φάκελο dist κάθε έκδοση:

output: {
    // ...snip...
    clean: true
},

Ενσωματωμένες μικρές εικόνες

Επιτέλους, οι εικόνες λειτουργούν και μπορούμε να κάνουμε αυτό για το οποίο ήρθαμε εδώ: inline μικρές εικόνες! Η βάση του Webpack asset Το Asset Module χειρίζεται αυτόματα το inlining για εμάς. Το Webpack θα ενσωματώσει οτιδήποτε κάτω από 8 KB από προεπιλογή, αλλά μπορούμε επίσης να ορίσουμε ρητά το όριο μεγέθους. Οι εικόνες πάνω από το όριο θα εξάγονται στο dist/ φάκελο όπως ήταν προηγουμένως:

module: {
        rules: [
            // ...snip...
            {
                test: /.(png|jpg)$/i,
                // Previously we had disabled inlining by using 'asset/resource'
                type: 'asset',
                parser: {
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // Inline images under 10KB
                    }
                },
                generator: {
                    filename: 'images/[name]-[hash][ext]'
                }
            }
        ]
    }

Οι μικρότερες εικόνες είναι ενσωματωμένες και ο κατάλογος εξόδου περιέχει μόνο μεγαλύτερες εικόνες:

Κατάλογος εξόδου Webpack με μόνο μεγάλες εικόνες

Μπορούμε να δούμε τις κωδικοποιημένες εικόνες Base64 εάν επιθεωρήσουμε τη σελίδα που έχει αποδοθεί:

Εικόνες Base64 στον επιθεωρητή Chrome Dev Tools

TLDR: Τελική διαμόρφωση πακέτου Web

Τώρα έχουμε το Webpack που ενσωματώνει αυτόματα εικόνες μαζί με μερικές βελτιώσεις στην ποιότητα ζωής. Όταν όλα λειτουργούν, η διαμόρφωση του πακέτου ιστού μας μοιάζει με αυτό:

var path = require("path");

module.exports = {
    mode: "development",
    entry: "./src/index.jsx",
    output: {
        filename: "index.js",
        path: path.resolve("dist/"),
        clean: true
    },
    module: {
        rules: [
            {
                test: /.jsx?$/,
                loader: "babel-loader",
                options: {
                    "presets": ["@babel/preset-react"]
                }
            },
            {
                test: /.html$/i,
                type: "asset/resource",
                generator: {
                    filename: "[name][ext]"
                }
            },
            {
                test: /.(png|jpg)$/i,
                type: 'asset',
                parser: {
                    dataUrlCondition: {
                        maxSize: 10 * 1024 
                    }
                },
                generator: {
                    filename: 'images/[name]-[hash][ext]'
                }
            }
        ]
    }
};

Συμπέρασμα

Πείσαμε με επιτυχία το Webpack να ενσωματώσει αυτόματα τις εικόνες μας. Αυτό μείωσε τον αριθμό των αιτημάτων δικτύου που πρέπει να κάνει η σελίδα μας, αλλά έκανε τη σελίδα μας πιο γρήγορη; Αυτό είναι το είδος της ερώτησης που δημιουργήθηκε για να απαντήσει το Request Metrics. Δοκίμασέ το σήμερα για να μετρήσετε την απόδοση του ιστότοπού σας για πραγματικούς χρήστες στην παραγωγή.

Έχουμε καλύψει μόνο έναν τρόπο βελτιστοποίησης εικόνων εδώ, αλλά υπάρχουν πολλοί άλλοι τρόποι βελτιστοποίηση της απόδοσης της εικόνας.

spot_img

Τελευταία Νοημοσύνη

spot_img

Συνομιλία με μας

Γεια σου! Πώς μπορώ να σε βοηθήσω?