[tdb_mobile_menu menu_id="81451" el_class="plato-left-menu" icon_size="eyJhbGwiOjUwLCJwaG9uZSI6IjMwIn0=" icon_padding="eyJhbGwiOjAuNSwicGhvbmUiOiIxLjUifQ==" tdc_css="eyJhbGwiOnsibWFyZ2luLXRvcCI6IjEwIiwibWFyZ2luLWJvdHRvbSI6IjAiLCJtYXJnaW4tbGVmdCI6IjE1IiwiZGlzcGxheSI6IiJ9LCJwaG9uZSI6eyJtYXJnaW4tdG9wIjoiMCIsIm1hcmdpbi1sZWZ0IjoiMCIsImRpc3BsYXkiOiIifSwicGhvbmVfbWF4X3dpZHRoIjo3Njd9" align_horiz="content-horiz-center" inline="yes" icon_color="#ffffff" icon_color_h="#ffffff"][tdb_header_logo align_vert="content-vert-center" url="https://zephyrnet.com" inline="yes" text="Zephyrnet" image_width="eyJwaG9uZSI6IjM1In0=" img_txt_space="eyJwaG9uZSI6IjEwIn0=" f_text_font_size="eyJwaG9uZSI6IjE4In0=" f_text_font_line_height="eyJwaG9uZSI6IjEuNSJ9" f_text_font_weight="eyJwaG9uZSI6IjcwMCJ9" f_text_font_transform="eyJwaG9uZSI6ImNhcGl0YWxpemUifQ==" f_text_font_family="eyJwaG9uZSI6ImZzXzIifQ==" text_color="#ffffff" text_color_h="var(--accent-color)"]
[tdb_mobile_horiz_menu menu_id="1658" single_line="yes" f_elem_font_family="eyJwaG9uZSI6ImZzXzIifQ==" f_elem_font_weight="eyJwaG9uZSI6IjcwMCJ9" text_color="var(--news-hub-white)" text_color_h="var(--news-hub-accent-hover)" f_elem_font_size="eyJwaG9uZSI6IjE0In0=" f_elem_font_line_height="eyJwaG9uZSI6IjQ4cHgifQ==" elem_padd="eyJwaG9uZSI6IjAgMTVweCJ9" tdc_css="eyJwaG9uZSI6eyJwYWRkaW5nLXJpZ2h0IjoiNSIsInBhZGRpbmctbGVmdCI6IjUiLCJkaXNwbGF5Ijoibm9uZSJ9LCJwaG9uZV9tYXhfd2lkdGgiOjc2N30="]
[tdb_mobile_menu inline="yes" menu_id="81451" el_class="plato-left-menu" icon_size="50" icon_padding="0.5" tdc_css="eyJhbGwiOnsibWFyZ2luLXRvcCI6IjEwIiwibWFyZ2luLWJvdHRvbSI6IjAiLCJtYXJnaW4tbGVmdCI6I jE1IiwiZGlzcGxheSI6IiJ9fQ==" icon_color="#ffffff" icon_color_h="#ffffff" ]
Logo Zephyrnet
[tdb_header_menu main_sub_tdicon = "td-icon-down" sub_tdicon = "td-icon-right-arrow" mm_align_horiz = "content-Horiz-center" modules_on_row_regular = "20%" modules_on_row_cats = "20%" image_size = "td_c300xgory0" "image" show_excerpt = "none" show_com = "none" show_date = "" show_author = "none" mm_sub_align_horiz = "content-Horiz-right" mm_elem_align_horiz = "content-Horiz-center" menu_id = "81450" show_mega_cats = "yes" align_horiz = "content-Horiz-center" elem_padd = "0 30px" main_sub_icon_space = "12" mm_width = "1192" mm_padd = "30px 25px" mm_align_screen = "yes" mm_sub_padd = "20px 25px 0" mm_sub_border = "1px 0 0" mm_elem_space = "25" mm_elem_padd = "0" mm_elem_border = "0" mm_elem_border_a = "0" mm_elem_border_rad = "0" mc1_title_tag = "h2" modules_gap = "25" excl_txt = "Premium" excl_margin = "0 6 "0px 0px 2px 5px" excl_bg = "var (- news-hub-voice)" f_excl_font_size = "2" f_excl_font_weight = "4" f_excl_font_transform = "uppercase" meta_padding = "12px 700 20" art_title = "0 0 0px" show_cat = "none" show_pagination = "vô hiệu hóa led "text_color =" var (- news-hub-white) "tds_menu_active0-line_color =" var (- news-hub-voice) "f_elem_font_size =" 10 "f_elem_font_line_height =" 1px "f_elem_font_weight =" 18 "f_elem_font_transform =" none "mm_bg =" var (- news-hub-dark-gray) "mm_border_color =" var (- news-hub-voice) "mm_subcats_border_color =" # 64 "mm_elem_color =" var (- news-hub-white ) "mm_elem_color_a =" var (- news-hub-voice-hover) "f_mm_sub_font_size =" 400 "title_txt =" var (- news-hub-white) "title_txt_hover =" var (- news-hub-voice- hover)" date_txt="var(--news-hub-light-grey)" f_title_font_line_height="444444" f_title_font_weight="14" f_meta_font_line_height="1.25" f_meta_font_family="fs_700" tdc_css="eyJhbGwiOnsiYm1.3yZGVyLXRvcC2aWR9aCI13IjEiLCJib0JkZXItcmlnaHQtd6lkdGgiOiIxIiwiYm3yZGVyLWJvdHRvbS2aWR9aCI13IjEiLCJib0JkZXItbGVmdC6aWR3aCI13IjEiLCJib0JkZXItY6sb3IiOiJ29YXIoLS3uZXdzLWh2Yi1kYXJrLWdyZXkpIiwiZGlzcGxheSI1IiJ1fQ==" mm_border_size="6px 9 4 "f_elem_font_family =" fs_0 "mm_subcats_bg =" var (- news-hub-dark-gray) "mm_elem_bg =" rgba (0) "mm_elem_bg_a =" rgba (2) "f_mm_sub_font_family =" fs_0,0,0,0 "mm_child_cats =" 0,0,0,0 "mm_sub_inline =" yes "mm_subcats_posts_limit =" 2 "]
Trang Chủ Hình ảnh nội tuyến nhanh với React và Webpack

Hình ảnh nội tuyến nhanh với React và Webpack

0

Gói web rất tốt để xây dựng các ứng dụng React, nhưng bạn có biết nó cũng có thể giúp bạn tối ưu hóa hiệu suất ứng dụng không? Webpack có thể tự động nội tuyến dữ liệu hình ảnh, cải thiện hiệu suất bằng cách giảm số lượng yêu cầu mà trang của bạn cần thực hiện. Hãy học cách làm.

Nội tuyến hình ảnh

Thông thường, mọi hình ảnh trên trang web là một tệp duy nhất mà trình duyệt phải thực hiện yêu cầu HTTP để hiển thị. Trình duyệt cần thực hiện càng nhiều yêu cầu thì thời gian tải trang càng lâu. Ngược lại, giảm tổng số yêu cầu nói chung sẽ cải thiện hiệu suất.

Nội tuyến hình ảnh làm giảm số lượng yêu cầu bổ sung cần thiết để tải trang bằng cách nhúng dữ liệu hình ảnh trực tiếp vào gói HTML hoặc Javascript. Như với bất kỳ điều gì, tối ưu hóa này không miễn phí: Tổng số lượng yêu cầu hình ảnh được giảm xuống với mức giá của tải trọng ban đầu lớn hơn. Điều này dẫn đến một điểm đặc biệt về hiệu suất trong đó hình ảnh nhỏ được nội tuyến, nhưng hình ảnh lớn hơn được tải bình thường với một yêu cầu HTTP bổ sung.

Chào! Bạn không muốn đọc tất cả thông tin chi tiết về việc bẻ cong Webpack thành hình dạng? Chuyển đến cấu hình webpack cuối cùng.

Một ứng dụng phản ứng đơn giản

Để kiểm tra nội tuyến hình ảnh, chúng tôi đã tạo một ứng dụng React đơn giản:

Thư mục nguồn ứng dụng React cơ bản

A index.html tệp được sử dụng để khởi động tệp JSX duy nhất (đã biên dịch):

<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" }));

Xây dựng tệp React JSX với Webpack

Đầu tiên, các phụ thuộc Webpack và React cần được cài đặt với NPM:

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

Webpack không biên dịch JSX ra khỏi hộp. Thêm quy tắc mô-đun vào webpack.config.js yêu cầu Webpack sử dụng Babel khi biên dịch các tệp JSX. Có một quy tắc bổ sung để sao chép html bootstrap của chúng tôi vào thư mục đầu ra. Tìm hiểu thêm về "mô-đun nội dung" sau:

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]"
                }
            }
        ]
    }
};

Chạy webpack từ dòng lệnh biên dịch JSX của chúng tôi thành một thư mục đầu ra có tên dist/, nhưng có một số vấn đề cần được khắc phục.

Nhập / Yêu cầu Hình ảnh

Chà, những thứ ALMOST hoạt động. Tất cả các thẻ hình ảnh của chúng tôi đều bị hỏng khi chúng tôi tải ứng dụng đã biên dịch:

Hình ảnh Webpack không hoạt động

Và không có hình ảnh nào được xuất ra dist/ thư mục:

Không có hình ảnh nào trong thư mục đầu ra của Webpack

Hình ảnh không hiển thị vì Webpack không đọc các url trong src thuộc tính. Không có tệp hình ảnh nào của chúng tôi được sao chép vào dist/ vì Webpack giả định rằng chúng ta đang tham chiếu đến một phụ thuộc bên ngoài mà nó không cần phải lo lắng. JSX cần nhập hoặc yêu cầu hình ảnh để Webpack biết chúng ta cần những hình ảnh đó:

// 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>

Sử dụng mô-đun nội dung cho tệp hình ảnh

Và, mọi thứ vẫn bị phá vỡ. Webpack biết về hình ảnh của chúng tôi bây giờ, nhưng đang gặp lỗi:

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 không thành công vì nó không biết phải làm gì với các tệp hình ảnh của chúng tôi. Cũng như với JSX, chúng ta cần một quy tắc mô-đun cho Webpack biết phải làm gì khi nó gặp một hình ảnh.

Webpack 5 có một tính năng mới được gọi là Mô-đun tài sản có nghĩa là để thay thế url-loader, file-loaderraw-loaderđược sử dụng trong Webpack 4 cho tình huống này. Để mọi thứ hoạt động, chúng tôi sẽ yêu cầu Webpack luôn sao chép các tệp hình ảnh vào thư mục đầu ra:


module: {
    rules: [

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

Cuối cùng, webpack bao gồm hình ảnh trong đầu ra đã biên dịch:

Thư mục đầu ra Webpack với hình ảnh

Và trang của chúng tôi đang hoạt động:

Phản ứng ứng dụng với hình ảnh

Đặt tất cả hình ảnh trong thư mục riêng của chúng

Webpack đang sao chép các tệp hình ảnh của chúng tôi, nhưng tất cả các hình ảnh đều nằm trong thư mục gốc của thư mục đầu ra với các hàm băm không thể hiểu được cho tên. Bất kỳ hình ảnh nào khác và dist/ thư mục sẽ trở thành một mớ hỗn độn. Chúng tôi có thể yêu cầu mô-đun nội dung đặt tên cho hình ảnh của chúng tôi tốt hơn và đặt chúng vào thư mục riêng của chúng:

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

Bây giờ tất cả các hình ảnh đều nằm trong một thư mục riêng biệt với những cái tên dễ hiểu. Giữ mã băm giúp xử lý chặn bộ nhớ cache:

Thư mục đầu ra của Webpack với tất cả các hình ảnh trong thư mục riêng của chúng

Tự động làm sạch thư mục đầu ra của Webpack

Tại sao thư mục phân phối của tôi rất lộn xộn? Vì cấu hình webpack đã thay đổi, chúng tôi đã xóa thủ công các tệp cũ khỏi dist/ danh mục. Theo mặc định, Webpack không bao giờ xóa các tệp cũ không còn cần thiết nữa. Chúng ta có thể cấu hình Webpack để tự động dọn dẹp thư mục dist trong mỗi bản dựng:

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

Hình ảnh nhỏ trong dòng

Cuối cùng, hình ảnh đang hoạt động và chúng tôi có thể làm những gì chúng tôi đến đây: hình ảnh nhỏ nội tuyến! Cơ sở của Webpack asset Mô-đun tài sản tự động xử lý nội tuyến cho chúng tôi. Webpack sẽ nội tuyến bất kỳ thứ gì dưới 8KB theo mặc định, nhưng chúng tôi cũng có thể đặt ngưỡng kích thước một cách rõ ràng. Hình ảnh vượt quá giới hạn sẽ được xuất vào dist/ thư mục như trước đây:

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]'
                }
            }
        ]
    }

Các hình ảnh nhỏ hơn được nội dòng và thư mục đầu ra chỉ chứa các hình ảnh lớn hơn:

Thư mục đầu ra của Webpack chỉ có hình ảnh lớn

Chúng tôi có thể thấy các hình ảnh được mã hóa Base64 nếu chúng tôi kiểm tra trang được kết xuất:

Hình ảnh Base64 trong trình kiểm tra Công cụ dành cho nhà phát triển của Chrome

TLDR: Cấu hình Webpack cuối cùng

Giờ đây, chúng tôi đã có Webpack tự động nội tuyến hình ảnh cùng với một số cải tiến về chất lượng cuộc sống. Với mọi thứ hoạt động, cấu hình webpack của chúng tôi trông giống như sau:

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]'
                }
            }
        ]
    }
};

Kết luận

Chúng tôi đã thuyết phục thành công Webpack tự động nội tuyến hình ảnh của chúng tôi. Điều này làm giảm số lượng yêu cầu mạng mà trang của chúng tôi cần thực hiện, nhưng nó có làm cho trang của chúng tôi nhanh hơn không? Đó là loại câu hỏi Số liệu yêu cầu được xây dựng để trả lời. Dùng thử ngay hôm nay để đo lường hiệu quả hoạt động của trang web đối với người dùng thực trong quá trình sản xuất.

Ở đây, chúng tôi chỉ đề cập đến một cách để tối ưu hóa hình ảnh, nhưng có nhiều cách khác để tối ưu hóa hiệu suất hình ảnh.

Trò chuyện trực tiếp với chúng tôi (chat)

Chào bạn! Làm thế nào để tôi giúp bạn?