در این مقاله ، ما می آموزیم که monorepo چیست و چگونه monorepos در توسعه سریع برنامه ها با تجربه توسعه بهتر کمک می کند. ما در مورد مزایای استفاده از Nx ابزارهای توسعه برای مدیریت monorepo ، و یاد بگیرید که چگونه از آن ابزارها برای ایجاد یک Next.js کاربرد.
کد این مقاله در دسترس است GitHubبه می توانید نسخه نمایشی برنامه ای را که در حال ساخت آن هستیم پیدا کنید اینجابه
Monorepo چیست و چرا باید از آن استفاده کنیم
آ monorepo یک مخزن واحد است که شامل برنامه ها ، ابزارها و تنظیمات چندین پروژه یا اجزای پروژه است. این یک جایگزین برای ایجاد مخازن جداگانه برای هر پروژه یا بخشی از پروژه است.
سناریویی را در نظر بگیرید که در آن ما با استفاده از کتابخانه یا چارچوب اصلی یک برنامه داشبورد ایجاد می کنیم. ممکن است کد این برنامه جلویی در برنامه ذخیره شود dashboard
مخزن اجزای UI که این مخزن از آنها استفاده می کند ممکن است در مخزن دیگری به نام ذخیره شود components
به در حال حاضر ، هر بار که ما به روز رسانی components
مخزن ، ما باید وارد آن شویم dashboard
مخزن و به روز رسانی components
وابستگی
برای تسکین این مشکل ، می توانیم ادغام کنیم components
repo با dashboard
مخزن.
با این حال ، ممکن است یک برنامه پیش فرض دیگر برای سایت بازاریابی وجود داشته باشد که در آن ذخیره شده است marketing
مخزن و بستگی به آن دارد components
مخزن بنابراین ، ما باید کپی کنیم components
و با آن ادغام کنید marketing
همچنین. با این حال ، به همین دلیل ، هر گونه تغییر مربوط به components
باید در دو مکان ساخته شود ، که ایده آل نیست.
مشکل فوق را می توان با استفاده از monorepo ، جایی که dashboard
، components
و marketing
اجزاء در یک مخزن واحد قرار دارند.
مزایای مختلفی برای استفاده از monorepo وجود دارد:
- به روز رسانی بسته ها بسیار ساده تر است ، زیرا همه برنامه ها و کتابخانه ها در یک مخزن واحد قرار دارند. از آنجا که همه برنامه ها و بسته ها تحت یک مخزن یکسان هستند ، افزودن کد جدید یا اصلاح کد موجود را می توان به راحتی آزمایش و ارسال کرد.
- تغییر شکل کد بسیار ساده تر است ، زیرا ما مجبوریم این کار را در یک مکان واحد انجام دهیم به جای این که مطالب مشابه را در چندین مخزن تکرار کنیم.
- monorepo امکان پیکربندی مداوم برای خطوط لوله CI/CD را فراهم می آورد ، که می تواند توسط همه برنامه ها و کتابخانه های موجود در یک مخزن مجدد مورد استفاده قرار گیرد.
- انتشار بسته ها نیز به دلیل ابزارهایی مانند Nx بسیار آسان تر می شود.
این Nx CLI به ما در ایجاد برنامه های جدید Next.js و کتابخانه های کامپوننت React کمک می کند. همچنین به ما در اجرای یک وب سرور توسعه با بارگذاری مجدد ماژول کمک می کند. همچنین می تواند مجموعه ای از کارهای مهم دیگر مانند خط کشی ، قالب بندی و تولید کدبه مزیت استفاده از CLI مانند این این است که حس استانداردسازی را در پایگاه کد ما ایجاد می کند. همانطور که پایگاه کد ما رشد می کند ، مدیریت و درک پیچیدگی های اساسی بسیار دشوار است. Nx CLI با ارائه ابزارهایی برای ایجاد خودکار تولید کد ، اکثر این پیچیدگی ها را از بین می برد.
نرم افزار مورد نیاز
برای اجرای برنامه ما به موارد زیر نیاز داریم:
از این فناوری ها در برنامه استفاده می شود:
توجه: اگر می خواهید با این کار سرعت بیشتری کسب کنید ، می توانید نحوه نصب چندین نسخه Node.js را با استفاده از nvm بخوانید.
ما همچنین به یک مورد نیاز خواهیم داشت شکار محصول حساب.
نصب و راه اندازی بوت Nx Workspace
ما می توانیم آن را نصب کنیم Nx CLI با استفاده از دستور زیر:
npm install nx -g
دستور بالا Nx CLI را به صورت جهانی نصب می کند. این مفید است زیرا در حال حاضر ما می توانیم یک برنامه Next.js جدید با استفاده از این CLI از هر فهرست ایجاد کنیم.
بعد ، ما باید دستور زیر را در داخل پوشه ای که می خواهیم monorepo خود را ایجاد کنیم اجرا کنیم:
npx create-nx-workspace@latest nx-nextjs-monorepo
دستور بالا یک فضای کاری Nx ایجاد می کند. همه برنامه های Nx می توانند در داخل یک فضای کاری Nx قرار بگیرند.
ممکن است نیاز به تعویض داشته باشید nx-nextjs-monorepo
با نام فضای کار شما می توان نام آن را هر چیزی که دوست دارید بگذارید. نام فضای کار به طور کلی نام یک سازمان ، شرکت و غیره است.
وقتی دستور بالا را اجرا می کنیم ، مجموعه ای از مراحل به ما داده می شود که نوع برنامه هایی را که می خواهیم با Nx ایجاد کنیم ایجاد می کند.
-
مرحله 1: ابتدا از ما می پرسد که چه نوع برنامه ای را می خواهیم ایجاد کنیم. Next.js را از لیست گزینه ها انتخاب می کنیم.
-
گام 2: نام برنامه ای را که می خواهیم ایجاد کنیم از ما می خواهد. ما می توانیم آن را هر چیزی بنامیم. در این مورد ، ما از آن به عنوان “شکار محصول” نام می بریم.
-
مرحله 3: از ما می پرسد که می خواهیم از چه نوع شیوه نامه ای استفاده کنیم. ما Styled Components را انتخاب می کنیم.
-
مرحله 4: از ما می پرسد که آیا می خواهیم استفاده کنیم Nx Cloud، که بستری برای افزایش سرعت ساخت برنامه های Nx است. در این مورد ، ما No را انتخاب می کنیم ، اما لطفاً آن را بررسی کنید.
Nx اکنون همه فایلها و فهرستها را داربست کرده و ساختار زیر را برای ما ایجاد می کند.
این apps
فهرست شامل همه برنامه های کاربردی ما است. در مورد ما ، این فهرست شامل برنامه Next.js است که ما در حال ساخت آن هستیم (نام product-hunt
) این دایرکتوری همچنین شامل برنامه های آزمایشی سرتاسر (به نام product-hunt-e2e
) داربست با استفاده از سروبه
این libs
فهرست شامل همه کتابخانه ها مانند اجزا ، توابع مفید و غیره است. این کتابخانه ها می توانند توسط هر یک از برنامه های موجود در apps
فهرست راهنما.
این tools
فهرست شامل همه اسکریپت های سفارشی ، مدل های کد و غیره است که برای ایجاد تغییرات خاصی در پایگاه کد ما استفاده می شود.
توجه: اطلاعات بیشتر در مورد ساختار دایرکتوری در دسترس است اینجابه
ایجاد صفحه اول محصول شکار با استفاده از Next.js
در این مرحله ، ما می سازیم صفحه اول Producthuntبه ما داده ها را از API رسمی محصول شکاربه API محصول شکار رابط GraphQL را ارائه می دهد که در حال حاضر وجود دارد https://api.producthunt.com/v2/api/graphqlبه از طریق an قابل دسترسی است نشانه دسترسی، که می تواند از داشبورد API محصول Huntبه
برای ایجاد یک برنامه جدید ، باید بر روی آن کلیک کنیم افزودن یک برنامه کاربردی دکمه.
در مرحله بعد ، می توانیم یک نام برای برنامه خود و https: // localhost: 4200/ به عنوان Redirect URI برای برنامه جدید ما و روی آن کلیک کنید ایجاد برنامه دکمه.
اکنون می توانیم اعتبار برنامه جدید خود را مشاهده کنیم.
در مرحله بعد ، ما باید a را تولید کنیم توسعه دهنده توکن با کلیک بر روی TOKEN ایجاد کنید دکمه در همان صفحه
این یک توکن جدید ایجاد می کند و آن را در صفحه نشان می دهد.
در مرحله بعد ، ما باید این اطلاعات را در برنامه خود ذخیره کنیم. ما می توانیم یک جدید ایجاد کنیم .env.local
فایل داخل apps/product-hunt
فهرست با محتوای زیر:
// apps/product-hunt/.env.local
NEXT_PUBLIC_PH_API_ENDPOINT=https://api.producthunt.com/v2/api/graphql
NEXT_PUBLIC_PH_TOKEN=<your-developer-token>
از آنجا که API Product Hunt در GraphQL است ، باید چند بسته را نصب کنیم تا برنامه ما با GraphQL کار کند. برای نصب بسته های لازم ، از فهرست اصلی باید دستور زیر را اجرا کنیم:
yarn add graphql-hooks graphql-hooks-memcache
graphql-hooks حداقل مشتری اولین قلاب GraphQL است. این به ما در درخواست داده از سرور GraphQL کمک می کند.
graphql-hooks-memcache پیاده سازی حافظه پنهان برای حافظه است graphql-hooks
به
بعد ، ما باید کلاینت GraphQL را از graphql-hooks
بسته ما می توانیم با ایجاد یک مورد جدید این کار را انجام دهیم graphql-client.ts
فایل داخل apps/product-hunt/lib
فهرست با محتوای زیر:
import { GraphQLClient } from "graphql-hooks";
import memCache from "graphql-hooks-memcache";
import { useMemo } from "react";
let graphQLClient;
const createClient = (initialState) => {
return new GraphQLClient({
ssrMode: typeof window === "undefined",
url: process.env.NEXT_PUBLIC_PH_API_ENDPOINT,
cache: memCache({ initialState }),
headers: {
Authorization: `Bearer ${process.env.NEXT_PUBLIC_PH_TOKEN}`,
},
});
};
export const initializeGraphQL = (initialState = null) => {
const _graphQLClient = graphQLClient ?? createClient(initialState);
if (initialState && graphQLClient) {
graphQLClient.cache = memCache({
initialState: Object.assign(
graphQLClient.cache.getInitialState(),
initialState
),
});
}
if (typeof window === "undefined") {
return _graphQLClient;
}
if (!graphQLClient) {
graphQLClient = _graphQLClient;
}
return _graphQLClient;
};
export const useGraphQLClient = (initialState) => {
const store = useMemo(() => initializeGraphQL(initialState), [initialState]);
return store;
};
کد بالا شبیه کد زیر است مثال رسمی Next.js GraphQLبه ایده اصلی فایل فوق ایجاد یک سرویس گیرنده GraphQL است که به ما در درخواست داده از سرور GraphQL کمک می کند.
این createClient
تابع وظیفه ایجاد کلاینت GraphQL با استفاده از graphql-hooks
بسته
این initializeGraphQL
تابع مسئول راه اندازی اولیه سرویس گیرنده GraphQL ما با استفاده از است createClient
و همچنین هیدراته کردن مشتری GraphQL ما در سمت مشتری. این امر ضروری است زیرا ما از Next.js استفاده می کنیم ، که به ما امکان می دهد داده ها را در سمت سرویس گیرنده و سرور واکشی کنیم. بنابراین ، اگر داده ها در سمت سرور واکشی شوند ، طرف سرویس گیرنده نیز باید با همان داده ها بدون نیاز به سرور GraphQL هیدراته شود.
این useGraphQLClient
یک قلاب است که می تواند برای تولید سرویس گیرنده GraphQL استفاده شود.
در مرحله بعد ، ما همچنین باید یک فایل دیگر ایجاد کنیم ، graphql-request.ts
، درون apps/product-hunt/lib
فهرست با محتوای زیر:
const defaultOpts = {
useCache: true,
};
const graphQLRequest = async (client, query, options = defaultOpts) => {
const operation = {
query,
};
const cacheKey = client.getCacheKey(operation, options);
const cacheValue = await client.request(operation, options);
client.saveCache(cacheKey, cacheValue);
return cacheValue;
};
export default graphQLRequest;
این graphQLRequest
تابع مسئول برگرداندن نتیجه پرس و جو GraphQL و همچنین افزودن نتیجه به حافظه پنهان سرویس گیرنده GraphQL است.
کد بالا شبیه کد زیر است مثال رسمی Next.js GraphQLبه
بعد ، ما باید برنامه را به روز کنیم apps/product-hunt/pages/_app.tsx
فایل با محتوای زیر:
import { ClientContext } from "graphql-hooks";
import { AppProps } from "next/app";
import Head from "next/head";
import React from "react";
import { useGraphQLClient } from "../lib/graphql-client";
const NextApp = ({ Component, pageProps }: AppProps) => {
const graphQLClient = useGraphQLClient(pageProps.initialGraphQLState);
return (
<ClientContext.Provider value={graphQLClient}>
<Head>
<title>Welcome to product-hunt!</title>
</Head>
<Component {...pageProps} />
</ClientContext.Provider>
);
};
export default NextApp;
کد بالا اطمینان حاصل می کند که کل برنامه ما به آن دسترسی دارد ارائه دهنده زمینه GraphQL با پیچاندن برنامه ما با ClientContext.Provider
به
در مرحله بعد ، ما باید یک فایل دیگر ایجاد کنیم ، all-posts.ts
، درون apps/product-hunt/queries
فهرست با محتوای زیر:
const ALL_POSTS_QUERY = `
query allPosts {
posts {
edges {
node {
id
name
description
votesCount
website
thumbnail {
url
}
}
}
}
}
`;
export default ALL_POSTS_QUERY;
پرس و جو GraphQL فوق به ما اجازه می دهد تا همه پست ها را از نقطه پایانی ProductHunt GraphQL API واکشی کنیم.
بیایید یک مورد جدید نیز ایجاد کنیم product.ts
فایل داخل apps/product-hunt/types
دایرکتوری با محتوای زیر برای تعریف Product
نوع:
export default interface Product {
id: number;
name: string;
tagline: string;
slug: string;
thumbnail: {
image_url: string;
};
user: {
avatar_url: string;
name: string;
};
}
کد بالا کد را اضافه می کند انواع TypeScript برای Product
به یک محصول می تواند دارای شناسه ، نام ، نشان ، اسلاگ ، تصویر کوچک و کاربر باشد. اینگونه است که Product Hunt GraphQL داده ها را برمی گرداند.
بعد ، ما باید برنامه را به روز کنیم apps/product-hunt/pages/index.tsx
فایل با محتوای زیر:
import { useQuery } from "graphql-hooks";
import { GetStaticProps, NextPage } from "next";
import Image from "next/image";
import React from "react";
import { initializeGraphQL } from "../lib/graphql-client";
import graphQLRequest from "../lib/graphql-request";
import {
StyledCard,
StyledCardColumn,
StyledCardLink,
StyledCardRow,
StyledCardTagline,
StyledCardThumbnailContainer,
StyledCardTitle,
StyledContainer,
StyledGrid,
} from "../public/styles";
import ALL_POSTS_QUERY from "../queries/all-posts";
import Product from "../types/product";
interface IProps {
hits: Product[];
}
const ProductsIndexPage: NextPage<IProps> = () => {
const { data } = useQuery(ALL_POSTS_QUERY);
return (
<StyledContainer>
<StyledGrid>
{data.posts.edges.map(({ node }) => {
return (
<StyledCardLink key={node.id} href={node.website} target="_blank">
<StyledCard>
<StyledCardColumn>
<StyledCardThumbnailContainer>
<Image src={node.thumbnail.url} layout="fill" />
</StyledCardThumbnailContainer>
</StyledCardColumn>
<StyledCardColumn>
<StyledCardRow>
<StyledCardTitle>{node.name}</StyledCardTitle>
<StyledCardTagline>{node.description}</StyledCardTagline>
</StyledCardRow>
</StyledCardColumn>
</StyledCard>
</StyledCardLink>
);
})}
</StyledGrid>
</StyledContainer>
);
};
export const getStaticProps: GetStaticProps = async () => {
const client = initializeGraphQL();
await graphQLRequest(client, ALL_POSTS_QUERY);
return {
props: {
initialGraphQLState: client.cache.getInitialState(),
},
revalidate: 60,
};
};
export default ProductsIndexPage;
در قطعه کد بالا ، ما دو کار را انجام می دهیم:
-
ما داده ها را از طریق واکشی می کنیم
ALL_POSTS_QUERY
پرس و جو GraphQL و سپس ما در حال نقشه برداری بر رویdata
آرایه توسط API ProductHunt باز می گردد. -
ما داده ها را واکشی می کنیم در زمان ساخت از طریق getStaticProps، که یک تابع Next.js است. با این حال ، اگر داده ها را در زمان ساخت خود واکشی کنیم ، ممکن است داده ها منسوخ شوند. بنابراین ، ما از
revalidate
گزینه. اعتبار مجدد مقدار اختیاری (در ثانیه) و پس از آن ایجاد مجدد صفحه می تواند رخ دهد. این نیز به عنوان شناخته می شود بازسازی استاتیک افزایشیبه
بیایید همچنین سبک ها را با افزودن محتوای زیر در داخل apps/product-hunt/public/styles.ts
فایل:
import styled from "styled-components";
export const StyledContainer = styled.div`
padding: 24px;
max-width: 600px;
margin: 0 auto;
font-family: sans-serif;
`;
export const StyledGrid = styled.div`
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
grid-gap: 24px;
`;
export const StyledCardLink = styled.a`
text-decoration: none;
color: #000;
`;
export const StyledCard = styled.div`
display: flex;
gap: 12px;
padding: 12px;
background-color: #f7f7f7;
`;
export const StyledCardColumn = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
justify-content: space-between;
`;
export const StyledCardRow = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
`;
export const StyledCardThumbnailContainer = styled.div`
object-fit: cover;
width: 150px;
height: 150px;
position: relative;
`;
export const StyledCardTitle = styled.div`
font-size: 18px;
font-weight: bold;
`;
export const StyledCardTagline = styled.div`
font-size: 14px;
line-height: 1.5;
`;
حالا اگر بدویم yarn start
دستور داخل پنجره ترمینال جدید ، صفحه زیر را مشاهده می کنیم http: // localhost: 4200/به
برای برطرف کردن مشکل فوق ، باید برنامه خود را به روز کنیم apps/product-hunt/next.config.js
فایل با محتوای زیر:
const withNx = require("@nrwl/next/plugins/with-nx");
module.exports = withNx({
nx: {
svgr: true,
},
images: {
domains: ["ph-files.imgix.net", "ph-avatars.imgix.net"],
},
});
اضافه کردیم دامنه ها که از آن Product Hunt API تصاویر را دریافت می کند. این ضروری است زیرا ما از آن استفاده می کنیم جزء تصویر بعدیبه
حال ، اگر سرور خود را مجدداً راه اندازی کنیم ، باید بتوانیم صفحه زیر را در آن مشاهده کنیم http: // localhost: 4200/به
ایجاد کتابخانه اجزای قابل استفاده مجدد
ما با موفقیت صفحه اول Product Hunt را ایجاد کردیم. با این حال ، ما می توانیم ببینیم که همه سبک های ما تحت یک برنامه واحد هستند. بنابراین ، اگر بخواهیم از همان سبک ها هنگام ساختن برنامه دیگری استفاده کنیم ، باید این سبک ها را در برنامه جدید کپی کنیم.
یکی از راه های حل این مسئله ایجاد کتابخانه اجزای جداگانه و ذخیره این سبک ها در آنجا است. آن کتابخانه کامپوننت را می توان با برنامه های متعدد مجدداً استفاده کرد.
برای ایجاد یک کتابخانه React جدید در Nx ، می توانیم موارد زیر را اجرا کنیم فرمان از ریشه پروژه ما:
nx generate @nrwl/react:library components
دستور بالا فوری را در تصویر زیر به ما می دهد.
از آنجا که از Styled Components استفاده می کنیم ، آن گزینه را در اعلان بالا انتخاب می کنیم. پس از انتخاب آن گزینه ، تغییرات زیر را در ترمینال خود مشاهده می کنیم.
در مرحله بعد ، همه استایل ها را از کپی می کنیم apps/product-hunt/public/styles.ts
به درون libs/components/src/lib/components.tsx
فایل.
ما همچنین باید همه سبک ها را از این کتابخانه وارد کنیم. برای انجام این کار ، ما باید برنامه خود را تغییر دهیم apps/product-hunt/pages/index.tsx
فایل:
import {
StyledCard,
StyledCardColumn,
StyledCardLink,
StyledCardRow,
StyledCardTagline,
StyledCardThumbnailContainer,
StyledCardTitle,
StyledContainer,
StyledGrid,
} from "@nx-nextjs-monorepo/components";
اگر به وضعیت خودمان نگاه کنیم tsconfig.base.json
فایل ، خط زیر را مشاهده می کنیم:
"paths": {
"@nx-nextjs-monorepo/components": ["libs/components/src/index.ts"]
}
@nx-nextjs-monorepo/components
نام کتابخانه اجزای ما است. بنابراین ، ما همه سبک ها را از آن کتابخانه در وارد کرده ایم apps/product-hunt/pages/index.tsx
فایل.
ما می توانیم حذف کنیم apps/product-hunt/public/styles.ts
فایل ، زیرا دیگر به آن نیاز نداریم
اکنون ، اگر سرور Nx خود را مجدداً راه اندازی کنیم ، صفحه زیر را مشاهده می کنیم http: // localhost: 4200/به
نتیجه
در این مقاله ، ما آموخته ایم که چگونه می توانیم از Nx برای ایجاد monorepo با Next.js و Styled Components استفاده کنیم. ما همچنین آموخته ایم که چگونه استفاده از monorepos می تواند تجربه توسعه و سرعت ساخت برنامه های کاربردی را بهبود بخشد. ما یک برنامه Next.js و یک کتابخانه Styled Components ایجاد کرده ایم ، اما با استفاده از Nx ، امکان ایجاد زاویه دار، سرو، لانه، گتسبی، بیان و کتاب داستان برنامه های کاربردی با استفاده از ژنراتورهای خود
و فراموش نکنید: کد این مقاله در دسترس است GitHub، و می توانید نسخه نمایشی برنامه را پیدا کنید اینجابه