روش ذکر فایلهای ایستا در کامپوننتهای جاوا اسکریپتی برنامههای React
React، برای مدیریت پروژهی خود، از Webpack استفاده میکند و در این حالت، کار با فایلهای ایستا مانند تصاویر و قلمهای وب، شبیه به کار با فایلهای CSS خواهد بود؛ یعنی این نوع فایلها را باید در فایلهای جاوا اسکریپتی برنامه، import کرد. به این ترتیب Webpack کار یکی سازی این فایلها را با bundle نهایی تولید شده، انجام میدهد.
یک مثال: فرض کنید فایل button.css به صورت زیر تعریف شدهاست:
.Button {
padding: 20px;
}
برای استفادهی از این فایل css در یک کامپوننت، ابتدا آنرا import کرده و سپس از classNameهای تعریف شدهی در آن استفاده میکنیم:
import React, { Component } from 'react';
import './Button.css';
class Button extends Component {
render() {
return <div className="Button" />;
}
}
در حالت توسعه، با هر تغییری در این فایل css، بارگذاری مجدد برنامه به صورت خودکار صورت گرفته و نتیجهی نهایی رندر خواهد شد. در حالت نهایی ارائهی برنامه، تمام فایلهای css، با هم یکی شده و نگارش minified آنها، به bundle نهایی برنامه اضافه میشوند. توصیه شدهاست یک فایل css را در چندین کامپوننت برنامه import نکنید. بهتر است یک کامپوننت دکمه را ایجاد کنید که فایل css مشخصی را import میکند و سپس از آن کامپوننت در قسمتهای مختلف برنامه استفاده کنید.
البته برخلاف حالت کار با CSS imports، با import یک فایل ایستا، یک رشته در اختیار ما قرار میگیرد که از آن میتوان در کدهای خود استفاده کرد. برای کاهش تعداد رفت و برگشتهای به سرور، اگر فایلهای تصویری با فرمتهای bmp, gif, jpg, jpeg و png، کمتر از 10,000 بایت باشند، از data URI آنها بجای مسیر نهایی استفاده خواهد شد. این مورد شامل فایلهای svg نمیشود.
یک مثال: import React from 'react';
import logo from './logo.svg';
console.log(logo);
function Header() {
return <img src={logo} alt="Logo" />;
}
export default Header;
در اینجا ابتدا یک فایل تصویری، import شدهاست. سپس میتوان از رشتهی متناظر با آن، به عنوان src المان تصویر استفاده کرد.
این مورد برای تصاویر ذکر شدهی در فایلهای CSS نیز صادق است:
.Logo {
background-image: url(./logo.png);
}
Webpack در فایلهای CSS به دنبال مسیرهای فایلهای ثابت شروع شدهی با /. میگردد و مسیرهای این نوع فایلها را با مسیر نهایی ارائهی برنامه، به صورت خودکار جایگزین و اصلاح میکند. همچنین نیازی هم به نگرانی در مورد کش شدن این فایلهای ثابت وجود ندارد؛ چون webpack از نامهای خاصی به همراه hash این نوع فایلها، برای جایگزینی نهایی استفاده خواهد کرد و اگر محتوای فایلهای ثابت تغییر کنند، این هش نیز تغییر کره و مرورگر نگارش جدید آنها را دریافت میکند. مزیت دیگر کار با webpack، ارائهی خطاهای زمان کامپایل برنامه است. برای مثال اگر فایلهای ثابت مورد استفادهی در برنامه به درستی مسیر دهی نشده باشند، یک خطای زمان کامپایل صادر میشود.
یک مثال: فرض کنید در برنامهی ASP.NET Core خود که با React یکی شدهاست، فایل project_folder/ClientApp/src/
images/progress_bar.gif را قرار دادهاید. روش import آن با توجه به مسیرهای نسبی برنامه به صورت زیر است:
import progressBar from '../images/progress_bar.gif';
و روش فراخوانی آن در کدهای یک کامپوننت به نحو زیر خواهد بود:
<img alt="loading..." src={progressBar} />
روش ذکر فایلهای ایستا در کامپوننتهای تایپ اسکریپتی برنامههای React
اگر از تایپاسکریپت استفاده میکنید، چنین importهایی سبب بروز خطای «'Cannot find module './logo.png» میشوند. برای رفع این مشکل، فایلی را به نام assets.d.ts به پروژهی خود اضافه کرده و آنرا به صورت زیر تکمیل کنید:
declare module "*.gif";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.png";
declare module "*.svg";
به این ترتیب پسوندهای فایلهای مختلف ایستا، به عنوان فرمتهای مجاز ماژولها، قابل استفاده میشوند.
نحوهی پردازش پوشهی ویژهی public در برنامههای React
اگر فایلی در پوشهی ویژهی public برنامههای react قرار گیرد، توسط webpack پردازش نخواهد شد. در این حالت این نوع فایلها بدون هیچ نوع تغییری به پوشهی build نهایی کپی میشوند. بنابراین برای کار با فایلهای ایستای قرار گرفتهی در پوشهی public باید از متغیر خاصی به نام PUBLIC_URL استفاده کرد. برای مثال درون فایل index.html، چنین تعریفی را میتوان مشاهده کرد:
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
اگر نیاز به استفادهی از فایلی درون پوشهی src و یا node_modules دارید، باید آنها را به این پوشه کپی کنید تا جزئی از پروسهی build شوند. متغیر PUBLIC_URL در زمان اجرای دستور npm run build، با مسیر صحیحی جایگزین خواهد شد.
برای دسترسی به این مسیر در کامپوننتهای برنامه نیز میتوان از متغیر محیطی process.env.PUBLIC_URL استفاده کرد:
render() {
return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}
البته روش توصیه شده، همان ذکر importهای فایلهای ایستا است و بهتر است از این متغیر محیطی زیاد استفاده نکنید؛ چون پردازش ثانویهای بر روی آنها صورت نمیگیرد و یا minified نمیشوند. نبود آنها سبب بروز خطای زمان کامپایل نخواهد شد و همچنین هیچ hash ای به نام نهایی آنها به صورت خودکار اضافه نمیگردد که ممکن است سبب بروز مشکلات کش شدن طولانی مدت این فایلهای ایستا شود.
بنابراین اکنون این سؤال مطرح میشود که چه زمانی بهتر است از پوشهی public استفاده شود؟
- اگر میخواهید نام فایل نهایی ایستای مدنظر مانند manifest.json، بدون تغییر باقی بماند.
- هزاران فایل ایستا را دارید و میخواهید این مسیرها را به صورت پویا در برنامه فراخوانی کنید (و قرار نیست جزئی از bundle نهایی شوند).
- میخواهید فایلهای js خاصی را خارج از سیستم bundle اصلی قرار دهید؛ چون به هر دلیلی این نوع فایلها با سیستم webpack سازگاری ندارند و نباید توسط آن پردازش شوند. در این حالت باید این نوع فایلها را با تگ script به فایل index.html به صورت دستی معرفی کنید.