Dari Next.js untuk React Edge dengan Cloudflare Workers: A Story of Liberation

Susan Sarandon
Lepaskan: 2024-11-20 14:26:17
asal
840 orang telah melayarinya

Indeks Pantas

  • Jerami Terakhir
  • Alternatif dengan Cloudflare ?
  • React Edge: Rangka Kerja React Lahir daripada Kesakitan Setiap Pembangun (atau Hampir)
    • Keajaiban RPC Ditaip
    • Kuasa penggunaanFetch: Di Mana Keajaiban Berlaku
  • Beyond useFetch: The Complete Arsenal
    • RPC: Seni Komunikasi Pelanggan-Pelayan
    • Sistem i18n yang Masuk akal
    • Pengesahan JWT Yang "Hanya Berfungsi"
    • Kedai Kongsi
    • Penghalaan Elegan
    • Cache Teragih dengan Cache Tepi
  • Pautan: Komponen Yang Berfikir Ke Hadapan
  • app.useContext: The Portal to the Edge
  • app.useUrlState: Keadaan Disegerakkan dengan URL
  • app.useStorageState: Keadaan Berterusan
  • app.useDebounce: Kawalan Frekuensi
  • app.useDistinct: Keadaan Tanpa Pendua
  • The React Edge CLI: Kuasa di Hujung Jari Anda
  • Kesimpulan

Jerami Terakhir

Semuanya bermula dengan invois Vercel. Tidak, sebenarnya, ia bermula lebih awal—dengan kekecewaan kecil bertimbun. Keperluan membayar untuk ciri asas seperti perlindungan DDoS, log yang lebih terperinci, atau juga tembok api yang baik, membina baris gilir, dll. Perasaan terperangkap dalam kunci masuk vendor yang semakin mahal.

"Dan yang paling teruk: pengepala SEO berharga kami hanya berhenti memaparkan pada pelayan dalam aplikasi menggunakan penghala halaman. Sakit kepala yang benar untuk mana-mana pembangun! ?"

Tetapi apa yang benar-benar membuatkan saya memikirkan semula segala-galanya ialah arah yang dituju Next.js. Pengenalan penggunaan klien, gunakan pelayan—arahan yang, secara teori, harus memudahkan pembangunan tetapi, dalam amalan, menambah satu lagi lapisan kerumitan untuk diurus. Ia seperti kembali ke zaman PHP, menandai fail dengan arahan untuk menentukan di mana ia harus dijalankan.

Dan ia tidak berhenti di situ. Penghala Apl—idea yang menarik tetapi dilaksanakan dengan cara yang mencipta rangka kerja yang hampir sepenuhnya baharu dalam Next.js. Tiba-tiba, terdapat dua cara yang sama sekali berbeza untuk melakukan perkara yang sama—'lama' dan 'baharu'—dengan gelagat yang berbeza secara halus dan perangkap tersembunyi.

Alternatif dengan Cloudflare ?

Ketika itulah saya tersentuh: mengapa tidak memanfaatkan infrastruktur Cloudflare yang luar biasa dengan Pekerja yang berjalan di tepi, R2 untuk penyimpanan, KV untuk data yang diedarkan... Bersama-sama dengan, sudah tentu, perlindungan DDoS yang menakjubkan, CDN global, firewall , peraturan halaman dan penghalaan, dan segala-galanya yang Cloudflare tawarkan.

Dan bahagian yang terbaik: model penetapan harga yang adil di mana anda membayar untuk apa yang anda gunakan, tanpa kejutan.

Beginilah cara React Edge dilahirkan. Rangka kerja yang tidak bertujuan untuk mencipta semula roda sebaliknya memberikan pengalaman pembangunan yang benar-benar mudah dan moden.

React Edge: Rangka Kerja React Lahir daripada Kesakitan Setiap Pembangun (atau Hampir)

Apabila saya mula membangunkan React Edge, saya mempunyai matlamat yang jelas: untuk mencipta rangka kerja yang masuk akal. Tiada lagi bergelut dengan arahan yang mengelirukan, tiada lagi bayaran yang terlalu tinggi untuk ciri asas, dan yang paling penting, tiada lagi berurusan dengan kerumitan buatan yang disebabkan oleh pemisahan pelanggan/pelayan. Saya mahukan kelajuan—rangka kerja yang memberikan prestasi tanpa mengorbankan kesederhanaan. Dengan memanfaatkan pengetahuan saya tentang API React dan pengalaman bertahun-tahun sebagai pembangun JavaScript dan Golang, saya tahu dengan tepat cara mengendalikan strim dan pemultipleksan untuk mengoptimumkan pemaparan dan pengurusan data.

Cloudflare Workers, dengan infrastruktur yang berkuasa dan kehadiran globalnya, menyediakan persekitaran yang sempurna untuk meneroka kemungkinan ini. Saya mahukan sesuatu yang benar-benar hibrid, dan gabungan alatan serta pengalaman ini menghidupkan React Edge: rangka kerja yang menyelesaikan masalah dunia sebenar dengan penyelesaian moden dan cekap.

React Edge memperkenalkan pendekatan revolusioner untuk pembangunan React. Bayangkan menulis kelas pada pelayan dan memanggilnya terus daripada klien, dengan keselamatan jenis penuh dan konfigurasi sifar. Bayangkan sistem caching yang diedarkan yang "hanya berfungsi", membenarkan ketidaksahihan oleh teg atau awalan. Bayangkan berkongsi keadaan dengan lancar dan selamat antara pelayan dan pelanggan. Tambahkan pengesahan yang dipermudahkan, sistem pengantarabangsaan yang cekap, CLI dan banyak lagi.

Komunikasi RPCnya terasa hampir ajaib—anda menulis kaedah dalam kelas dan memanggilnya daripada pelanggan seolah-olah kaedah itu tempatan. Sistem pemultipleksan pintar memastikan bahawa walaupun berbilang komponen membuat panggilan yang sama, hanya satu permintaan dihantar ke pelayan. Caching sementara mengelakkan permintaan berulang yang tidak perlu, dan semuanya berfungsi dengan lancar pada kedua-dua pelayan dan pelanggan.

Salah satu ciri yang paling berkuasa ialah app.useFetch hook, yang menyatukan pengalaman pengambilan data. Pada pelayan, ia pramuat data semasa SSR; pada pelanggan, ia secara automatik menghidrat dengan data tersebut dan menyokong kemas kini atas permintaan. Dengan sokongan untuk tinjauan automatik dan kereaktifan berasaskan pergantungan, mencipta antara muka dinamik tidak pernah semudah ini.

Tetapi bukan itu sahaja. Rangka kerja ini menawarkan sistem penghalaan yang berkuasa (diilhamkan oleh Hono yang hebat), pengurusan aset bersepadu dengan Cloudflare R2, dan cara yang elegan untuk menangani ralat melalui kelas HttpError. Middlewares boleh menghantar data dengan mudah kepada pelanggan melalui kedai kongsi dan semuanya dikaburkan secara automatik untuk keselamatan.

Bahagian yang paling mengagumkan? Hampir semua kod rangka kerja adalah hibrid. Tiada versi "pelanggan" dan versi "pelayan"—kod yang sama berfungsi dalam kedua-dua persekitaran, menyesuaikan secara automatik kepada konteks. Pelanggan hanya menerima apa yang diperlukan, menjadikan berkas terakhir sangat dioptimumkan.

Dan icing pada kek: semua ini berjalan pada infrastruktur tepi Cloudflare Workers, memberikan prestasi luar biasa pada kos yang berpatutan. Tiada invois mengejut, tiada ciri asas yang terkunci di sebalik rancangan perusahaan yang mahal—hanya rangka kerja yang kukuh yang membolehkan anda menumpukan pada perkara yang benar-benar penting: membina aplikasi yang menakjubkan. Selain itu, React Edge memanfaatkan ekosistem Cloudflare, termasuk Baris Gilir, Objek Tahan Lama, Storan KV dan banyak lagi, menyediakan asas yang teguh dan berskala untuk aplikasi anda.

Vite digunakan sebagai asas untuk persekitaran pembangunan, ujian dan proses binaan. Dengan kelajuan yang mengagumkan dan seni bina moden, Vite membolehkan aliran kerja yang tangkas dan cekap. Ia bukan sahaja mempercepatkan pembangunan tetapi juga mengoptimumkan proses binaan, memastikan penyusunan pantas dan tepat. Tidak syak lagi, Vite ialah pilihan yang tepat untuk React Edge.

Memikirkan Semula Pembangunan Reaksi untuk Era Pengkomputeran Edge

Pernahkah anda terfikir bagaimana rasanya membangunkan aplikasi React tanpa perlu risau tentang halangan pelanggan/pelayan? Tanpa menghafal berpuluh-puluh arahan seperti menggunakan klien atau menggunakan pelayan? Lebih baik lagi: bagaimana jika anda boleh memanggil fungsi pelayan seolah-olah ia tempatan, dengan penaipan penuh dan konfigurasi sifar?

Dengan React Edge, anda tidak perlu lagi:

  • Buat laluan API berasingan
  • Urus keadaan pemuatan/ralat secara manual
  • Laksanakan debounce diri anda
  • Bimbang tentang pensirilan/deserialisasi
  • Berurusan dengan CORS
  • Urus menaip antara klien/pelayan
  • Kendalikan peraturan pengesahan secara manual
  • Perjuangan dengan persediaan pengantarabangsaan

Dan bahagian yang terbaik: semua ini berfungsi dengan lancar pada kedua-dua pelayan dan pelanggan tanpa menandai apa-apa sebagai klien guna atau pelayan guna. Rangka kerja secara automatik mengetahui perkara yang perlu dilakukan berdasarkan konteks. Bolehkah kita menyelam?

Keajaiban RPC Ditaip

Bayangkan boleh melakukan ini:

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Bandingkan ini dengan Next.js/Vercel:

// pages/api/search.ts
export default async handler = (req, res) => {
  // Configure CORS
  // Validate request
  // Handle errors
  // Serialize response
  // ...100 lines later...
}

// app/search/page.tsx
'use client';
import { useEffect, useState } from 'react';

export default const SearchPage = () => {
  const [search, setSearch] = useState('');
  const [filters, setFilters] = useState({});
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let timeout;
    const doSearch = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/search?' + new URLSearchParams({
          q: search,
          ...filters
        }));
        if (!res.ok) throw new Error('Search failed');
        setData(await res.json());
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    timeout = setTimeout(doSearch, 300);
    return () => clearTimeout(timeout);
  }, [search, filters]);

  // ... rest of the component
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kuasa penggunaanFetch: Di Mana Sihir Berlaku

Memikirkan semula Pengambilan Data

Lupakan semua yang anda ketahui tentang pengambilan data dalam React. Cangkuk app.useFetch daripada React Edge memperkenalkan pendekatan yang benar-benar baharu dan berkuasa. Bayangkan cangkuk yang:

  • Pramuat data pada pelayan semasa SSR.
  • Menghidrat data pada pelanggan secara automatik tanpa kelipan.
  • Mengekalkan penaipan penuh antara pelanggan dan pelayan.
  • Menyokong kereaktifan dengan nyahlantun pintar.
  • Memultipleks panggilan yang sama secara automatik.
  • Mendayakan kemas kini program dan tinjauan pendapat.

Jom lihat aksinya:

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Keajaiban Multiplexing

Contoh di atas menyembunyikan ciri berkuasa: pemultipleksan pintar. Apabila anda menggunakan ctx.rpc.batch, React Edge bukan sahaja mengumpulkan panggilan—ia juga menyahduplikasi panggilan yang sama secara automatik:

// pages/api/search.ts
export default async handler = (req, res) => {
  // Configure CORS
  // Validate request
  // Handle errors
  // Serialize response
  // ...100 lines later...
}

// app/search/page.tsx
'use client';
import { useEffect, useState } from 'react';

export default const SearchPage = () => {
  const [search, setSearch] = useState('');
  const [filters, setFilters] = useState({});
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let timeout;
    const doSearch = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/search?' + new URLSearchParams({
          q: search,
          ...filters
        }));
        if (!res.ok) throw new Error('Search failed');
        setData(await res.json());
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    timeout = setTimeout(doSearch, 300);
    return () => clearTimeout(timeout);
  }, [search, filters]);

  // ... rest of the component
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Penghidratan Sempurna SSR

// First, define your API on the server
class PropertiesAPI extends Rpc {
  async searchProperties(filters: PropertyFilters) {
    const results = await this.db.properties.search(filters);
    // Automatic caching for 5 minutes
    return this.createResponse(results, {
      cache: { ttl: 300, tags: ['properties'] }
    });
  }

  async getPropertyDetails(ids: string[]) {
    return Promise.all(
      ids.map(id => this.db.properties.findById(id))
    );
  }
}

// Now, on the client, the magic happens
const PropertySearch = () => {
  const [filters, setFilters] = useState<PropertyFilters>({
    price: { min: 100000, max: 500000 },
    bedrooms: 2
  });

  // Reactive search with intelligent debounce
  const {
    data: searchResults,
    loading: searchLoading,
    error: searchError
  } = app.useFetch(
    async (ctx) => ctx.rpc.searchProperties(filters),
    {
      // Re-fetch when filters change
      deps: [filters],
      // Wait 300ms of "silence" before fetching
      depsDebounce: {
        filters: 300
      }
    }
  );

  // Fetch property details for the found results
  const {
    data: propertyDetails,
    loading: detailsLoading,
    fetch: refreshDetails
  } = app.useFetch(
    async (ctx) => {
      if (!searchResults?.length) return null;

      // This looks like multiple calls, but...
      return ctx.rpc.batch([
        // Everything is multiplexed into a single request!
        ...searchResults.map(result =>
          ctx.rpc.getPropertyDetails(result.id)
        )
      ]);
    },
    {
      // Refresh when searchResults change
      deps: [searchResults]
    }
  );

  // A beautiful and responsive interface
  return (
    <div>
      <FiltersPanel
        value={filters}
        onChange={setFilters}
        disabled={searchLoading}
      />

      {searchError && (
        <Alert status='error'>
          Search error: {searchError.message}
        </Alert>
      )}

      <PropertyGrid
        items={propertyDetails || []}
        loading={detailsLoading}
        onRefresh={() => refreshDetails()}
      />
    </div>
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Beyond useFetch: The Complete Arsenal

RPC: Seni Komunikasi Pelanggan-Pelayan

Keselamatan dan Enkapsulasi

Sistem RPC dalam React Edge direka bentuk dengan mengambil kira keselamatan dan enkapsulasi. Tidak semua dalam kelas RPC didedahkan secara automatik kepada pelanggan:

const PropertyListingPage = () => {
  const { data } = app.useFetch(async (ctx) => {
    // Even if you make 100 identical calls...
    return ctx.rpc.batch([
      ctx.rpc.getProperty('123'),
      ctx.rpc.getProperty('123'), // same call
      ctx.rpc.getProperty('456'),
      ctx.rpc.getProperty('456'), // same call
    ]);
  });

  // Behind the scenes:
  // 1. The batch groups all calls into ONE single HTTP request.
  // 2. Identical calls are deduplicated automatically.
  // 3. Results are distributed correctly to each position in the array.
  // 4. Typing is maintained for each individual result!

  // Actual RPC calls:
  // 1. getProperty('123')
  // 2. getProperty('456')
  // Results are distributed correctly to all callers!
};
Salin selepas log masuk

Hierarki API RPC

Salah satu ciri RPC yang paling berkuasa ialah keupayaan untuk menyusun API ke dalam hierarki:

One of the most impressive parts is how useFetch handles SSR:

const ProductPage = ({ productId }: Props) => {
  const { data, loaded, loading, error } = app.useFetch(
    async (ctx) => ctx.rpc.getProduct(productId),
    {
      // Fine-grained control over when to fetch
      shouldFetch: ({ worker, loaded }) => {
        // On the worker (SSR): always fetch
        if (worker) return true;
        // On the client: fetch only if no data is loaded
        return !loaded;
      }
    }
  );

  // On the server:
  // 1. `useFetch` makes the RPC call.
  // 2. Data is serialized and sent to the client.
  // 3. Component renders with the data.

  // On the client:
  // 1. Component hydrates with server data.
  // 2. No new call is made (shouldFetch returns false).
  // 3. If necessary, you can re-fetch with `data.fetch()`.

  return (
    <Suspense fallback={<ProductSkeleton />}>
      <ProductView
        product={data}
        loading={loading}
        error={error}
      />
    </Suspense>
  );
};
Salin selepas log masuk

Faedah Hierarki

Mengatur API ke dalam hierarki memberikan beberapa faedah:

  • Organisasi Logik: Kumpulan fungsi berkaitan secara intuitif.
  • Ruang Nama Semulajadi: Elakkan konflik nama dengan laluan yang jelas (cth., users.preferences.getTheme).
  • Encapsulation: Pastikan kaedah pembantu peribadi pada setiap peringkat.
  • Kebolehselenggaraan: Setiap subkelas boleh dikekalkan dan diuji secara bebas.
  • Penaipan Penuh: TypeScript memahami keseluruhan hierarki.

Sistem RPC dalam React Edge menjadikan komunikasi pelanggan-pelayan sangat semula jadi sehingga anda hampir terlupa anda membuat panggilan jauh. Dengan keupayaan untuk menyusun API ke dalam hierarki, anda boleh membina struktur yang kompleks sambil memastikan kod anda bersih dan selamat.

Sistem i18n yang Masuk akal

React Edge memperkenalkan sistem pengantarabangsaan yang elegan dan fleksibel yang menyokong interpolasi pembolehubah dan pemformatan kompleks tanpa bergantung pada perpustakaan kelas berat.

class PaymentsAPI extends Rpc {
  // Properties are never exposed
  private stripe = new Stripe(process.env.STRIPE_KEY);

  // Methods starting with $ are private
  private async $validateCard(card: CardInfo) {
    return await this.stripe.cards.validate(card);
  }

  // Methods starting with _ are also private
  private async _processPayment(amount: number) {
    return await this.stripe.charges.create({ amount });
  }

  // This method is public and accessible via RPC
  async createPayment(orderData: OrderData) {
    // Internal validation using a private method
    const validCard = await this.$validateCard(orderData.card);
    if (!validCard) {
      throw new HttpError(400, 'Invalid card');
    }

    // Processing using another private method
    const payment = await this._processPayment(orderData.amount);
    return payment;
  }
}

// On the client:
const PaymentForm = () => {
  const { rpc } = app.useContext<App.Context>();

  // ✅ This works
  const handleSubmit = () => rpc.createPayment(data);

  // ❌ These do not work - private methods are not exposed
  const invalid1 = () => rpc.$validateCard(data);
  const invalid2 = () => rpc._processPayment(100);

  // ❌ This also does not work - properties are not exposed
  const invalid3 = () => rpc.stripe;
};
Salin selepas log masuk

Penggunaan dalam kod:

// Nested APIs for better organization
class UsersAPI extends Rpc {
  // Subclass to manage preferences
  preferences = new UserPreferencesAPI();
  // Subclass to manage notifications
  notifications = new UserNotificationsAPI();

  async getProfile(id: string) {
    return this.db.users.findById(id);
  }
}

class UserPreferencesAPI extends Rpc {
  async getTheme(userId: string) {
    return this.db.preferences.getTheme(userId);
  }

  async setTheme(userId: string, theme: Theme) {
    return this.db.preferences.setTheme(userId, theme);
  }
}

class UserNotificationsAPI extends Rpc {
  // Private methods remain private
  private async $sendPush(userId: string, message: string) {
    await this.pushService.send(userId, message);
  }

  async getSettings(userId: string) {
    return this.db.notifications.getSettings(userId);
  }

  async notify(userId: string, notification: Notification) {
    const settings = await this.getSettings(userId);
    if (settings.pushEnabled) {
      await this.$sendPush(userId, notification.message);
    }
  }
}

// On the client:
const UserProfile = () => {
  const { rpc } = app.useContext<App.Context>();

  const { data: profile } = app.useFetch(
    async (ctx) => {
      // Nested calls are fully typed
      const [user, theme, notificationSettings] = await ctx.rpc.batch([
        // Method from the main class
        ctx.rpc.getProfile('123'),
        // Method from the preferences subclass
        ctx.rpc.preferences.getTheme('123'),
        // Method from the notifications subclass
        ctx.rpc.notifications.getSettings('123')
      ]);

      return { user, theme, notificationSettings };
    }
  );

  // ❌ Private methods remain inaccessible
  const invalid = () => rpc.notifications.$sendPush('123', 'hello');
};
Salin selepas log masuk

Konfigurasi Sifar

React Edge mengesan dan memuatkan terjemahan anda secara automatik. Ia juga membolehkan menyimpan pilihan pengguna dalam kuki dengan mudah. Tetapi, sudah tentu, anda menjangkakan ini, bukan?

// translations/fr.ts
export default {
  'Good Morning, {name}!': 'Bonjour, {name}!',
};
Salin selepas log masuk

Pengesahan JWT "Hanya Berfungsi"

Pengesahan sentiasa menjadi masalah dalam aplikasi web. Menguruskan token JWT, kuki selamat dan pengesahan semula selalunya memerlukan banyak kod boilerplate. React Edge mengubah ini sepenuhnya.

Begini cara mudahnya untuk melaksanakan sistem pengesahan penuh:

const WelcomeMessage = () => {
  const userName = 'John';

  return (
    <div>
      {/* Output: Good Morning, John! */}
      <h1>{__('Good Morning, {name}!', { name: userName })}</h1>
    </div>
  );
};
Salin selepas log masuk

Penggunaan Pelanggan: Konfigurasi Sifar

// worker.ts
const handler = {
  fetch: async (request: Request, env: types.Worker.Env, context: ExecutionContext) => {
    const url = new URL(request.url);

    const lang = (() => {
      const lang =
        url.searchParams.get('lang') || worker.cookies.get(request.headers, 'lang') || request.headers.get('accept-language') || '';

      if (!lang || !i18n[lang]) {
        return 'en-us';
      }

      return lang;
    })();

    const workerApp = new AppWorkerEntry({
      i18n: {
        en: await import('./translations/en'),
        pt: await import('./translations/pt'),
        es: await import('./translations/es')
      }
    });

    const res = await workerApp.fetch();

    if (url.searchParams.has('lang')) {
      return new Response(res.body, {
        headers: worker.cookies.set(res.headers, 'lang', lang)
      });
    }

    return res;
  }
};
Salin selepas log masuk

Mengapa Ini Revolusioner?

  1. Sifar Plat Dandang

    • Tiada pengurusan kuki manual
    • Tidak perlu pemintas
    • Tiada token muat semula manual
  2. Keselamatan secara Lalai

    • Token disulitkan secara automatik
    • Kuki adalah selamat dan httpSahaja
    • Pengesahan semula automatik
  3. Taip Penuh

    • Muatan JWT ditaip
    • Pengesahan Zod Bersepadu
    • Ralat pengesahan ditaip
  4. Penyatuan Lancar

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kedai Kongsi

Salah satu ciri React Edge yang paling berkuasa ialah keupayaannya untuk berkongsi keadaan dengan selamat antara pekerja dan pelanggan. Begini caranya:

Contoh Penggunaan Middleware dan Kedai

// pages/api/search.ts
export default async handler = (req, res) => {
  // Configure CORS
  // Validate request
  // Handle errors
  // Serialize response
  // ...100 lines later...
}

// app/search/page.tsx
'use client';
import { useEffect, useState } from 'react';

export default const SearchPage = () => {
  const [search, setSearch] = useState('');
  const [filters, setFilters] = useState({});
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let timeout;
    const doSearch = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/search?' + new URLSearchParams({
          q: search,
          ...filters
        }));
        if (!res.ok) throw new Error('Search failed');
        setData(await res.json());
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    timeout = setTimeout(doSearch, 300);
    return () => clearTimeout(timeout);
  }, [search, filters]);

  // ... rest of the component
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Bagaimana Ia Berfungsi

  • Data Awam: Data yang ditandakan sebagai awam dikongsi dengan selamat dengan pelanggan, menjadikannya mudah diakses untuk komponen.
  • Data Peribadi: Data sensitif kekal dalam persekitaran pekerja dan tidak pernah terdedah kepada pelanggan.
  • Integrasi dengan Middleware: Middleware boleh mengisi kedai dengan kedua-dua data awam dan peribadi, memastikan aliran maklumat yang lancar antara logik bahagian pelayan dan pemaparan bahagian pelanggan.

Faedah

  1. Keselamatan: Asingkan skop data awam dan peribadi memastikan maklumat sensitif kekal dilindungi.
  2. Kemudahan: Akses telus untuk menyimpan data memudahkan pengurusan negeri merentas pekerja dan pelanggan.
  3. Fleksibiliti: Kedai mudah disepadukan dengan perisian tengah, membenarkan kemas kini keadaan dinamik berdasarkan pengendalian permintaan.

Penghalaan Elegan

Sistem penghalaan React Edge diilhamkan oleh Hono, tetapi dengan ciri yang dipertingkatkan untuk SSR:

// First, define your API on the server
class PropertiesAPI extends Rpc {
  async searchProperties(filters: PropertyFilters) {
    const results = await this.db.properties.search(filters);
    // Automatic caching for 5 minutes
    return this.createResponse(results, {
      cache: { ttl: 300, tags: ['properties'] }
    });
  }

  async getPropertyDetails(ids: string[]) {
    return Promise.all(
      ids.map(id => this.db.properties.findById(id))
    );
  }
}

// Now, on the client, the magic happens
const PropertySearch = () => {
  const [filters, setFilters] = useState<PropertyFilters>({
    price: { min: 100000, max: 500000 },
    bedrooms: 2
  });

  // Reactive search with intelligent debounce
  const {
    data: searchResults,
    loading: searchLoading,
    error: searchError
  } = app.useFetch(
    async (ctx) => ctx.rpc.searchProperties(filters),
    {
      // Re-fetch when filters change
      deps: [filters],
      // Wait 300ms of "silence" before fetching
      depsDebounce: {
        filters: 300
      }
    }
  );

  // Fetch property details for the found results
  const {
    data: propertyDetails,
    loading: detailsLoading,
    fetch: refreshDetails
  } = app.useFetch(
    async (ctx) => {
      if (!searchResults?.length) return null;

      // This looks like multiple calls, but...
      return ctx.rpc.batch([
        // Everything is multiplexed into a single request!
        ...searchResults.map(result =>
          ctx.rpc.getPropertyDetails(result.id)
        )
      ]);
    },
    {
      // Refresh when searchResults change
      deps: [searchResults]
    }
  );

  // A beautiful and responsive interface
  return (
    <div>
      <FiltersPanel
        value={filters}
        onChange={setFilters}
        disabled={searchLoading}
      />

      {searchError && (
        <Alert status='error'>
          Search error: {searchError.message}
        </Alert>
      )}

      <PropertyGrid
        items={propertyDetails || []}
        loading={detailsLoading}
        onRefresh={() => refreshDetails()}
      />
    </div>
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ciri-ciri Utama

  • Laluan Berkumpulan: Pengumpulan logik laluan berkaitan di bawah laluan kongsi dan perisian tengah.
  • Pengendali Fleksibel: Tentukan pengendali yang mengembalikan halaman atau respons API langsung.
  • Pengepala Per-Laluan: Sesuaikan pengepala HTTP untuk laluan individu.
  • Caching Terbina dalam: Permudahkan strategi caching dengan ttl dan tag.

Faedah

  1. Ketekalan: Dengan mengumpulkan laluan berkaitan, anda memastikan aplikasi perisian tengah dan organisasi kod yang konsisten.
  2. Skalabiliti: Sistem ini menyokong penghalaan bersarang dan modular untuk aplikasi berskala besar.
  3. Prestasi: Sokongan asli untuk caching memastikan masa tindak balas yang optimum tanpa konfigurasi manual.

Cache Teragih dengan Cache Tepi

React Edge termasuk sistem caching berkuasa yang berfungsi dengan lancar untuk kedua-dua data JSON dan keseluruhan halaman. Sistem caching ini menyokong penandaan pintar dan ketidaksahihan berasaskan awalan, menjadikannya sesuai untuk pelbagai senario.

Contoh: Caching Respons API dengan Teg

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ciri-ciri Utama

  • Pembatalan Berasaskan Teg: Entri cache boleh dikumpulkan menggunakan teg, membenarkan ketidaksahihan yang mudah dan terpilih apabila data berubah.
  • Padanan Awalan: Batalkan berbilang entri cache menggunakan awalan biasa, sesuai untuk senario seperti pertanyaan carian atau data hierarki.
  • Time-to-Live (TTL): Tetapkan masa tamat tempoh untuk entri cache bagi memastikan kesegaran data sambil mengekalkan prestasi tinggi.

Faedah

  1. Prestasi yang Dipertingkat: Kurangkan beban pada API dengan menyediakan respons cache untuk data yang kerap diakses.
  2. Kebolehskalaan: Mengendalikan set data berskala besar dan trafik tinggi dengan cekap dengan sistem caching teragih.
  3. Fleksibiliti: Kawalan terperinci ke atas caching, membolehkan pembangun mengoptimumkan prestasi tanpa mengorbankan ketepatan data.

Pautan: Komponen Yang Berfikir Ke Hadapan

Komponen Pautan ialah penyelesaian pintar dan berorientasikan prestasi untuk pramuat sumber pihak pelanggan, memastikan pengalaman navigasi yang lebih lancar dan pantas untuk pengguna. Fungsi prefetchingnya dicetuskan apabila pengguna menuding pada pautan, mengambil kesempatan daripada detik terbiar untuk meminta data destinasi terlebih dahulu.

Bagaimana Ia Berfungsi

  1. Prafetch Bersyarat: Atribut prefetch (didayakan secara lalai) mengawal sama ada pramuat dilaksanakan.
  2. Cache Pintar: Satu Set digunakan untuk menyimpan pautan yang telah diambil semula, mengelakkan panggilan pengambilan berlebihan.
  3. Peristiwa Masuk Tetikus: Apabila pengguna menuding pada pautan, fungsi handleMouseEnter menyemak sama ada pramuat perlu dan, jika ya, memulakan permintaan pengambilan untuk destinasi.
  4. Ketahanan Ralat: Sebarang kegagalan semasa permintaan ditindas, memastikan gelagat komponen tidak terjejas oleh isu rangkaian sementara.

Contoh Penggunaan

// pages/api/search.ts
export default async handler = (req, res) => {
  // Configure CORS
  // Validate request
  // Handle errors
  // Serialize response
  // ...100 lines later...
}

// app/search/page.tsx
'use client';
import { useEffect, useState } from 'react';

export default const SearchPage = () => {
  const [search, setSearch] = useState('');
  const [filters, setFilters] = useState({});
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let timeout;
    const doSearch = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/search?' + new URLSearchParams({
          q: search,
          ...filters
        }));
        if (!res.ok) throw new Error('Search failed');
        setData(await res.json());
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    timeout = setTimeout(doSearch, 300);
    return () => clearTimeout(timeout);
  }, [search, filters]);

  // ... rest of the component
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Apabila pengguna menuding pada pautan “Perihal Kami”, komponen akan mula memuatkan data untuk halaman /tentang, memastikan peralihan yang hampir serta-merta. Idea genius, bukan? Diilhamkan oleh dokumentasi react.dev.

app.useContext: The Portal to the Edge

Kait app.useContext ialah asas React Edge, memberikan akses lancar kepada keseluruhan konteks pekerja. Ia menyediakan antara muka yang berkuasa untuk mengurus penghalaan, keadaan, panggilan RPC dan banyak lagi.

Contoh: Menggunakan app.useContext dalam Papan Pemuka

// First, define your API on the server
class PropertiesAPI extends Rpc {
  async searchProperties(filters: PropertyFilters) {
    const results = await this.db.properties.search(filters);
    // Automatic caching for 5 minutes
    return this.createResponse(results, {
      cache: { ttl: 300, tags: ['properties'] }
    });
  }

  async getPropertyDetails(ids: string[]) {
    return Promise.all(
      ids.map(id => this.db.properties.findById(id))
    );
  }
}

// Now, on the client, the magic happens
const PropertySearch = () => {
  const [filters, setFilters] = useState<PropertyFilters>({
    price: { min: 100000, max: 500000 },
    bedrooms: 2
  });

  // Reactive search with intelligent debounce
  const {
    data: searchResults,
    loading: searchLoading,
    error: searchError
  } = app.useFetch(
    async (ctx) => ctx.rpc.searchProperties(filters),
    {
      // Re-fetch when filters change
      deps: [filters],
      // Wait 300ms of "silence" before fetching
      depsDebounce: {
        filters: 300
      }
    }
  );

  // Fetch property details for the found results
  const {
    data: propertyDetails,
    loading: detailsLoading,
    fetch: refreshDetails
  } = app.useFetch(
    async (ctx) => {
      if (!searchResults?.length) return null;

      // This looks like multiple calls, but...
      return ctx.rpc.batch([
        // Everything is multiplexed into a single request!
        ...searchResults.map(result =>
          ctx.rpc.getPropertyDetails(result.id)
        )
      ]);
    },
    {
      // Refresh when searchResults change
      deps: [searchResults]
    }
  );

  // A beautiful and responsive interface
  return (
    <div>
      <FiltersPanel
        value={filters}
        onChange={setFilters}
        disabled={searchLoading}
      />

      {searchError && (
        <Alert status='error'>
          Search error: {searchError.message}
        </Alert>
      )}

      <PropertyGrid
        items={propertyDetails || []}
        loading={detailsLoading}
        onRefresh={() => refreshDetails()}
      />
    </div>
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ciri Utama app.useContext

  • Pengurusan Laluan: Dapatkan akses kepada laluan yang dipadankan, parameternya dan rentetan pertanyaan dengan mudah.
  • Penyepaduan RPC: Buat panggilan RPC yang ditaip dan selamat terus daripada pelanggan tanpa konfigurasi tambahan.
  • Akses Kedai Kongsi: Dapatkan semula atau tetapkan nilai dalam keadaan pekerja-klien kongsi dengan kawalan penuh ke atas keterlihatan (awam/swasta).
  • Akses URL Universal: Akses URL penuh permintaan semasa untuk pemaparan dan interaksi dinamik dengan mudah.

Mengapa Ia Berkuasa

Kait app.useContext merapatkan jurang antara pekerja dan pelanggan. Ia membolehkan anda membina ciri yang bergantung pada keadaan dikongsi, pengambilan data selamat dan pemaparan kontekstual tanpa boilerplate. Ini memudahkan aplikasi yang kompleks, menjadikannya lebih mudah untuk diselenggara dan lebih cepat untuk dibangunkan.

app.useUrlState: Negeri Disegerakkan dengan URL

Cangkuk app.useUrlState memastikan keadaan aplikasi anda disegerakkan dengan parameter pertanyaan URL, menawarkan kawalan terperinci ke atas perkara yang disertakan dalam URL, cara keadaan disiri dan masa ia dikemas kini.

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Parameter

  1. Keadaan Awal

    • Objek yang mentakrifkan struktur lalai dan nilai untuk keadaan anda.
  2. Pilihan:

    • nyahpantun: Mengawal seberapa cepat URL dikemas kini selepas keadaan berubah. Berguna untuk mengelakkan kemas kini yang berlebihan.
    • kebabCase: Menukar kekunci keadaan kepada kebab-case apabila bersiri ke URL (cth., filter.locations → filter-locations).
    • omitKeys: Menentukan kunci untuk dikecualikan daripada URL. Contohnya, data sensitif atau objek besar boleh ditinggalkan.
    • omitValues: Nilai yang, apabila ada, akan mengecualikan kunci yang berkaitan daripada URL.
    • pickKeys: Mengehadkan keadaan bersiri untuk memasukkan kunci yang ditentukan sahaja.
    • awalan: Menambah awalan pada semua parameter pertanyaan untuk ruang nama.
    • url: URL asas untuk disegerakkan, biasanya diperoleh daripada konteks apl.

Faedah

  • API Keadaan Penggunaan yang sama: Penyepaduan mudah dengan komponen sedia ada.
  • Mesra SEO: Memastikan paparan bergantung kepada negeri ditunjukkan dalam URL yang boleh dikongsi dan boleh ditanda buku.
  • Kemas Kini Nyah Lantun: Menghalang kemas kini pertanyaan yang berlebihan untuk input yang berubah dengan pantas, seperti peluncur atau kotak teks.
  • URL Bersih: Pilihan seperti kebabCase dan omitKeys memastikan rentetan pertanyaan boleh dibaca dan berkaitan.
  • Keadaan Penghidratan: Memulakan keadaan secara automatik daripada URL pada lekap komponen, menjadikan pautan dalam lancar.
  • Berfungsi Di Mana-mana: Menyokong pemaparan sisi pelayan dan navigasi sisi klien, memastikan keadaan yang konsisten merentas aplikasi.

Aplikasi Praktikal

  • Penapis untuk Penyenaraian Harta: Segerakkan penapis yang digunakan pengguna seperti senaraiJenis dan sempadan peta ke URL untuk carian boleh kongsi.
  • Paparan Dinamik: Pastikan zum peta, titik tengah atau tetapan paparan lain berterusan merentas penyegaran halaman atau pautan.
  • Keutamaan Pengguna: Simpan tetapan yang dipilih pengguna dalam URL untuk perkongsian mudah atau penanda halaman.

app.useStorageState: Keadaan Berterusan

Kait app.useStorageState membolehkan anda mengekalkan keadaan dalam penyemak imbas menggunakan localStorage atau sessionStorage, dengan sokongan TypeScript penuh.

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pilihan Kegigihan

  • nyahlantun: Mengawal kekerapan menyimpan ke storan.
  • storan: Pilih antara localStorage dan sessionStorage.
  • omitKeys/pickKeys: Kawalan terperinci ke atas data yang dikekalkan.

Prestasi

  • Kemas kini yang dioptimumkan dengan nyahlantun.
  • Pensirilan/penyahserikatan automatik.
  • Caching dalam memori.

Kes Penggunaan Biasa

  • Sejarah carian
  • Senarai kegemaran
  • Pilihan pengguna
  • Keadaan penapis
  • Troli beli-belah sementara
  • Draf borang

app.useDebounce: Kawalan Kekerapan

Nyahlantunkan nilai reaktif dengan mudah:

// pages/api/search.ts
export default async handler = (req, res) => {
  // Configure CORS
  // Validate request
  // Handle errors
  // Serialize response
  // ...100 lines later...
}

// app/search/page.tsx
'use client';
import { useEffect, useState } from 'react';

export default const SearchPage = () => {
  const [search, setSearch] = useState('');
  const [filters, setFilters] = useState({});
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let timeout;
    const doSearch = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/search?' + new URLSearchParams({
          q: search,
          ...filters
        }));
        if (!res.ok) throw new Error('Search failed');
        setData(await res.json());
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    timeout = setTimeout(doSearch, 300);
    return () => clearTimeout(timeout);
  }, [search, filters]);

  // ... rest of the component
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

app.useDistinct: Keadaan Tanpa Pendua

Simpan tatasusunan dengan nilai unik sambil mengekalkan keselamatan jenis.

Kait app.useDistinct mengkhusus dalam mengesan apabila nilai telah benar-benar berubah, dengan sokongan untuk perbandingan yang mendalam dan nyahlantun:

// On the server
class UserAPI extends Rpc {
  async searchUsers(query: string, filters: UserFilters) {
    // Validation with Zod
    const validated = searchSchema.parse({ query, filters });
    return this.db.users.search(validated);
  }
}

// On the client
const UserSearch = () => {
  const { rpc } = app.useContext<App.Context>();

  // TypeScript knows exactly what searchUsers accepts and returns!
  const { data, loading, error, fetch: retry } = app.useFetch(
    async (ctx) => ctx.rpc.searchUsers('John', { age: '>18' })
  );
};
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ciri-ciri Utama

  1. Pengesanan Nilai Berbeza:
    • Menjejaki nilai semasa dan sebelumnya.
    • Mengesan secara automatik jika perubahan bermakna berdasarkan kriteria anda.
  2. Perbandingan Mendalam:
    • Mendayakan semakan kesaksamaan nilai pada tahap yang mendalam untuk objek kompleks.
  3. Perbandingan Tersuai:
    • Menyokong fungsi tersuai untuk mentakrifkan perkara yang merupakan perubahan yang "berbeza".
  4. Melantun:
    • Mengurangkan kemas kini yang tidak perlu apabila perubahan berlaku terlalu kerap.

Faedah

  • API Keadaan Penggunaan yang sama: Penyepaduan mudah dengan komponen sedia ada.
  • Prestasi Dioptimumkan: Mengelakkan pengambilan semula atau pengiraan semula yang tidak perlu apabila nilai tidak berubah dengan ketara.
  • UX Dipertingkat: Menghalang kemas kini UI yang terlalu reaktif, yang membawa kepada interaksi yang lebih lancar.
  • Logik Ringkas: Menghapuskan semakan manual untuk kesamarataan atau pertindihan dalam pengurusan negeri.

Kait dalam React Edge direka bentuk untuk berfungsi secara harmoni, memberikan pengalaman pembangunan yang lancar dan ditaip kuat. Gabungan mereka membolehkan untuk mencipta antara muka yang kompleks dan reaktif dengan kod yang lebih sedikit.

The React Edge CLI: Kuasa di Hujung Jari Anda

CLI untuk React Edge direka untuk memudahkan kehidupan pembangun dengan mengumpulkan alatan penting ke dalam satu antara muka yang intuitif. Sama ada anda seorang pemula atau pembangun berpengalaman, CLI memastikan anda boleh mengkonfigurasi, membangun, menguji dan menggunakan projek dengan cekap dan mudah.

Ciri-ciri Utama

Perintah Modular dan Fleksibel:

  • bina: Membina kedua-dua apl dan pekerja, dengan pilihan untuk menentukan persekitaran dan mod (pembangunan atau pengeluaran).
  • dev: Memulakan pelayan pembangunan setempat atau jauh, membenarkan kerja berasingan pada apl atau pekerja.
  • kerahkan: Mendayakan penggunaan yang pantas dan cekap dengan memanfaatkan kuasa gabungan Cloudflare Workers dan Cloudflare R2, memastikan prestasi dan kebolehskalaan dalam infrastruktur tepi.
  • log: Memantau log pekerja terus dalam terminal.
  • lint: Mengautomasikan pelaksanaan Prettier dan ESLint, dengan sokongan untuk pembetulan automatik.
  • ujian: Menjalankan ujian dengan liputan pilihan menggunakan Vitest.
  • semak taip: Mengesahkan penaipan TypeScript merentas projek.

Kes Penggunaan Dunia Sebenar

Saya berbangga untuk berkongsi bahawa aplikasi pengeluaran pertama menggunakan React Edge sudah pun disiarkan! Ia ialah syarikat hartanah Brazil, Lopes Imóveis, yang sudah pun meraih manfaat daripada prestasi dan fleksibiliti rangka kerja.

Di tapak web mereka, sifat dimuatkan ke dalam cache untuk mengoptimumkan carian dan memberikan pengalaman pengguna yang lebih lancar. Memandangkan ia adalah tapak yang sangat dinamik, cache laluan menggunakan TTL selama 10 saat sahaja, digabungkan dengan strategi yang lapuk sementara pengesahan semula. Ini memastikan tapak menghantar data yang dikemas kini dengan prestasi luar biasa, walaupun semasa pengesahan semula latar belakang.

Selain itu, pengesyoran untuk sifat serupa dikira dengan cekap dan tidak segerak di latar belakang, kemudian disimpan terus ke cache Cloudflare menggunakan sistem caching RPC bersepadu. Pendekatan ini mengurangkan masa tindak balas untuk permintaan seterusnya dan membuat pengesyoran pertanyaan hampir serta-merta. Semua imej disimpan pada Cloudflare R2, menawarkan storan berskala dan teragih tanpa bergantung pada pembekal luaran.

From Next.js to React Edge with Cloudflare Workers: A Story of Liberation
From Next.js to React Edge with Cloudflare Workers: A Story of Liberation

Tidak lama lagi, kami juga akan melancarkan projek pemasaran automatik besar-besaran untuk Easy Auth, mempamerkan potensi teknologi ini dengan lebih jauh lagi.

Kesimpulan

Jadi, pembaca yang dihormati, kami telah sampai ke penghujung perjalanan ini melalui dunia React Edge! Saya tahu masih terdapat banyak ciri luar biasa untuk diterokai, seperti pilihan pengesahan yang lebih mudah seperti Asas dan Pembawa, dan helah lain yang menjadikan hari pembangun lebih bahagia. Tapi tahan! Ideanya ialah untuk membawa artikel yang lebih terperinci pada masa hadapan untuk menyelami setiap ciri ini.

Isyarat spoiler: tidak lama lagi, React Edge akan menjadi sumber terbuka dan didokumenkan dengan betul! Mengimbangi pembangunan, kerja, penulisan dan sedikit kehidupan sosial bukanlah mudah, tetapi keseronokan melihat keajaiban ini dalam tindakan, terutamanya dengan kelajuan tidak masuk akal yang disediakan oleh infrastruktur Cloudflare, adalah bahan api yang membuatkan saya terus maju. Jadi, nantikan, kerana yang terbaik akan datang! ?

Sementara itu, jika anda ingin mula meneroka dan mengujinya sekarang, pakej itu sudah tersedia di NPM: React Edge pada NPM..

E-mel saya ialah feliperohdee@gmail.com, dan saya sentiasa terbuka untuk menerima maklum balas—ini hanyalah permulaan perjalanan ini. Cadangan dan kritikan membina dialu-alukan. Jika anda menikmati apa yang anda baca, kongsikannya dengan rakan dan rakan sekerja anda, dan nantikan lebih banyak kemas kini. Terima kasih kerana membaca sejauh ini, dan jumpa lagi pada masa akan datang! ???

Atas ialah kandungan terperinci Dari Next.js untuk React Edge dengan Cloudflare Workers: A Story of Liberation. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan