303 lines
12 KiB
TypeScript
303 lines
12 KiB
TypeScript
import { ArrowLeft, Facebook, Link, Linkedin, Twitter } from "lucide-react";
|
||||
|
|
|
|||
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|||
|
|
import { Button } from "@/components/ui/button";
|
|||
|
|
import { cn } from "@/lib/utils";
|
|||
|
|
|
|||
|
|
interface Resource2Props {
|
|||
|
|
navigation: {
|
|||
|
|
backText: string;
|
|||
|
|
backHref: string;
|
|||
|
|
className?: string;
|
|||
|
|
};
|
|||
|
|
blog: {
|
|||
|
|
title: string;
|
|||
|
|
author: string;
|
|||
|
|
role: string;
|
|||
|
|
date: string;
|
|||
|
|
readTime: string;
|
|||
|
|
imageSrc: string;
|
|||
|
|
content: React.ReactNode;
|
|||
|
|
};
|
|||
|
|
social: {
|
|||
|
|
heading: string;
|
|||
|
|
links: Array<{
|
|||
|
|
icon: "link" | "linkedin" | "twitter" | "facebook";
|
|||
|
|
href: string;
|
|||
|
|
label: string;
|
|||
|
|
}>;
|
|||
|
|
};
|
|||
|
|
illustration: {
|
|||
|
|
imageSrc: string;
|
|||
|
|
imageAlt: string;
|
|||
|
|
};
|
|||
|
|
className?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const Resource2 = ({
|
|||
|
|
className,
|
|||
|
|
navigation = {
|
|||
|
|
backText: "همه مقالات",
|
|||
|
|
backHref: "/resources",
|
|||
|
|
},
|
|||
|
|
blog = {
|
|||
|
|
title:
|
|||
|
|
"ساخت وباپلیکیشنهای پایدار: راهنمای توسعهدهنده برای کدنویسی سبز",
|
|||
|
|
author: "سارا چن",
|
|||
|
|
date: "۲۵ آذر ۱۴۰۳",
|
|||
|
|
readTime: "۸ دقیقه مطالعه",
|
|||
|
|
role: "توسعهدهنده ارشد",
|
|||
|
|
imageSrc: "/block-media/shadcnblocks/block/avatar-1.webp",
|
|||
|
|
content: (
|
|||
|
|
<>
|
|||
|
|
<p>
|
|||
|
|
دنیای دیجیتال انرژی بیشتری نسبت به کل صنعت هوانوردی مصرف میکند. ما
|
|||
|
|
بهعنوان توسعهدهنده مسئولیت داریم برنامههایی بسازیم که نهتنها
|
|||
|
|
کاربردی و زیبا باشند، بلکه برای سیاره ما نیز پایدار باشند.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h2>ردپای کربنی کد</h2>
|
|||
|
|
<p>
|
|||
|
|
هر خط کدی که مینویسیم تأثیر محیطی دارد. از انرژی مصرفی سرورها تا
|
|||
|
|
منابع بهکاررفته در ساخت دستگاهها، انتخابهای دیجیتال ما مهمتر از
|
|||
|
|
آنچه فکر میکنیم اهمیت دارند.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h3>درک تأثیر</h3>
|
|||
|
|
<p>
|
|||
|
|
وباپلیکیشنهای مدرن بهشدت پرمصرف هستند. این واقعیتهای
|
|||
|
|
چشمگیر را در نظر بگیرید:
|
|||
|
|
</p>
|
|||
|
|
<ul>
|
|||
|
|
<li>
|
|||
|
|
<strong>مراکز داده</strong> ۱٪ از برق جهانی را مصرف میکنند
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>پخش ویدیو</strong> ۳٪ از انتشار کربن جهانی را تشکیل
|
|||
|
|
میدهد
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>هرزنامه ایمیل</strong> سالانه ۱۷ میلیون تن CO₂ تولید
|
|||
|
|
میکند
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
<blockquote>
|
|||
|
|
<p>
|
|||
|
|
«پایدارترین کد، کدی است که اصلاً نمینویسید. دومین کد پایدار، کدی
|
|||
|
|
است که کارآمد اجرا میشود.»
|
|||
|
|
</p>
|
|||
|
|
</blockquote>
|
|||
|
|
|
|||
|
|
<h2>اصول کدنویسی سبز</h2>
|
|||
|
|
<p>این اصول پایه را هر توسعهدهنده باید رعایت کند:</p>
|
|||
|
|
<ol>
|
|||
|
|
<li>
|
|||
|
|
<strong>بهینهسازی برای عملکرد:</strong> کد سریعتر، انرژی کمتری
|
|||
|
|
مصرف میکند
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>کاهش وابستگیها:</strong> هر پکیج به حجم بسته اضافه
|
|||
|
|
میکند
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>استفاده از الگوریتمهای کارآمد:</strong> پیچیدگی بهتر یعنی
|
|||
|
|
محاسبه کمتر
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>پیادهسازی استراتژیهای کش:</strong> کاهش عملیات تکراری
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<strong>انتخاب هاستینگ سبز:</strong> سرورهای با انرژی تجدیدپذیر
|
|||
|
|
</li>
|
|||
|
|
</ol>
|
|||
|
|
|
|||
|
|
<h3>پیادهسازی عملی</h3>
|
|||
|
|
<p>
|
|||
|
|
بیایید چند نمونه مشخص از پیادهسازی این اصول را ببینیم:
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h4>۱ بهینهسازی تصویر</h4>
|
|||
|
|
<p>
|
|||
|
|
تصاویر اغلب ۶۰ تا ۸۰ درصد حجم یک صفحه را تشکیل میدهند. از
|
|||
|
|
فرمتهای مدرن مثل WebP یا AVIF استفاده کنید، بارگذاری هوشمند پیاده
|
|||
|
|
کنید و تصاویر با اندازه مناسب سرو کنید.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h4>۲ تقسیم کد (تقسیم هوشمند بار)</h4>
|
|||
|
|
<p>
|
|||
|
|
فقط جاوااسکریپتی را بارگذاری کنید که کاربر واقعاً به آن نیاز
|
|||
|
|
دارد. این کار حجم بسته اولیه را کم میکند و عملکرد را بهبود
|
|||
|
|
میدهد.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h4>۳. بهینهسازی پایگاه داده</h4>
|
|||
|
|
<p>
|
|||
|
|
کوئریهای کارآمد بنویسید، ایندکسگذاری درست انجام دهید و connection
|
|||
|
|
pooling پیاده کنید تا بار پایگاه داده کاهش یابد.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h2>آینده توسعه پایدار</h2>
|
|||
|
|
<p>
|
|||
|
|
با حرکت به جلو، پایداری باید در هر تصمیم توسعه یک ملاحظه اصلی
|
|||
|
|
شود. ابزارهایی مثل <strong>ابزار تست سرعت</strong> و{" "}
|
|||
|
|
<strong>ابزار تحلیل عملکرد</strong> میتوانند به سنجش تأثیر محیطی
|
|||
|
|
برنامههای ما کمک کنند.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<p>
|
|||
|
|
مسیر توسعه وب پایدار مستمر است، اما هر بهینهسازی کوچک به آینده
|
|||
|
|
دیجیتال سبزتر کمک میکند. با یک اصل شروع کنید، تأثیر را بسنجید و
|
|||
|
|
بهتدریج شیوههای پایدارتر را به گردش کار توسعه خود اضافه کنید.
|
|||
|
|
</p>
|
|||
|
|
</>
|
|||
|
|
),
|
|||
|
|
},
|
|||
|
|
social = {
|
|||
|
|
heading: "اشتراکگذاری این مقاله",
|
|||
|
|
links: [
|
|||
|
|
{ icon: "link", href: "#", label: "کپی لینک" },
|
|||
|
|
{ icon: "linkedin", href: "#", label: "اشتراک در لینکدین" },
|
|||
|
|
{ icon: "twitter", href: "#", label: "اشتراک در X" },
|
|||
|
|
{ icon: "facebook", href: "#", label: "اشتراک در فیسبوک" },
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
illustration = {
|
|||
|
|
imageSrc: "/block-media/shadcnblocks/block/placeholder-2.svg",
|
|||
|
|
imageAlt:
|
|||
|
|
"تصویر توسعه وب پایدار با تمرینهای کدنویسی سبز و تأثیر محیطی",
|
|||
|
|
},
|
|||
|
|
}: Resource2Props) => {
|
|||
|
|
const getIcon = (icon: string, className: string) => {
|
|||
|
|
switch (icon) {
|
|||
|
|
case "link":
|
|||
|
|
return <Link className={`size-4 ${className}`} />;
|
|||
|
|
case "شبکه حرفهای":
|
|||
|
|
return <Linkedin className={`size-4 ${className}`} />;
|
|||
|
|
case "شبکه اجتماعی":
|
|||
|
|
return <Twitter className={`size-4 ${className}`} />;
|
|||
|
|
case "شبکه اجتماعی":
|
|||
|
|
return <Facebook className={`size-4 ${className}`} />;
|
|||
|
|
default:
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<section dir="rtl" lang="fa" className={cn("", className)}>
|
|||
|
|
<div className="min-h-128 bg-primary text-primary-foreground">
|
|||
|
|
<div className="container py-16">
|
|||
|
|
<div className="grid grid-cols-1 items-start gap-8 lg:grid-cols-3">
|
|||
|
|
<div className="flex h-full max-w-md flex-col justify-between gap-8">
|
|||
|
|
<div className="space-y-6">
|
|||
|
|
<div className="flex items-center gap-2 text-primary-foreground">
|
|||
|
|
<a
|
|||
|
|
href={navigation.backHref}
|
|||
|
|
className="group/nav flex items-center gap-2 transition-all duration-200 hover:gap-4"
|
|||
|
|
>
|
|||
|
|
<ArrowLeft className="size-4 rtl:rotate-180 group-hover/nav:text-primary-foreground" />
|
|||
|
|
<span className="transition-colors group-hover/nav:text-primary-foreground group-hover/nav:underline">
|
|||
|
|
{navigation.backText}
|
|||
|
|
</span>
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
<h1 className="text-start text-3xl leading-tight font-medium">
|
|||
|
|
{blog.title}
|
|||
|
|
</h1>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex flex-col gap-8">
|
|||
|
|
<div className="space-y-2 text-start">
|
|||
|
|
<p className="text-lg text-muted-foreground">{blog.author}</p>
|
|||
|
|
<p className="text-muted-foreground">
|
|||
|
|
{blog.date} • {blog.readTime}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="space-y-4 text-start">
|
|||
|
|
<h3>{social.heading}</h3>
|
|||
|
|
<div className="flex gap-3">
|
|||
|
|
{social.links.map((link, index) => (
|
|||
|
|
<Button
|
|||
|
|
key={index}
|
|||
|
|
variant="outline"
|
|||
|
|
size="icon"
|
|||
|
|
className="group/btn h-12 w-12 rounded-full border-border/10 bg-muted/20 transition-colors hover:bg-transparent hover:text-muted"
|
|||
|
|
asChild
|
|||
|
|
>
|
|||
|
|
<a
|
|||
|
|
href={link.href}
|
|||
|
|
aria-label={link.label}
|
|||
|
|
className="flex items-center justify-center"
|
|||
|
|
>
|
|||
|
|
{getIcon(
|
|||
|
|
link.icon,
|
|||
|
|
"text-muted/30 group-hover/btn:text-primary-foreground transition-colors",
|
|||
|
|
)}
|
|||
|
|
</a>
|
|||
|
|
</Button>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="col-span-2 h-full w-full">
|
|||
|
|
<div className="aspect-video min-h-96 w-full">
|
|||
|
|
<img
|
|||
|
|
src={illustration.imageSrc}
|
|||
|
|
alt={illustration.imageAlt}
|
|||
|
|
className="h-full w-full object-cover"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="container mx-auto py-16 md:max-w-2xl xl:max-w-5xl">
|
|||
|
|
<div className="prose max-w-none pb-16 text-start prose-headings:text-foreground prose-p:text-muted-foreground prose-blockquote:border-s-primary prose-blockquote:text-muted-foreground prose-strong:text-foreground prose-em:text-foreground prose-ol:text-muted-foreground prose-ul:text-muted-foreground prose-li:text-muted-foreground">
|
|||
|
|
{blog.content}
|
|||
|
|
</div>
|
|||
|
|
<div className="flex flex-col justify-between gap-8 border-t border-border py-8 md:flex-row">
|
|||
|
|
<div className="flex items-center gap-3">
|
|||
|
|
<Avatar className="size-12 border xl:size-16">
|
|||
|
|
<AvatarImage src={blog.imageSrc} />
|
|||
|
|
<AvatarFallback>{blog.author}</AvatarFallback>
|
|||
|
|
</Avatar>
|
|||
|
|
<div className="text-start">
|
|||
|
|
<p className="font-medium">{blog.author}</p>
|
|||
|
|
<p className="text-sm text-muted-foreground">{blog.role}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="space-y-4 text-start">
|
|||
|
|
<h3>{social.heading}</h3>
|
|||
|
|
<div className="flex gap-3">
|
|||
|
|
{social.links.map((link, index) => (
|
|||
|
|
<Button
|
|||
|
|
key={index}
|
|||
|
|
variant="outline"
|
|||
|
|
size="icon"
|
|||
|
|
className="group/btn h-12 w-12 rounded-full border-border bg-muted transition-colors hover:bg-transparent hover:text-muted"
|
|||
|
|
asChild
|
|||
|
|
>
|
|||
|
|
<a
|
|||
|
|
href={link.href}
|
|||
|
|
aria-label={link.label}
|
|||
|
|
className="flex items-center justify-center"
|
|||
|
|
>
|
|||
|
|
{getIcon(
|
|||
|
|
link.icon,
|
|||
|
|
"text-muted-foreground group-hover/btn:text-primary transition-colors",
|
|||
|
|
)}
|
|||
|
|
</a>
|
|||
|
|
</Button>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export { Resource2 };
|