परिचय मुझे न्यूनतम कॉन्फ़िगरेशन के साथ Vite और Cloudflare Workers-Pages के साथ Remix का उपयोग करने का एक तरीका चाहिए था। मैंने अन्य रिपॉजिटरी भी देखीं, जैसे: , सुसमाचार का ढेर , गिरीश21 . हिमोरीशिगे लेकिन उनकी कुछ सीमाएँ थीं: मैं इसे पहले से बनाना नहीं चाहता था, क्योंकि मैं रिपॉजिटरीज में और अधिक कॉन्फ़िगरेशन फ़ाइलें नहीं डालना चाहता था। क्लाउडफ्लेयर वर्कर्स/पेजेस का लक्ष्य अलग है। इसे tsup के साथ लक्षित करना मुश्किल हो गया, क्योंकि पोस्टग्रेस जैसे पैकेज रीमिक्स में आयात किए जाने पर नोड निर्भरता को तोड़ देंगे। मुझे विभिन्न लक्ष्यों (रीमिक्स-क्लाउडफ्लेयर, नोड/बुन) का उपभोग करने का एक तरीका भी चाहिए था फिर भी, मैं उनका धन्यवाद करता हूं, क्योंकि उन्होंने इसे संभव बनाने का मार्ग प्रशस्त किया! नीचे दिए गए नुकसान वाले अनुभाग को अवश्य पढ़ें! सोशल मीडिया पर मुझे फॉलो करें! मैं उत्पादन में उन 1% त्रुटियों को पकड़ने के लिए सार्वजनिक रूप से एक स्वचालित परीक्षण मंच का निर्माण कर रहा हूं। मैं अपनी प्रगति साझा करता हूँ: X/ट्विटर @javiasilis लिंक्डइन @javiasilis GitHub रिपॉजिटरी आप देख सकते हैं। यहां पूर्ण कार्यान्वयन क्रमशः आवश्यकताएं नोडजेएस पीएनपीएम 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 फ़ाइल टर्बो रेपो को बताती है कि हमारे आदेशों की व्याख्या कैसे की जाए। कुंजी के अंदर जो कुछ भी है वह सभी package.json में पाए जाने वाले से मेल खाएगा। tasks ध्यान दें कि हमने चार कमांड परिभाषित किए हैं। ये प्रत्येक रिपॉजिटरी के package.json के स्क्रिप्ट सेक्शन में मौजूद कमांड से मेल खाते हैं। हालाँकि, सभी package.json को इन कमांड को लागू करना ज़रूरी नहीं है। उदाहरण: कमांड को द्वारा ट्रिगर किया जाएगा, और यह उन सभी पैकेजों को निष्पादित करेगा जो package.json में पाए जाते हैं। यदि आप इसे turbo में शामिल नहीं करते हैं, तो यह निष्पादित नहीं होगा। dev turbo dev dev 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. से Dependencies और devDependencies को रूट के में कॉपी करें apps/<app>/package.json 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 ध्वज pnpm को इसे कार्यक्षेत्र रूट पर स्थापित करने के लिए कहता है। -w 9. रूट package.json में निम्नलिखित प्रविष्टियाँ जोड़ें में कमांड जोड़ें scripts dev को विकल्प में जोड़ें packageManager { "name": "@repo/main", "version": "1.0.0", "scripts": { "dev": "turbo dev" }, "keywords": [], "author": "", "license": "ISC", "packageManager": "pnpm@9.1.0", "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 टिप्पणियाँ: फ्लैग pnpm को पैकेज को db रिपोजिटरी में जोड़ने के लिए कहता है। --filter=@repo/db 17. dotenv को वर्कस्पेस रिपॉजिटरी में जोड़ें pnpm add dotenv -w नोट्स फ्लैग pnpm को रूट के package.json पर इसे स्थापित करने के लिए कहता है -w 18. कॉन्फ़िगरेशन प्रोजेक्ट को सभी प्रोजेक्ट्स में जोड़ें। pnpm add @repo/config -r --filter=!@repo/config : टिप्पणियाँ फ्लैग pnpm को पैकेज को सभी रिपॉजिटरी में जोड़ने के लिए कहता है। -r ध्वज pnpm को कॉन्फ़िगरेशन रिपोजिटरी को बाहर करने के लिए कहता है। --filter=! पैकेज नाम से पहले पर ध्यान दें ! 19. (वैकल्पिक) क्या ऊपर दिए गए कमांड काम नहीं करते? .npmrc का उपयोग करें यदि pnpm रिपोजिटरी से पैकेज खींच रहा है, तो हम प्रोजेक्ट के रूट पर एक फ़ाइल बना सकते हैं। .npmrc .npmrc link-workspace-packages= true prefer-workspace-packages=true यह pnpm को पहले वर्कस्पेस पैकेजों का उपयोग करने के लिए कहेगा। Reddit के को धन्यवाद, जिन्होंने मुझे .nprmc फ़ाइल बनाने में मदद की ZoWnx 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 और के लिए tsconfig.json बनाएँ libs/db libs/utils touch "libs/db/tsconfig.json" "libs/utils/tsconfig.json" फिर प्रत्येक में जोड़ें: { "extends": "@repo/configs/tsconfig.base.lib.json", "include": ["./src"], } देखें कि उपयोग हमारे tsconfig.base.lib.json को संदर्भित करने के लिए पथ के रूप में किया जाता है। @repo/configs यह हमारा मार्ग स्वच्छ बनाता है। 23. टीएसएक्स स्थापित करें टाइपस्क्रिप्ट एक्ज़ीक्यूट (TSX) ts-node का एक लाइब्रेरी विकल्प है। हम इसका उपयोग ड्रिज़ल के माइग्रेशन को निष्पादित करने के लिए करेंगे। pnpm add tsx -D --filter=@repo/db 24. डायरेक्टरी में एक खाली .env जोड़ें libs/db 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 यदि यह काम नहीं करता है, तो के package.json पर जाएं, और निर्भरता को मैन्युअल रूप से जोड़ें। apps/my-remix-cloudflare-app { "name": "@repo/my-remix-cloudflare-app", "version": "1.0.0", "dependencies": { "@repo/db": "workspace:*" } } वर्शन फ़ील्ड में पर ध्यान दें। यह pnpm को वर्कस्पेस में पैकेज के किसी भी वर्शन का उपयोग करने के लिए कहता है। workspace:* यदि आपने इसे आपको संभवतः जैसा कुछ दिखाई देगा। जब तक आप स्थानीय पैकेज संस्करणों को नहीं बढ़ाते हैं, तब तक इससे कोई फर्क नहीं पड़ता है। 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: admin@a.com PGADMIN_DEFAULT_PASSWORD: admin फिर आप चला सकते हैं: docker-compose up -d फ्लैग docker-compose को अलग से चलने के लिए कहता है ताकि आप फिर से अपने टर्मिनल तक पहुंच सकें। -d 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 गुना कैसे बढ़ाया । जाए मैं अपने कोड में बदलाव किए बिना रीमिक्स को हटा सकता हूं या किसी अन्य उपभोक्ता का उपयोग कर सकता हूं। लेकिन…। जब आप टर्बोरेपो का उपयोग करके मोनोरेपो संरचना में काम करते हैं तो एक अतिरिक्त चुनौती होती है। यदि आप लोड-संदर्भ के भीतर किसी पैकेज से टाइपस्क्रिप्ट फ़ाइल आयात करते हैं, मान लीजिए Vite एक त्रुटि लौटाएगा कि एक्सटेंशन वाली फ़ाइल अज्ञात है, और यह नहीं जानता कि इसे कैसे संसाधित किया जाए। @repo/db .ts ऐसा इसलिए होता है क्योंकि लोड-संदर्भ + वर्कस्पेस साइट के मुख्य आयात ग्राफ के बाहर होते हैं, जिससे टाइपस्क्रिप्ट फ़ाइलें प्ले के बाहर रह जाती हैं। तरकीब यह है कि उपयोग करें और Vite को कॉल करने इसे लोड करें, जो काम करेगा। यह महत्वपूर्ण है क्योंकि यह निम्नलिखित सीमाओं को पार करता है: tsx से पहले क्लाउडफ्लेयर पैकेज निर्भरताएँ. क्लाउडफ्लेयर पैकेज निर्भरताएँ और प्री-बिल्डिंग सबसे पहले, यह वह चरण था जिसे मैं टालने की कोशिश कर रहा था, क्योंकि इसका मतलब था कि मुझे प्रत्येक पैकेज के लिए एक निर्माण चरण शुरू करना होगा, जिसका मतलब था अधिक कॉन्फ़िगरेशन। सौभाग्य से, यह क्लाउडफ्लेयर पेज के लिए काम नहीं करता है। Postgres जैसी विशिष्ट लाइब्रेरी रनटाइम का पता लगाएगी और आवश्यक पैकेज खींचेगी। इसका एक समाधान है: हम सभी टाइपस्क्रिप्ट फ़ाइलों को लोड करने के लिए tsx का उपयोग कर सकते हैं और निष्पादन से पहले उन्हें ट्रांसपाइल कर सकते हैं। आप यह तर्क दे सकते हैं कि यह एक पूर्व-निर्माण चरण है, लेकिन चूंकि यह अभी भी रीमिक्स के रिपोजिटरी स्तर पर है, इसलिए मुझे इस दृष्टिकोण में कोई महत्वपूर्ण समस्या नहीं दिखती। इसे हल करने के लिए, हम tsx को निर्भरता के रूप में जोड़ते हैं: pnpm add tsx -D --filter=@repo/my-remix-cloudflare-app और फिर, हमें अपने को संशोधित करने और हमारी प्रत्येक रीमिक्स स्क्रिप्ट में tsx प्रक्रिया को जोड़ने की आवश्यकता है: package.json { "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 के को धन्यवाद जिन्होंने मुझे .nprmc फ़ाइल बनाने में मदद की ZoWnx नुकसान - अपनी फ़ाइलों में और नाम देते समय सावधान रहें। भले ही यह किसी अलग लाइब्रेरी में हो। रीमिक्स इनका उपयोग यह निर्धारित करने के लिए करता है कि यह क्लाइंट या सर्वर फ़ाइल है। प्रोजेक्ट को रिपॉजिटरी के अनुसार संकलित नहीं किया गया है, इसलिए यह एक आयात त्रुटि फेंक देगा! .client .server यदि आपको Postgres जैसे मल्टी-प्लेटफ़ॉर्म पैकेज के साथ समस्या हो रही है, तो इसे वर्कस्पेस स्तर पर इंस्टॉल करना बेहतर है। यह उचित आयात का पता लगाएगा। इसे सीधे @repo/db रिपॉजिटरी में इंस्टॉल करने से इसे रीमिक्स में आयात करते समय टूट जाएगा। बस इतना ही, मित्रों!!! GitHub रिपॉजिटरी आप देख सकते हैं। यहां पूर्ण कार्यान्वयन सोशल मीडिया पर मुझे फॉलो करें! मैं उत्पादन में उन 1% त्रुटियों को पकड़ने के लिए सार्वजनिक रूप से एक स्वचालित परीक्षण इंजीनियर का निर्माण कर रहा हूं। मैं अपनी प्रगति साझा करता हूँ: X/ट्विटर @javiasilis लिंक्डइन @javiasilis