paint-brush
Vite, Cloudflare, Remix, PNPM ve Turborepo ile Monorepo Nasıl Oluşturulur (Derleme Adımı Yok)ile@josejaviasilis
Yeni tarih

Vite, Cloudflare, Remix, PNPM ve Turborepo ile Monorepo Nasıl Oluşturulur (Derleme Adımı Yok)

ile Jose Javi Asilis19m2024/08/28
Read on Terminal Reader

Çok uzun; Okumak

Bu, Remix'in Vite Cloduflare Dağıtımları için bir derleme adımı olmadan bir monorepo oluşturur. Bu, bunu birden fazla hedefe genişletmenize olanak tanır
featured image - Vite, Cloudflare, Remix, PNPM ve Turborepo ile Monorepo Nasıl Oluşturulur (Derleme Adımı Yok)
Jose Javi Asilis HackerNoon profile picture
0-item




giriiş

Remix'i Vite ve Cloudflare Workers-Pages ile minimum yapılandırmayla kullanmanın bir yoluna ihtiyacım vardı.


Diğer depoları da gördüm, örneğin:


Ancak bazı sınırlamaları vardı:

  1. Önceden derlemek istemedim, çünkü daha fazla yapılandırma dosyasıyla depoları zehirlemek istemedim.


  2. Cloudflare Workers/Pages'ın farklı bir hedefi var. Postgres gibi paketler Remix'e aktarıldığında düğüm bağımlılıklarını bozarak çekeceğinden, tsup ile hedeflemek zorlaştı.


  3. Ayrıca farklı hedefleri (Remix-Cloudflare, Node/Bun) tüketmenin bir yoluna ihtiyacım vardı


Yine de onlara teşekkür ediyorum, çünkü bu başarının önünü açtılar!


Alt taraftaki tuzaklar bölümünü mutlaka okuyun!

Beni Sosyal Medyada Takip Edin!

Üretimdeki %1'lik hataları yakalamak için kamuya açık bir otomatik test platformu kuruyorum.


İlerlememi şu şekilde paylaşıyorum:


X/Twitter @javiasilis

LinkedIn @javiasilis

GitHub Deposu

Uygulamanın tamamına buradan ulaşabilirsiniz.

Adım adım

Gereksinimler

  1. DüğümJS
  2. PNPM
  3. Docker (İsteğe bağlı - Yerel veritabanı örneği için)


Bu sizi yeni bir mono-depoda gezdirse de, var olan bir mono-depoyu tek bir mono-depoya dönüştürmek de tamamen geçerlidir.


Bu aynı zamanda mono repo konusunda da bilgi sahibi olduğunuzu varsayar.


Not:

  • “at root” monorepository’nizin başlangıç yolunu ifade eder. Bu proje için, libs ve packages dizinlerinin dışında olacaktır.

Turborepo'yu yükleyin

Turborepo, projenizin betiklerini ve çıktılarını yönetmek için paket yöneticinizin çalışma alanlarının üstünde çalışır (hatta çıktınızı önbelleğe alabilir). Şimdiye kadar, Rush'ın (denemediğim ve sevmediğim) dışında çalışabilen tek mono-repo aracıdır.


NX'te Remix'in Vite desteği yok (bu yazının yazıldığı tarih itibarıyla - 28 Ağustos 2024).


https://turbo.build/

 pnpm dlx create-turbo@latest

1. PNPM Çalışma Alanlarını Yapılandırın

Bağımlılıkları yönetmek için PNPM'nin çalışma alanı yeteneklerini kullanacağız.


Monorepo dizininizde pnpm-workspace.yaml oluşturun.


İçine şunu ekleyin:

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


Bu pnpm'e tüm depoların apps ve libs içinde yer alacağını söyleyecektir. libs veya packages kullanmanın (başka bir yerde görmüş olabileceğiniz gibi) bir önemi olmadığını unutmayın.

2. Projenin Kök Dizininde Boş Bir package.json Oluşturun:

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


name:@repo/main Bu bize bunun uygulamanın ana girişi olduğunu söyler. Belirli bir kuralı takip etmeniz veya @ önekini kullanmanız gerekmez. İnsanlar bunu yerel/uzak paketlerden ayırt etmek veya bir organizasyonda gruplandırmayı kolaylaştırmak için kullanırlar.

3. Projenin Kök Dizininde turbo.json Dosyasını Oluşturun:

 { "$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": {} } }


turbo.json dosyası turbo deposuna komutlarımızı nasıl yorumlayacağını söyler. tasks anahtarının içinde bulunan her şey all package.json'da bulunanlarla eşleşecektir.


Dört komut tanımladığımızı unutmayın. Bunlar her deponun package.json dosyasının script bölümündekilerle eşleşir. Ancak, tüm package.json dosyaları bu komutları uygulamak zorunda değildir.


Örn: dev komutu turbo dev tarafından tetiklenecek ve package.json içinde dev bulunan tüm paketleri çalıştıracaktır. Eğer bunu turbo'ya dahil etmezseniz, çalıştırılmayacaktır.

4. Projenin Kökünde bir apps klasörü oluşturun

 mkdir apps

5. apps klasöründe bir Remix Uygulaması oluşturun (veya mevcut olanı taşıyın)

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


Install any dependencies with npm istediğinde hayır deyin.


  • Böyle görünmesi lazım

6. package.json dosyasının name @repo/my-remix-cloudflare-app (veya kendi adınız) olarak değiştirin.

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

7. Bağımlılıkları ve devDependencies'i apps/<app>/package.json Root'un package.json kopyalayın

Örn:

<kök>/paket.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. Turbo'yu kök seviyesine devDependency olarak ekleyin (Bu, Remix'in tüm paketlerini yükleyecektir).

Turbo'nun package.json'ın devDependencies'inde olduğunu doğrulayın. Listelenmemişse, aşağıdaki komutu çalıştırın:

 pnpm add turbo -D -w


-w bayrağı pnpm'e bunu çalışma alanı köküne kurmasını söyler.

9. Root package.json'a aşağıdaki girdileri ekleyin

  • dev komutunu scripts ekleyin

  • packageManager seçeneğe ekleyin


 { "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 komutunu çalıştırarak her şeyin çalıştığını doğrulayın

 pnpm dev

11. Projenin Kökünde bir Libs Klasörü Oluşturun. config, db ve utils ekleyin:

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

12. Paketlerin her biri için src/index.ts ekleyin.

 touch libs/config/src/index.ts libs/db/src/index.ts libs/utils/src/index.ts
  • Tüm paketleri dışarı aktarmak için index.ts dosyası kullanılacaktır.
  • Her şeyi kompakt hale getirmek için klasörü giriş noktamız olarak kullanacağız.
  • Bu bir kuraldır ve buna uymamayı seçebilirsiniz.

13. Boş bir package.json dosyası oluşturun ve libs/config/package.json dosyasına aşağıdakileri ekleyin:

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

14. Aynısını libs/db/package.json için de yapın:

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

15. Ve libs/utils/package.json :

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


  • "Exports" alanını belirtiyoruz. Bu, diğer depolara paketi nereden içe aktaracaklarını söyler.
  • "Ad" alanını belirtiyoruz. Bu, paketi yüklemek ve diğer depolara yönlendirmek için kullanılır.

16. (DB) - Drizzle ve Postgres'i ekleyin

Notlar:

  • ORM'lerden nefret etmeye başlıyorum. 6 farklı ORM öğrenmek için 10 yıldan fazla zaman harcadım ve bunlar aktarılamayan bilgiler.

  • Yeni teknolojiler çıktığında sorunlar yaşıyorsunuz. Prisma, Cloudflare çalışanlarını anında desteklemiyor.

  • LLM sayesinde karmaşık SQL sorguları yazmak her zamankinden daha kolay.

  • SQL öğrenmek evrensel bir dildir ve büyük olasılıkla değişmeyecektir.


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


Postgres'i çalışma alanı düzeyinde yükleyin. Pitfall bölümüne bakın .

 pnma add postgres -w


Notlar:

  • --filter=@repo/db bayrağı pnpm'e paketi db deposuna eklemesini söyler.

17. Dotenv'i Workspace Deposuna ekleyin

 pnpm add dotenv -w

Notlar

  • -w bayrağı pnpm'e bunu root'un package.json dosyasına kurmasını söyler

18. Yapılandırma Projesini Tüm Projelere Ekleyin.

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

Notlar :

  • -r bayrağı pnpm'e paketi tüm depolarına eklemesini söyler.
  • --filter=! bayrağı pnpm'e yapılandırma deposunu hariç tutmasını söyler.
  • Paket adından önceki ! işaretine dikkat edin

19. (İsteğe bağlı) Yukarıdaki Komutlar Çalışmıyor mu? .npmrc kullanın

Eğer pnpm paketleri depodan çekiyorsa, projenin kökünde bir .npmrc dosyası oluşturabiliriz.


.npmrc

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


  • Bu, pnpm'e öncelikle çalışma alanı paketlerini kullanmasını söyleyecektir.
  • .nprmc dosyasını oluşturmama yardımcı olan Reddit'ten ZoWnx'e teşekkürler

20. Libs/Config İçinde Paylaşılan tsconfig.json Yapılandırın

Pnpm çalışma alanlarının gücünü kullanarak, projeler arasında paylaşılabilen yapılandırma dosyaları oluşturabilirsiniz.


Kütüphanelerimiz için kullanacağımız temel tsconfig.lib.json'ı oluşturacağız.


libs/config içerisinde tsconfig.lib.json dosyasını oluşturun:

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


Daha sonra şunu ekleyin:

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 Bağlantısını db Deposuna ekleyin.

 // 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, });


Şema dosyası:

 // 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(), });


Müşteri dosyası:

 // 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!; } }


Göç dosyası:

 // 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();

Bu, göçlerden sonra yürütülmelidir


Ve istemciyi ve şemayı src/index.ts dosyasına aktarın. Diğerleri belirli zamanlarda çalıştırılır.

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


package.json dosyanıza drizzle-kit generate komutunu ve geçiş komutunu çalıştıracak kodu ekleyin:

 { "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 ve libs/utils için Paylaşılan tsconfig.json kullanın

libs/db ve libs/utils için bir tsconfig.json oluşturun

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


Sonra her birine şunu ekleyin:

 { "extends": "@repo/configs/tsconfig.base.lib.json", "include": ["./src"], }
  • @repo/configs tsconfig.base.lib.json dosyamıza referans vermek için kullanılan yol olduğunu görün.
  • Yolumuzu temizler.

23. TSX'i yükleyin

TypeScript Execute (TSX), ts-node'a bir kütüphane alternatifidir. Bunu, drizzle'ın geçişlerini yürütmek için kullanacağız.

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

24. libs/db dizinine boş bir .env ekleyin

 touch "libs/db/.env"


Aşağıdaki içerikleri ekleyin:

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


Şuna benzer bir şey olmalı


25. libs/db Deposunu Remix Projemize Ekleyin

Projenin kökünden şunu çalıştırın:

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


Eğer bu işe yaramazsa, apps/my-remix-cloudflare-app dosyasının package.json dosyasına gidin ve bağımlılığı manuel olarak ekleyin.

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

Sürüm alanında workspace:* i not edin. Bu, pnpm'e çalışma alanındaki paketin herhangi bir sürümünü kullanmasını söyler.


Eğer pnpm add, muhtemelen workspace:^ gibi bir şey göreceksiniz. Yerel paket sürümlerini artırmadığınız sürece sorun olmamalı.


Eğer bunu manuel olarak eklediyseniz, projenin kökünden pnpm install çalıştırın.


@repo/db'yi projemizde tüketebilmeliyiz.

26. Yardımcı Programlarımıza Bazı Paylaşımlı Kodlar Ekleyin:

Bu kodu libs/utils/src/index.ts dosyasına ekleyin:

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


27. Libs/Utils'ı Remix Uygulamamıza yükleyin:

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

28. (İsteğe bağlı) Bir Docker Konteynerinden Postgres Başlatma

Çalışan bir Postgres örneğiniz yoksa, docker-compose kullanarak bir tane başlatabiliriz. Docker'ı bildiğinizi varsayıyorum.


Projenin kökünde docker-compose.yml dosyasını oluşturun.

 # 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


Daha sonra şunu çalıştırabilirsiniz:

 docker-compose up -d

-d bayrağı docker-compose'a bağımsız çalışmasını söyler, böylece terminalinize tekrar erişebilirsiniz.

29. DB Şemasını Oluşturun

Şimdi libs/db deposuna gidin ve db:generate çalıştırın.

 cd `./libs/db` && pnpm db:generate
  • db:generate drizzle-kit generate için bir takma ad olduğunu unutmayın
  • Uygun .env'ye sahip olduğunuzu doğrulayın.
  • Ayrıca, bu, bir Postgres örneğinizin çalıştığını varsayar.

30. Göçleri çalıştırın.

Veritabanımızdaki tüm tabloları desteklemek için göçleri çalıştırmamız gerekiyor.


libs/db deposuna gidin (orada değilseniz) ve db:generate çalıştırın.

 cd `./libs/db` && pnpm db:migrate
  • db:migrate dotenv tsx ./drizzle/migrate için bir takma ad olduğunu unutmayın
  • Uygun .env'ye sahip olduğunuzu doğrulayın.
  • Ayrıca, bu, bir Postgres örneğinizin çalıştığını varsayar.

31. Remix Uygulamanıza Bir DB Çağrısı Ekleyin.

 // 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} />; }


  • Burada en iyi uygulamaları takip etmediğimizi unutmayın.
  • Yükleyiciniz içerisinde doğrudan herhangi bir DB çağrısı yapmamanızı, bunun yerine onları çağıran bir soyutlama oluşturmanızı öneririm.
  • Cloudflare, ortam değişkenlerini ayarlama konusunda zorludur. Bunlar istekle iletilir

32. .dev.vars dosyanıza aşağıdakileri ekleyin:

uygulamalar/benim-remix-cloudflare-uygulamam/.dev.vars

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

33. Remix Projesini Yürütün!

Postgres örneğini başlatın (hazır değilse)

 docker-compose up -d


Projeyi başlatın

 pnpm turbo dev 


Gelişmiş Kullanım Örneği - Cloudflare Workers'daki GetLoadContext'te CQRS.

Projelerimde CQRS desenini uygulamaya çalışıyorum, 2. Bu, bu eğitimin kapsamı dışındadır.


Bununla birlikte, yükleme bağlamı içerisinde, tüm Remix Uygulamamı iş mantığımdan ayıracak bir aracı (ve bir çerez flaş mesajı) enjekte etme eğilimindeyim.


Bu şuna benzer bir şey:

 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, }; };

Dağıtım kodunun atlandığını unutmayın. TypeScript geliştirme deneyiminizi 10 katına çıkarma hakkında daha fazla bilgiyi buradaki makalemde bulabilirsiniz.


Kodumu değiştirmeden Remix'i kaldırabilir veya başka bir tüketici kullanabilirim.


Ancak….


Turborepo kullanarak monorepo yapısında çalıştığınızda ek bir zorluk daha ortaya çıkar.


Örneğin, load-context içindeki bir paketten bir TypeScript dosyası içe aktarırsanız, @repo/db Vite'ın .ts uzantılı dosyanın bilinmediğine dair bir hata döndüreceğini ve onu nasıl işleyeceğini bilemeyeceğini varsayalım.


Bunun nedeni, yükleme bağlamı + çalışma alanlarının sitenin ana içe aktarma grafiğinin dışında olması ve TypeScript dosyalarının oyunun dışında kalmasıdır.


İşin püf noktası tsx kullanmak ve Vite'ı çağırmadan önce yüklemektir, bu işe yarayacaktır. Bu önemlidir çünkü aşağıdaki sınırlamaları aşar:


Cloudflare Paket Bağımlılıkları.


Cloudflare Paket Bağımlılıkları ve Ön Yapı

Öncelikle kaçınmaya çalıştığım adım buydu, çünkü bu, paketlerin her biri için bir derleme adımı eklemem gerektiği anlamına geliyordu ve bu da daha fazla yapılandırma anlamına geliyordu.


Neyse ki bu Cloudflare Pages için işe yaramadı. Postgres gibi belirli kütüphaneler çalışma zamanını algılayacak ve gerekli paketi çekecektir.


Bir çözüm yolu var: tsx'i kullanarak tüm TypeScript dosyalarını yükleyebilir ve çalıştırmadan önce derleyebiliriz.


Bunun önceden oluşturulmuş bir adım olduğunu iddia edebilirsiniz, ancak hala remiksin depo düzeyinde olduğu için bu yaklaşımda önemli bir sorun görmüyorum.


Bunu çözmek için tsx'i bağımlılık olarak ekliyoruz:

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


Daha sonra package.json dosyamızı düzenleyip, remix scriptlerimizin her birine tsx sürecini eklememiz gerekiyor:

 { "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" } }

Ekstralar

.npmrc Dosyası Oluşturma

Yerel paketlerinizi komut satırıyla eklerken sorun yaşıyorsanız, projenin kök dizininde .npmrc dosyası oluşturabilirsiniz.

.npmrc

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

Bu, pnpm'e öncelikle çalışma alanı paketlerini kullanmasını söyleyecektir.


.nprmc dosyasını oluşturmama yardımcı olan Reddit'ten ZoWnx'e teşekkürler

Tuzaklar -

  1. Dosyalarınızda .client ve .server isimlendirmesine dikkat edin. Ayrı bir kütüphanede olsa bile. Remix, bir istemci veya sunucu dosyası olup olmadığını belirlemek için bunları kullanır. Proje depo başına derlenmediğinden içe aktarma hatası verecektir!


  2. Postgres gibi çoklu platform paketleriyle ilgili sorunlar yaşıyorsanız, bunu çalışma alanı düzeyinde yüklemek daha iyidir. Uygun içe aktarımı algılayacaktır. @repo/db deposuna doğrudan yüklemek, Remix'e içe aktarırken bozulacaktır.


İşte bu kadar arkadaşlar!!!

GitHub Deposu

Uygulamanın tamamına buradan ulaşabilirsiniz.

Beni Sosyal Medyada Takip Edin!

Üretimdeki %1'lik hataları yakalamak için kamuya açık bir otomatik test mühendisi kuruyorum.


İlerlememi şu şekilde paylaşıyorum:


X/Twitter @javiasilis

LinkedIn @javiasilis