paint-brush
Vite, Cloudflare, Remix, PNPM और Turborepo के साथ मोनोरेपो कैसे बनाएं (बिल्डिंग स्टेप नहीं)द्वारा@josejaviasilis
1,087 रीडिंग
1,087 रीडिंग

Vite, Cloudflare, Remix, PNPM और Turborepo के साथ मोनोरेपो कैसे बनाएं (बिल्डिंग स्टेप नहीं)

द्वारा Jose Javi Asilis19m2024/08/28
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

यह रीमिक्स के वीट क्लोडुफ्लेयर डिप्लॉयमेंट के लिए बिना किसी बिल्ड स्टेप के मोनोरेपो बनाता है। यह आपको इसे कई लक्ष्यों तक विस्तारित करने की अनुमति देता है
featured image - Vite, Cloudflare, Remix, PNPM और Turborepo के साथ मोनोरेपो कैसे बनाएं (बिल्डिंग स्टेप नहीं)
Jose Javi Asilis HackerNoon profile picture
0-item




परिचय

मुझे न्यूनतम कॉन्फ़िगरेशन के साथ Vite और Cloudflare Workers-Pages के साथ Remix का उपयोग करने का एक तरीका चाहिए था।


मैंने अन्य रिपॉजिटरी भी देखीं, जैसे:


लेकिन उनकी कुछ सीमाएँ थीं:

  1. मैं इसे पहले से बनाना नहीं चाहता था, क्योंकि मैं रिपॉजिटरीज में और अधिक कॉन्फ़िगरेशन फ़ाइलें नहीं डालना चाहता था।


  2. क्लाउडफ्लेयर वर्कर्स/पेजेस का लक्ष्य अलग है। इसे tsup के साथ लक्षित करना मुश्किल हो गया, क्योंकि पोस्टग्रेस जैसे पैकेज रीमिक्स में आयात किए जाने पर नोड निर्भरता को तोड़ देंगे।


  3. मुझे विभिन्न लक्ष्यों (रीमिक्स-क्लाउडफ्लेयर, नोड/बुन) का उपभोग करने का एक तरीका भी चाहिए था


फिर भी, मैं उनका धन्यवाद करता हूं, क्योंकि उन्होंने इसे संभव बनाने का मार्ग प्रशस्त किया!


नीचे दिए गए नुकसान वाले अनुभाग को अवश्य पढ़ें!

सोशल मीडिया पर मुझे फॉलो करें!

मैं उत्पादन में उन 1% त्रुटियों को पकड़ने के लिए सार्वजनिक रूप से एक स्वचालित परीक्षण मंच का निर्माण कर रहा हूं।


मैं अपनी प्रगति साझा करता हूँ:


X/ट्विटर @javiasilis

लिंक्डइन @javiasilis

GitHub रिपॉजिटरी

आप यहां पूर्ण कार्यान्वयन देख सकते हैं।

क्रमशः

आवश्यकताएं

  1. नोडजेएस
  2. पीएनपीएम
  3. Docker (वैकल्पिक - स्थानीय डेटाबेस उदाहरण के लिए)


यद्यपि यह आपको एक नए मोनो-रिपॉजिटरी के माध्यम से ले जाता है, लेकिन मौजूदा को एक में बदलने के लिए यह पूरी तरह से वैध है।


यह भी मान लिया जाएगा कि आपके पास मोनो रेपो का कुछ ज्ञान है।


टिप्पणी:

  • "रूट पर" आपके मोनोरेपॉजिटरी के शुरुआती पथ को संदर्भित करता है। इस प्रोजेक्ट के लिए, यह libs और packages निर्देशिकाओं के बाहर होगा।

टर्बोरेपो स्थापित करें

टर्बोरेपो आपके पैकेज मैनेजर के वर्कस्पेस के ऊपर काम करता है ताकि आपके प्रोजेक्ट की स्क्रिप्ट और आउटपुट को मैनेज किया जा सके (यह आपके आउटपुट को कैश भी कर सकता है)। अब तक, यह रश (जिसे मैंने आजमाया नहीं है और मुझे पसंद नहीं है) के अलावा एकमात्र मोनो-रेपो टूल है जो काम करने में सक्षम है।


NX में रीमिक्स का Vite समर्थन नहीं है (इस लेखन के अनुसार - 28 अगस्त, 2024)।


https://turbo.build/

 pnpm dlx create-turbo@latest

1. PNPM कार्यस्थान कॉन्फ़िगर करें

हम निर्भरताओं के प्रबंधन के लिए PNPM की कार्यक्षेत्र क्षमताओं का उपयोग करेंगे।


अपनी मोनोरेपो निर्देशिका पर, pnpm-workspace.yaml बनाएं।


इसके अंदर जोड़ें:

 packages: - "apps/*" - "libs/*"


यह pnpm को बताएगा कि सभी रिपॉजिटरी apps और libs अंदर होंगी। ध्यान दें कि libs या packages (जैसा कि आपने कहीं और देखा होगा) का उपयोग करना कोई मायने नहीं रखता।

2. प्रोजेक्ट के मूल में एक खाली package.json बनाएं:

 pnpm init
 { "name": "@repo/main", "version": "1.0.0", "scripts": {}, "keywords": [], "author": "", "license": "ISC" }


name:@repo/main यह हमें बताता है कि यह एप्लिकेशन की मुख्य प्रविष्टि है। आपको किसी विशेष परंपरा का पालन करने या @ उपसर्ग का उपयोग करने की आवश्यकता नहीं है। लोग इसे स्थानीय/दूरस्थ पैकेजों से अलग करने या इसे किसी संगठन में समूहीकृत करना आसान बनाने के लिए इसका उपयोग करते हैं।

3. प्रोजेक्ट के रूट में turbo.json फ़ाइल बनाएँ:

 { "$schema": "https://turbo.build/schema.json", "tasks": { "build": {}, "dev": { "cache": false, "persistent": true }, "start": { "dependsOn": ["^build"], "persistent": true }, "preview": { "cache": false, "persistent": true }, "db:migrate": {} } }


टर्बो.json फ़ाइल टर्बो रेपो को बताती है कि हमारे आदेशों की व्याख्या कैसे की जाए। tasks कुंजी के अंदर जो कुछ भी है वह सभी package.json में पाए जाने वाले से मेल खाएगा।


ध्यान दें कि हमने चार कमांड परिभाषित किए हैं। ये प्रत्येक रिपॉजिटरी के package.json के स्क्रिप्ट सेक्शन में मौजूद कमांड से मेल खाते हैं। हालाँकि, सभी package.json को इन कमांड को लागू करना ज़रूरी नहीं है।


उदाहरण: dev कमांड को turbo dev द्वारा ट्रिगर किया जाएगा, और यह उन सभी पैकेजों को निष्पादित करेगा जो dev package.json में पाए जाते हैं। यदि आप इसे turbo में शामिल नहीं करते हैं, तो यह निष्पादित नहीं होगा।

4. प्रोजेक्ट के रूट में एक apps फ़ोल्डर बनाएँ

 mkdir apps

5. apps फ़ोल्डर में रीमिक्स ऐप बनाएं (या मौजूदा ऐप को स्थानांतरित करें)

 npx create-remix --template edmundhung/remix-worker-template


जब यह आपसे Install any dependencies with npm के लिए कहता है तो 'नहीं' कहें।


  • यह इस तरह दिखना चाहिए

6. package.json का name बदलकर @repo/my-remix-cloudflare-app (या आपका नाम) रखें

 { - "name": "my-remix-cloudflare-app", + "name": "@repo/my-remix-cloudflare-app", "version": "1.0.0", "keywords": [], "author": "", "license": "ISC" }

7. apps/<app>/package.json से Dependencies और devDependencies को रूट के package.json में कॉपी करें

उदाहरण:

<रूट>/package.json

 { "name": "@repo/main", "version": "1.0.0", "scripts": {}, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@markdoc/markdoc": "^0.4.0", "@remix-run/cloudflare": "^2.8.1", "@remix-run/cloudflare-pages": "^2.8.1", "@remix-run/react": "^2.8.1", "isbot": "^3.6.5", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@cloudflare/workers-types": "^4.20240222.0", "@octokit/types": "^12.6.0", "@playwright/test": "^1.42.1", "@remix-run/dev": "^2.8.1", "@remix-run/eslint-config": "^2.8.1", "@tailwindcss/typography": "^0.5.10", "@types/react": "^18.2.64", "@types/react-dom": "^18.2.21", "autoprefixer": "^10.4.18", "concurrently": "^8.2.2", "cross-env": "^7.0.3", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "husky": "^9.0.11", "lint-staged": "^15.2.2", "msw": "^2.2.3", "postcss": "^8.4.35", "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.12", "rimraf": "^5.0.5", "tailwindcss": "^3.4.1", "typescript": "^5.4.2", "vite": "^5.1.5", "vite-tsconfig-paths": "^4.3.1", "wrangler": "^3.32.0" } }


8. रूट स्तर पर टर्बो को एक डेवडिपेंडेंसी के रूप में जोड़ें (यह सभी रीमिक्स पैकेज स्थापित करेगा)।

सत्यापित करें कि टर्बो package.json के devDependencies के अंदर है। यदि यह सूचीबद्ध नहीं है, तो निम्न आदेश निष्पादित करें:

 pnpm add turbo -D -w


-w ध्वज pnpm को इसे कार्यक्षेत्र रूट पर स्थापित करने के लिए कहता है।

9. रूट package.json में निम्नलिखित प्रविष्टियाँ जोड़ें

  • scripts में dev कमांड जोड़ें

  • packageManager को विकल्प में जोड़ें


 { "name": "@repo/main", "version": "1.0.0", "scripts": { "dev": "turbo dev" }, "keywords": [], "author": "", "license": "ISC", "packageManager": "[email protected]", "dependencies": { // omitted for brevity }, "devDependencies": { // omitted for brevity } }

10. pnpm dev चलाकर सत्यापित करें कि सब कुछ काम कर रहा है

 pnpm dev

11. प्रोजेक्ट के रूट पर Libs फ़ोल्डर बनाएँ। कॉन्फ़िगरेशन, db और utils जोड़ें:

 mkdir -p libs/config libs/db libs/utils

12. प्रत्येक पैकेज के लिए src/index.ts जोड़ें।

 touch libs/config/src/index.ts libs/db/src/index.ts libs/utils/src/index.ts
  • सभी पैकेजों को निर्यात करने के लिए index.ts फ़ाइल का उपयोग किया जाएगा।
  • हम सब कुछ संक्षिप्त बनाने के लिए फ़ोल्डर को प्रवेश बिंदु के रूप में उपयोग करेंगे।
  • यह एक परम्परा है और आप इसका पालन न करने का विकल्प चुन सकते हैं।

13. एक खाली package.json बनाएं, और libs/config/package.json फ़ाइल में निम्नलिखित जोड़ें:

 { "name": "@repo/config", "version": "1.0.0", "type": "module", "exports": { ".": { "import": "./src/index.ts", "default": "./src/index.ts" } } }

14. libs/db/package.json के लिए भी यही करें:

 { "name": "@repo/db", "version": "1.0.0", "exports": { ".": { "import": "./src/index.ts", "default": "./src/index.ts" } } }

15. और libs/utils/package.json :

 { "name": "@repo/utils", "version": "1.0.0", "exports": { ".": { "import": "./src/index.ts", "default": "./src/index.ts" } } }


  • हम “एक्सपोर्ट” फ़ील्ड निर्दिष्ट करते हैं। यह अन्य रिपॉजिटरी को बताता है कि पैकेज को कहाँ से आयात करना है।
  • हम “नाम” फ़ील्ड निर्दिष्ट करते हैं। इसका उपयोग पैकेज को स्थापित करने और इसे अन्य रिपॉजिटरी में संदर्भित करने के लिए किया जाता है।

16. (DB) - ड्रिज़ल और पोस्टग्रेज़ जोड़ें

टिप्पणियाँ:

  • मैं ORM से घृणा करने लगा हूँ। मैंने 6 अलग-अलग ORM सीखने में 10 साल से ज़्यादा का समय बिताया है, और यह ऐसा ज्ञान है जिसे आप हस्तांतरित नहीं कर सकते।

  • जब नई तकनीकें आती हैं तो आपको समस्याएँ होती हैं। Prisma क्लाउडफ्लेयर वर्कर्स को बॉक्स से बाहर समर्थन नहीं करता है।

  • एलएलएम के साथ, जटिल SQL क्वेरीज़ लिखना पहले से कहीं अधिक आसान हो गया है।

  • SQL सीखना एक सार्वभौमिक भाषा है और इसमें कोई परिवर्तन होने की सम्भावना नहीं है।


 pnpm add drizzle-orm drizle-kit --filter=@repo/db


वर्कस्पेस स्तर पर Postgres स्थापित करें। नुकसान अनुभाग देखें

 pnma add postgres -w


टिप्पणियाँ:

  • --filter=@repo/db फ्लैग pnpm को पैकेज को db रिपोजिटरी में जोड़ने के लिए कहता है।

17. dotenv को वर्कस्पेस रिपॉजिटरी में जोड़ें

 pnpm add dotenv -w

नोट्स

  • -w फ्लैग pnpm को रूट के package.json पर इसे स्थापित करने के लिए कहता है

18. कॉन्फ़िगरेशन प्रोजेक्ट को सभी प्रोजेक्ट्स में जोड़ें।

 pnpm add @repo/config -r --filter=!@repo/config

टिप्पणियाँ :

  • -r फ्लैग pnpm को पैकेज को सभी रिपॉजिटरी में जोड़ने के लिए कहता है।
  • --filter=! ध्वज pnpm को कॉन्फ़िगरेशन रिपोजिटरी को बाहर करने के लिए कहता है।
  • पैकेज नाम से पहले ! पर ध्यान दें

19. (वैकल्पिक) क्या ऊपर दिए गए कमांड काम नहीं करते? .npmrc का उपयोग करें

यदि pnpm रिपोजिटरी से पैकेज खींच रहा है, तो हम प्रोजेक्ट के रूट पर एक .npmrc फ़ाइल बना सकते हैं।


.npmrc

 link-workspace-packages= true prefer-workspace-packages=true


  • यह pnpm को पहले वर्कस्पेस पैकेजों का उपयोग करने के लिए कहेगा।
  • Reddit के ZoWnx को धन्यवाद, जिन्होंने मुझे .nprmc फ़ाइल बनाने में मदद की

20. Libs/Config के अंदर साझा tsconfig.json कॉन्फ़िगर करें

pnpm वर्कस्पेस की शक्ति का उपयोग करके, आप कॉन्फ़िगरेशन फ़ाइलें बना सकते हैं जिन्हें परियोजनाओं में साझा किया जा सकता है।


हम एक आधार tsconfig.lib.json बनाएंगे जिसका उपयोग हम अपनी लाइब्रेरीज़ के लिए करेंगे।


libs/config के अंदर tsconfig.lib.json को तत्काल बनाएं:

 touch "libs/config/tsconfig.base.lib.json"


फिर, निम्नलिखित जोड़ें:

tsconfig.base.lib.json

 { "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "lib": ["ES2022"], "module": "ESNext", "moduleResolution": "Bundler", "resolveJsonModule": true, "target": "ES2022", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "allowImportingTsExtensions": true, "allowJs": true, "noUncheckedIndexedAccess": true, "noEmit": true, "incremental": true, "composite": false, "declaration": true, "declarationMap": true, "inlineSources": false, "isolatedModules": true, "noUnusedLocals": false, "noUnusedParameters": false, "preserveWatchOutput": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "sourceMap": true, } } 


21. db कनेक्शन को db रिपॉजिटरी में जोड़ें।

 // libs/db/drizzle.config.ts (Yes, this one is at root of the db package, outside the src folder) // We don't want to export this file as this is ran at setup. import "dotenv/config"; // make sure to install dotenv package import { defineConfig } from "drizzle-kit"; export default defineConfig({ dialect: "postgresql", out: "./src/generated", schema: "./src/drizzle/schema.ts", dbCredentials: { url: process.env.DATABASE_URL!, }, // Print all statements verbose: true, // Always ask for confirmation strict: true, });


स्कीमा फ़ाइल:

 // libs/db/src/drizzle/schema.ts export const User = pgTable("User", { userId: char("userId", { length: 26 }).primaryKey().notNull(), subId: char("subId", { length: 36 }).notNull(), // We are not making this unique to support merging accounts in later // iterations email: text("email"), loginProvider: loginProviderEnum("loginProvider").array().notNull(), createdAt: timestamp("createdAt", { precision: 3, mode: "date" }).notNull(), updatedAt: timestamp("updatedAt", { precision: 3, mode: "date" }).notNull(), });


क्लाइंट फ़ाइल:

 // libs/db/src/drizzle-client.ts import { drizzle, PostgresJsDatabase } from "drizzle-orm/postgres-js"; import postgres from "postgres"; import * as schema from "./schema"; export type DrizzleClient = PostgresJsDatabase<typeof schema>; let drizzleClient: DrizzleClient | undefined; type GetClientInput = { databaseUrl: string; env: string; mode?: "cloudflare" | "node"; }; declare var window: typeof globalThis; declare var self: typeof globalThis; export function getDrizzleClient(input: GetClientInput) { const { mode, env } = input; if (mode === "cloudflare") { return generateClient(input); } const globalObject = typeof globalThis !== "undefined" ? globalThis : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : self; if (env === "production") { drizzleClient = generateClient(input); } else if (globalObject) { if (!(globalObject as any).__db__) { (globalObject as any).__db__ = generateClient(input); } drizzleClient = (globalObject as any).__db__; } else { drizzleClient = generateClient(input); } return drizzleClient; } type GenerateClientInput = { databaseUrl: string; env: string; }; function generateClient(input: GenerateClientInput) { const { databaseUrl, env } = input; const isLoggingEnabled = env === "development"; // prepare: false for serverless try { const client = postgres(databaseUrl, { prepare: false }); const db = drizzle(client, { schema, logger: isLoggingEnabled }); return db; } catch (e) { console.log("ERROR", e); return undefined!; } }


माइग्रेशन फ़ाइल:

 // libs/db/src/drizzle/migrate.ts import { config } from "dotenv"; import { migrate } from "drizzle-orm/postgres-js/migrator"; import postgres from "postgres"; import { drizzle } from "drizzle-orm/postgres-js"; import "dotenv/config"; import path from "path"; config({ path: "../../../../apps/my-remix-cloudflare-app/.dev.vars" }); const ssl = process.env.ENVIRONMENT === "development" ? undefined : "require"; const databaseUrl = drizzle( postgres(`${process.env.DATABASE_URL}`, { ssl, max: 1 }) ); // Somehow the current starting path is /libs/db // Remember to have the DB running before running this script const migration = path.resolve("./src/generated"); const main = async () => { try { await migrate(databaseUrl, { migrationsFolder: migration, }); console.log("Migration complete"); } catch (error) { console.log(error); } process.exit(0); }; main();

इसे माइग्रेशन के बाद निष्पादित किया जाना चाहिए


और क्लाइंट और स्कीमा को src/index.ts फ़ाइल में निर्यात करें। अन्य को विशिष्ट समय पर चलाया जाता है।

 // libs/db/src/index.ts export * from "./drizzle/drizzle-client"; export * from "./drizzle/schema "


अपने package.json में, drizzle-kit generate और माइग्रेशन कमांड चलाने के लिए कोड जोड़ें:

 { "name": "@repo/db", "version": "1.0.0", "main": "./src/index.ts", "module": "./src/index.ts", "types": "./src/index.ts", "scripts": { "db:generate": "drizzle-kit generate", "db:migrate": "dotenv tsx ./drizzle/migrate", }, "exports": { ".": { "import": "./src/index.ts", "default": "./src/index.ts" } }, "dependencies": { "@repo/configs": "workspace:^", "drizzle-kit": "^0.24.1", "drizzle-orm": "^0.33.0", }, "devDependencies": { "@types/node": "^22.5.0" } }

22. libs/db और libs/utils के लिए साझा tsconfig.json उपयोग करें

libs/db और libs/utils के लिए tsconfig.json बनाएँ

 touch "libs/db/tsconfig.json" "libs/utils/tsconfig.json"


फिर प्रत्येक में जोड़ें:

 { "extends": "@repo/configs/tsconfig.base.lib.json", "include": ["./src"], }
  • देखें कि @repo/configs उपयोग हमारे tsconfig.base.lib.json को संदर्भित करने के लिए पथ के रूप में किया जाता है।
  • यह हमारा मार्ग स्वच्छ बनाता है।

23. टीएसएक्स स्थापित करें

टाइपस्क्रिप्ट एक्ज़ीक्यूट (TSX) ts-node का एक लाइब्रेरी विकल्प है। हम इसका उपयोग ड्रिज़ल के माइग्रेशन को निष्पादित करने के लिए करेंगे।

 pnpm add tsx -D --filter=@repo/db

24. libs/db डायरेक्टरी में एक खाली .env जोड़ें

 touch "libs/db/.env"


निम्नलिखित सामग्री जोड़ें:

 DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" NODE_ENV="development" MODE="node" 


यह कुछ इस तरह दिखना चाहिए


25. हमारे रीमिक्स प्रोजेक्ट में libs/db रिपॉजिटरी जोड़ें

प्रोजेक्ट के मूल से चलाएँ:

 pnpm add @repo/db --filter=@repo/my-remix-cloudflare-app


यदि यह काम नहीं करता है, तो apps/my-remix-cloudflare-app के package.json पर जाएं, और निर्भरता को मैन्युअल रूप से जोड़ें।

 { "name": "@repo/my-remix-cloudflare-app", "version": "1.0.0", "dependencies": { "@repo/db": "workspace:*" } }

वर्शन फ़ील्ड में workspace:* पर ध्यान दें। यह pnpm को वर्कस्पेस में पैकेज के किसी भी वर्शन का उपयोग करने के लिए कहता है।


यदि आपने इसे pnpm add, आपको संभवतः workspace:^ जैसा कुछ दिखाई देगा। जब तक आप स्थानीय पैकेज संस्करणों को नहीं बढ़ाते हैं, तब तक इससे कोई फर्क नहीं पड़ता है।


यदि आपने इसे मैन्युअल रूप से जोड़ा है, तो प्रोजेक्ट के रूट से pnpm install चलाएँ।


हमें अपने प्रोजेक्ट में @repo/db का उपयोग करने में सक्षम होना चाहिए।

26. हमारे यूटिलिटीज में कुछ साझा कोड जोड़ें:

इस कोड को libs/utils/src/index.ts फ़ाइल में जोड़ें:

 // libs/utils/src/index.ts export function hellowWorld() { return "Hello World!"; }


27. हमारे रीमिक्स ऐप में लाइब्रेरी/यूटिलिटीज इंस्टॉल करें:

 pnpm add @repo/db --filter=@repo/my-remix-cloudflare-app

28. (वैकल्पिक) Docker कंटेनर से Postgres लॉन्च करें

यदि आपके पास Postgres इंस्टेंस नहीं चल रहा है, तो हम docker-compose का उपयोग करके इसे लॉन्च कर सकते हैं। ध्यान दें, मैं मान रहा हूँ कि आप Docker जानते हैं।


प्रोजेक्ट के मूल में docker-compose.yml फ़ाइल बनाएँ.

 # Auto-generated docker-compose.yml file. version: '3.8' # Define services. services: postgres: image: postgres:latest restart: always environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_DB=postgres ports: - "5432:5432" volumes: - ./postgres-data:/var/lib/postgresql/data pgadmin: # To connect PG Admin, navigate to http://localhost:8500 use: # host.docker.internal # postgres # (username) postgres # (password) postgres image: dpage/pgadmin4 ports: - "8500:80" environment: PGADMIN_DEFAULT_EMAIL: [email protected] PGADMIN_DEFAULT_PASSWORD: admin


फिर आप चला सकते हैं:

 docker-compose up -d

-d फ्लैग docker-compose को अलग से चलने के लिए कहता है ताकि आप फिर से अपने टर्मिनल तक पहुंच सकें।

29. DB स्कीमा उत्पन्न करें

अब, libs/db रिपोजिटरी पर जाएँ और db:generate चलाएँ।

 cd `./libs/db` && pnpm db:generate
  • ध्यान दें कि db:generate एक उपनाम है: drizzle-kit generate
  • सत्यापित करें कि आपके पास उचित .env है.
  • इसके अतिरिक्त, यह मानता है कि आपके पास एक Postgres इंस्टेंस चल रहा है।

30. माइग्रेशन चलाएं.

हमें अपने डेटाबेस के भीतर सभी तालिकाओं को स्कैफोल्ड करने के लिए माइग्रेशन चलाने की आवश्यकता है।


libs/db रिपोजिटरी पर जाएं (यदि आप वहां नहीं हैं) और db:generate चलाएं।

 cd `./libs/db` && pnpm db:migrate
  • ध्यान दें कि db:migrate एक उपनाम है: dotenv tsx ./drizzle/migrate
  • सत्यापित करें कि आपके पास उचित .env है.
  • इसके अतिरिक्त, यह मानता है कि आपके पास एक Postgres इंस्टेंस चल रहा है।

31. अपने रीमिक्स ऐप के अंदर एक DB कॉल डालें।

 // apps/my-remix-cloudflare-app/app/routes/_index.tsx import type { LoaderFunctionArgs } from '@remix-run/cloudflare'; import { json, useLoaderData } from '@remix-run/react'; import { getDrizzleClient } from '@repo/db'; import { Markdown } from '~/components'; import { getFileContentWithCache } from '~/services/github.server'; import { parse } from '~/services/markdoc.server'; export async function loader({ context }: LoaderFunctionArgs) { const client = await getDrizzleClient({ databaseUrl: context.env.DATABASE_URL, env: 'development', mode: 'cloudflare', }); if (client) { const res = await client.query.User.findFirst(); console.log('res', res); } const content = await getFileContentWithCache(context, 'README.md'); return json( { content: parse(content), // user: firstUser, }, { headers: { 'Cache-Control': 'public, max-age=3600', }, }, ); } export default function Index() { const { content } = useLoaderData<typeof loader>(); return <Markdown content={content} />; }


  • ध्यान रखें कि हम यहां सर्वोत्तम प्रथाओं का पालन नहीं कर रहे हैं।
  • मैं आपको सलाह दूंगा कि आप अपने लोडर के भीतर सीधे कोई भी DB कॉल न करें, बल्कि एक ऐसा एब्सट्रैक्शन बनाएं जो उन्हें कॉल करे।
  • जब पर्यावरण चर सेट करने की बात आती है तो क्लाउडफ्लेयर चुनौतीपूर्ण होता है। उन्हें अनुरोध द्वारा पारित किया जाता है

32. अपने .dev.vars में निम्नलिखित जोड़ें:

ऐप्स/माई-रीमिक्स-क्लाउडफ्लेयर-ऐप/.dev.vars

 DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"

33. रीमिक्स प्रोजेक्ट को क्रियान्वित करें!

पोस्टग्रेज इंस्टैंस लॉन्च करें (यदि तैयार नहीं है)

 docker-compose up -d


परियोजना का शुभारंभ

 pnpm turbo dev 


उन्नत उपयोग मामला - क्लाउडफ्लेयर वर्कर्स में GetLoadContext में CQRS.

अपनी परियोजनाओं में, मैं CQRS पैटर्न , 2 को लागू करने का प्रयास करता हूँ। यह इस ट्यूटोरियल के दायरे से बाहर है।


फिर भी, लोड संदर्भ में, मैं एक मध्यस्थ (और एक कुकी फ्लैश संदेश) को इंजेक्ट करता हूं जो मेरे पूरे रीमिक्स एप्लिकेशन को मेरे व्यावसायिक तर्क से अलग कर देगा।


यह कुछ इस तरह दिखता है:

 export const getLoadContext: GetLoadContext = async ({ context, request }) => { const isEnvEmpty = Object.keys(context.cloudflare.env).length === 0; const env = isEnvEmpty ? process.env : context.cloudflare.env; const sessionFlashSecret = env.SESSION_FLASH_SECRET; const flashStorage = createCookieSessionStorage({ cookie: { name: "__flash", httpOnly: true, maxAge: 60, path: "/", sameSite: "lax", secrets: [sessionFlashSecret], secure: true, }, }); return { ...context, cloudflare: { ...context.cloudflare, env, }, dispatch: (await dispatchWithContext({ env: env as unknown as Record<string, string>, request, })) as Dispatch, flashStorage, }; };

ध्यान दें कि डिस्पैच कोड छोड़ा गया है। आप इसके बारे में मेरे लेख में अधिक जानकारी पा सकते हैं कि अपने TypeScript डेवलपर अनुभव को 10 गुना कैसे बढ़ाया जाए


मैं अपने कोड में बदलाव किए बिना रीमिक्स को हटा सकता हूं या किसी अन्य उपभोक्ता का उपयोग कर सकता हूं।


लेकिन…।


जब आप टर्बोरेपो का उपयोग करके मोनोरेपो संरचना में काम करते हैं तो एक अतिरिक्त चुनौती होती है।


यदि आप लोड-संदर्भ के भीतर किसी पैकेज से टाइपस्क्रिप्ट फ़ाइल आयात करते हैं, मान लीजिए @repo/db Vite एक त्रुटि लौटाएगा कि एक्सटेंशन .ts वाली फ़ाइल अज्ञात है, और यह नहीं जानता कि इसे कैसे संसाधित किया जाए।


ऐसा इसलिए होता है क्योंकि लोड-संदर्भ + वर्कस्पेस साइट के मुख्य आयात ग्राफ के बाहर होते हैं, जिससे टाइपस्क्रिप्ट फ़ाइलें प्ले के बाहर रह जाती हैं।


तरकीब यह है कि tsx उपयोग करें और Vite को कॉल करने से पहले इसे लोड करें, जो काम करेगा। यह महत्वपूर्ण है क्योंकि यह निम्नलिखित सीमाओं को पार करता है:


क्लाउडफ्लेयर पैकेज निर्भरताएँ.


क्लाउडफ्लेयर पैकेज निर्भरताएँ और प्री-बिल्डिंग

सबसे पहले, यह वह चरण था जिसे मैं टालने की कोशिश कर रहा था, क्योंकि इसका मतलब था कि मुझे प्रत्येक पैकेज के लिए एक निर्माण चरण शुरू करना होगा, जिसका मतलब था अधिक कॉन्फ़िगरेशन।


सौभाग्य से, यह क्लाउडफ्लेयर पेज के लिए काम नहीं करता है। Postgres जैसी विशिष्ट लाइब्रेरी रनटाइम का पता लगाएगी और आवश्यक पैकेज खींचेगी।


इसका एक समाधान है: हम सभी टाइपस्क्रिप्ट फ़ाइलों को लोड करने के लिए tsx का उपयोग कर सकते हैं और निष्पादन से पहले उन्हें ट्रांसपाइल कर सकते हैं।


आप यह तर्क दे सकते हैं कि यह एक पूर्व-निर्माण चरण है, लेकिन चूंकि यह अभी भी रीमिक्स के रिपोजिटरी स्तर पर है, इसलिए मुझे इस दृष्टिकोण में कोई महत्वपूर्ण समस्या नहीं दिखती।


इसे हल करने के लिए, हम tsx को निर्भरता के रूप में जोड़ते हैं:

 pnpm add tsx -D --filter=@repo/my-remix-cloudflare-app


और फिर, हमें अपने package.json को संशोधित करने और हमारी प्रत्येक रीमिक्स स्क्रिप्ट में tsx प्रक्रिया को जोड़ने की आवश्यकता है:

 { "name": "@repo/my-remix-cloudflare-app", "version": "1.0.0", "scripts": { // Other scripts omitted "build": "NODE_OPTIONS=\"--import tsx/esm\" remix vite:build", "dev": "NODE_OPTIONS=\"--import tsx/esm\" remix vite:dev", "start": "NODE_OPTIONS=\"--import tsx/esm\" wrangler pages dev ./build/client" } }

अतिरिक्त

.npmrc फ़ाइल बनाना

यदि आपको कमांड लाइन के साथ अपने स्थानीय पैकेज जोड़ते समय समस्या आ रही है, तो आप प्रोजेक्ट के रूट में .npmrc फ़ाइल बना सकते हैं।

.npmrc

 link-workspace-packages= true prefer-workspace-packages=true

यह pnpm को पहले वर्कस्पेस पैकेजों का उपयोग करने के लिए कहेगा।


Reddit के ZoWnx को धन्यवाद जिन्होंने मुझे .nprmc फ़ाइल बनाने में मदद की

नुकसान -

  1. अपनी फ़ाइलों में .client और .server नाम देते समय सावधान रहें। भले ही यह किसी अलग लाइब्रेरी में हो। रीमिक्स इनका उपयोग यह निर्धारित करने के लिए करता है कि यह क्लाइंट या सर्वर फ़ाइल है। प्रोजेक्ट को रिपॉजिटरी के अनुसार संकलित नहीं किया गया है, इसलिए यह एक आयात त्रुटि फेंक देगा!


  2. यदि आपको Postgres जैसे मल्टी-प्लेटफ़ॉर्म पैकेज के साथ समस्या हो रही है, तो इसे वर्कस्पेस स्तर पर इंस्टॉल करना बेहतर है। यह उचित आयात का पता लगाएगा। इसे सीधे @repo/db रिपॉजिटरी में इंस्टॉल करने से इसे रीमिक्स में आयात करते समय टूट जाएगा।


बस इतना ही, मित्रों!!!

GitHub रिपॉजिटरी

आप यहां पूर्ण कार्यान्वयन देख सकते हैं।

सोशल मीडिया पर मुझे फॉलो करें!

मैं उत्पादन में उन 1% त्रुटियों को पकड़ने के लिए सार्वजनिक रूप से एक स्वचालित परीक्षण इंजीनियर का निर्माण कर रहा हूं।


मैं अपनी प्रगति साझा करता हूँ:


X/ट्विटर @javiasilis

लिंक्डइन @javiasilis