こんにちは!
あなたも私と同じなら、おそらく、即座に応答するチャットボット、ページを更新せずにポップアップ表示されるライブ通知、すぐに更新される共同ツールなど、今日のリアルタイム Web アプリケーションのシームレスなインタラクティブ性に驚嘆していることでしょう。瞬き。デジタル時代において、リアルタイム機能は贅沢品ではなく、期待されるものになりました。
Next.js の世界の開発を追跡している場合は、バージョン 13.4 の注目すべき機能、特にゲームチェンジャーであるサーバー アクションに気付いたかもしれません。これにより、リアルタイム エクスペリエンスを作成する方法がどのように再定義されるかについて興味がありますか?
そうですね、私もそうでした!
このケーススタディを一緒に見ていきましょう。Next.jsサーバー アクションのパワーと精巧さを活用して、リアルタイム アプリケーションを構築する旅に乗り出します。あなたが経験豊富な開発者であっても、リアルタイム アプリの領域に足を踏み入れたばかりの人であっても、たくさんの洞察があなたを待っています。
ボールを転がしてみましょう?
今日のペースの速いデジタル環境では、ゲームや金融から通信やソーシャル メディアに至るまで、さまざまな文脈で「リアルタイム」という用語が頻繁に登場します。しかし、Web アプリケーションの世界における「リアルタイム」とは正確には何を意味するのでしょうか? L
これを分かりやすく説明しましょう。
リアルタイム アプリケーションは、ユーザー入力や外部イベントに即座に応答し、目に見える遅延なく即座にフィードバックを提供するシステムまたはプログラムです。簡単に言うと、現代のデジタル エコシステムにおける絶え間ない情報の流れを反映し、「リアルタイム」で進化するライブで動的なプラットフォームと考えてください。
それを大局的に理解するために、どこにでもあるいくつかの例を考えてみましょう。
インスタント メッセージング アプリ: WhatsAppや Telegram など、メッセージが遅延なく送信、受信、表示されるプラットフォーム。
共同作業ツール: Google ドキュメントを思い浮かべてください。複数のユーザーが同時にドキュメントを編集し、お互いの変更をリアルタイムで観察できます。
Live Stock Tickers : 市場の変動に応じて瞬時に更新される株価を表示するプラットフォーム。
オンライン マルチプレイヤー ゲーム: プレイヤーが遅延ゼロでお互いや環境と対話し、シームレスなゲーム体験を保証します。
では、なぜリアルタイム機能がこれほど求められているのでしょうか?
リアルタイム アプリケーションの構築には次のようなハードルがあります。
スケーラビリティの問題: リアルタイム アプリは多くの場合、多数の同時接続を処理する必要があるため、堅牢なインフラストラクチャが必要です。
データの整合性: さまざまなユーザー インターフェイス間でリアルタイム データの一貫性を確保することは、特に複数の同時編集や操作の場合に困難になる可能性があります。
遅延: リアルタイム アプリの性能は、最も遅いコンポーネントによって決まります。遅延を最小限に抑えるには、慎重な最適化とリソースの効率的な使用が必要です。
リアルタイム アプリケーションの基礎を理解して準備を整えたので、サーバー アクションを備えた Next.js 13.4 が、そのような没入型エクスペリエンスの作成を目指す開発者にとって重要なツールとしてどのように登場するかを詳しく掘り下げていきます。
進化し続ける Web 開発環境において、Next.js は常に最前線に立ち、アプリケーション構築へのアプローチ方法を再定義する機能を導入してきました。バージョン 13.4 も例外ではなく、特にサーバー アクションに重点が置かれています。ただし、詳しく説明する前に、いくつかの用語を明確にしましょう。
React エコシステムのアクションは、まだ実験段階ではありますが、開発者がユーザーの操作に応じて非同期コードを実行できるようにすることで、パラダイム シフトをもたらしました。
興味深いことに、これらは Next.js またはReactサーバー コンポーネントに限定されているわけではありませんが、Next.js を通じて使用するということは、React 実験チャネルに参加していることを意味します。
HTML フォームに慣れている人は、 action
プロパティに URL を渡すことを思い出したかもしれません。アクションを使用すると、関数を直接渡すことができるため、対話がより動的で統合されたものになります。
<button action={() => { /* async function logic here */ }}>Click me!</button>
React と Actions の統合により、楽観的な更新のための組み込みソリューションも提供されます。これは、アクションが画期的である一方、パターンはまだ進化しており、さらに強化するために新しい API が追加される可能性があることを強調しています。
フォーム アクションは、 React のアクションと標準の<form>
API を巧みに組み合わせたものです。これらは HTML の基本的なformaction
属性と共鳴し、開発者がすぐに使用できるプログレッシブ読み込み状態やその他の機能を強化できるようになります。
<!-- Traditional HTML approach --> <form action="/submit-url"> <!-- form elements --> </form> <!-- With Next.js 13.4 Form Actions --> <form action={asyncFunctionForSubmission}> <!-- form elements --> </form>
サーバー関数は基本的にサーバー側で動作する関数ですが、クライアントから呼び出すこともできます。これらにより、Next.js のサーバー側レンダリング機能がまったく新しいレベルに引き上げられます。
サーバー アクションに移行すると、サーバー関数として理解できますが、特にアクションとしてトリガーされるものです。特にaction
プロパティを介したフォーム要素との統合により、クライアント側の JavaScript が読み込まれる前でもフォームがインタラクティブなままであることが保証されます。これにより、React ハイドレーションがフォーム送信の前提条件ではなくなり、よりスムーズなユーザー エクスペリエンスが実現します。
// A simple Server Action in Next.js 13.4 <form action={serverActionFunction}> <!-- form elements --> </form>
最後に、サーバーアクションのサブセットであるサーバーミューテーションがあります。これらは、サーバー上のデータを変更してから、 redirect
、 revalidatePath
、またはrevalidateTag
などの特定の応答を実行する必要がある場合に特に強力です。
const serverMutationFunction = async () => { // Modify data logic here... // ... return { revalidatePath: '/updated-path' }; } <form action={serverMutationFunction}> <!-- form elements --> </form>
注:要約すると、Next.js 13.4 のサーバー アクション フレームワークは、アクション、フォーム アクション、サーバー関数、サーバー ミューテーションによって支えられ、リアルタイム Web アプリケーションへの革新的なアプローチを具体化しています。
ケーススタディを進めていくと、これらの機能がもたらす優れた機能を直接目の当たりにすることになります。
それでは、これからのエキサイティングな旅に備えて準備をしましょう。
リアルタイム アプリケーションの構築というコンテキストでは、Next.js 13.4 のサーバー アクションが重要な役割を果たします。これらのアルファ機能により、サーバー側のデータ変更の管理、クライアント側の JavaScript の削減、およびフォームの段階的な強化が容易になります。
まず、Next.js プロジェクトでサーバー アクションを有効にする必要があります。次のコードをnext.config.js
ファイルに追加するだけです。
module.exports = { experimental: { serverActions: true, }, }
サーバー アクションは、それを使用するサーバー コンポーネント内で定義することも、クライアント コンポーネントとサーバー コンポーネントの間で再利用できるように別のファイルで定義することもできます。
サーバー アクションを作成して呼び出す方法は次のとおりです。
サーバー コンポーネント内: サーバー アクションは、次のようにサーバー コンポーネント内で簡単に定義できます。
export default function ServerComponent() { async function myAction() { 'use server' // ... } }
クライアント コンポーネントの場合: クライアント コンポーネント内でサーバー アクションを使用する場合は、別のファイルにアクションを作成してインポートします。
// app/actions.js 'use server' export async function myAction() { // ... }
クライアント コンポーネントでのインポートと使用:
// app/client-component.js import { myAction } from './actions' export default function ClientComponent() { return ( <form action={myAction}> <button type="submit">Add to Cart</button> </form> ) }
カスタム呼び出し: startTransition
などのカスタム メソッドを使用して、フォーム、ボタン、入力の外部でサーバー アクションを呼び出すことができます。
// Example using startTransition 'use client' import { useTransition } from 'react' import { addItem } from '../actions' function ExampleClientComponent({ id }) { let [isPending, startTransition] = useTransition() return ( <button onClick={() => startTransition(() => addItem(id))}> Add To Cart </button> ) }
Next.js 13.4 では、Progressive Enhancement も提供されており、JavaScript なしで<form>
を機能させることができます。サーバー アクションは<form>
に直接渡すことができるため、JavaScript が無効になっている場合でもフォームをインタラクティブにすることができます。
// app/components/example-client-component.js 'use client' import { handleSubmit } from './actions.js' export default function ExampleClientComponent({ myAction }) { return ( <form action={handleSubmit}> {/* ... */} </form> ) }
サーバー アクションに送信される最大リクエスト本文は、デフォルトでは 1MB です。必要に応じて、 serverActionsBodySizeLimit
オプションを使用してこの制限を構成できます。
module.exports = { experimental: { serverActions: true, serverActionsBodySizeLimit: '2mb', }, }
Next.js 13.4 を使用してリアルタイム アプリケーションの構築を開始するには、最初のステップは新しいプロジェクトを作成することです。標準の Next.js CLI コマンドを使用してプロジェクトを初期化できます。
npx create-next-app@latest my-real-time-app
my-real-time-app
プロジェクトの目的の名前に置き換えます。このコマンドは、デフォルト構成で新しい Next.js プロジェクトをセットアップします。
リアルタイム機能には、必要となる可能性のある特定のパッケージと依存関係があります。アプリケーションの詳細に応じて、これらは WebSocket ライブラリから GraphQL サブスクリプションなどに及ぶ可能性があります。
プロジェクトの要件を確認し、必要な依存関係を追加したことを確認してください。
ただし、Next.js 13.4 のサーバー アクションのサポートにより、サーバー側の処理をサポートする組み込みのセットアップがすでに存在し、一部のリアルタイム機能の実現に役立ちます。
Next.js 13.4 の導入により、 App Router は開発者が共有レイアウト、ネストされたルーティング、エラー処理などを利用できるようにする重要な機能です。これは既存のpages
ディレクトリと連携して動作するように設計されていますが、 app
という名前の新しいディレクトリ内に格納されます。
App Router の使用を開始するには:
プロジェクトのルートにapp
ディレクトリを作成します。
このディレクトリ内にルートまたはコンポーネントを追加します。
デフォルトでは、 app
ディレクトリ内のコンポーネントはサーバー コンポーネントであり、最適なパフォーマンスを提供し、開発者が簡単に導入できるようにします。
構造の例を次に示します。
my-real-time-app/ │ ├── app/ # Main directory for App Router components │ ├── _error.js # Custom error page │ ├── _layout.js # Shared layout for the app │ │ │ ├── dashboard/ # Nested route example │ │ ├── index.js # Dashboard main view │ │ └── settings.js # Dashboard settings view │ │ │ ├── index.js # Landing/Home page │ ├── profile.js # User profile page │ ├── login.js # Login page │ └── register.js # Registration page │ ├── public/ # Static assets go here (images, fonts, etc.) │ ├── images/ │ └── favicon.ico │ ├── styles/ # Global styles or variables │ └── global.css │ ├── package.json # Dependencies and scripts ├── next.config.js # Next.js configuration └── README.md # Project documentation
コンポーネントがどのようにレンダリングされるかを考えることが重要です。従来の SPA (シングル ページ アプリケーション) では、React はクライアント側でアプリケーション全体をレンダリングします。サーバー コンポーネントを使用すると、アプリケーションの多くがサーバー上でレンダリングされるため、パフォーマンスが向上します。ガイドラインは次のとおりです。
サーバー コンポーネント: アプリケーションの非対話型部分に最適です。これらのコンポーネントはサーバー上でレンダリングされ、HTML としてクライアントに送信されます。ここでの利点は、パフォーマンスの向上、クライアント側の JavaScript の削減、およびデータのフェッチやバックエンド リソースへの直接アクセスができることです。
クライアント コンポーネント: インタラクティブな UI 要素に使用されます。これらはサーバー上で事前にレンダリングされ、クライアント上で「ハイドレート」されて対話性が追加されます。
これらのコンポーネントを区別するために、Next.js では"use client"
ディレクティブが導入されました。このディレクティブは、コンポーネントがクライアント コンポーネントとして扱われる必要があることを示します。これは、インポートの前に、コンポーネント ファイルの先頭に配置する必要があります。
たとえば、提供されたコードのように対話型カウンターがある場合は、 "use client"
ディレクティブを使用して、それがクライアント側コンポーネントであることを示します。
アプリケーションを構築する際のガイドラインは次のとおりです。
デフォルトでサーバー コンポーネントを使用します ( app
ディレクトリにあるため)。
インタラクティブ性の追加、ブラウザー専用 API の利用、状態またはブラウザーの機能に依存する React フックの活用など、特定のユースケースがある場合にのみ、クライアント コンポーネントを選択してください。
注:この構造とセットアップに従えば、Next.js 13.4 のサーバー アクションを使用してパフォーマンスの高いリアルタイム アプリケーションを構築できるようになります。
Next.js 13.4 のパワーは、リアルタイム バックエンド機能をプロジェクトに統合するときに輝きます。 my-real-time-app
に関連するコード例を使用して手順を見てみましょう。
my-real-time-app
の場合、サーバー アクションは、 frontendとbackendの間の主要なブリッジとして機能し、個別の API を必要とせずに効率的なデータ トランザクションを可能にします。
// my-real-time-app/app/actions/index.js export * from './auth-action'; export * from './chat-action';
my-real-time-app
では、サーバー アクションを活用して認証プロセスを合理化します。
// my-real-time-app/app/actions/auth-action.js export const login = async (credentials) => { // Logic for authenticating user with credentials // Return user details or error message }; export const logout = async (userId) => { // Logic for logging out the user // Return success or error message }; export const register = async (userInfo) => { // Logic for registering a new user // Store user in database and return success or error message };
チャット機能の場合:
// my-real-time-app/app/actions/chat-action.js export const sendMessage = async (messageDetails) => { // Logic to send a new message // Store message in database and inform other users via WebSocket or similar }; export const receiveMessage = async () => { // Logic to receive a message in real-time // Return the message details }; export const getRecentMessages = async (userId) => { // Logic to fetch recent messages for the user // Retrieve messages from the database };
MongoDB をプライマリ データ ストアとして使用する:
// Initialize MongoDB connection const { MongoClient } = require('mongodb'); const client = new MongoClient(process.env.MONGODB_URI); await client.connect(); // Now, use this connection in server actions to interact with the database.
チャットアクションでは:
// my-real-time-app/app/actions/chat-action.js export const sendMessage = async (messageDetails) => { const messagesCollection = client.db('chatDB').collection('messages'); await messagesCollection.insertOne(messageDetails); // Inform other users via WebSocket or similar };
セキュリティのため:
// Middleware for validating request data const validateRequest = (req) => { // Validation logic here return isValid; }; export const sendMessage = async (messageDetails) => { if (!validateRequest(messageDetails)) { throw new Error("Invalid request data"); } // Remaining logic... };
このセクションでは、 my-real-time-app
用の直感的で応答性の高いチャット インターフェイスを構築します。 Next.js 13.4 のサーバー コンポーネントの統合により、リアルタイムの更新が可能になり、スムーズなユーザー エクスペリエンスが実現します。
まず、メインのチャット インターフェイスを作成しましょう。
// my-real-time-app/app/chat-interface.js import { useEffect, useState } from 'react'; import { getRecentMessages } from './actions/chat-action'; export default function ChatInterface() { const [messages, setMessages] = useState([]); useEffect(() => { async function loadMessages() { const recentMessages = await getRecentMessages(); setMessages(recentMessages); } loadMessages(); }, []); return ( <div className="chatBox"> {messages.map(msg => ( <p key={msg.id}>{msg.content}</p> ))} </div> ); }
このコンポーネントは、読み込み時に最近のメッセージをフェッチし、チャットボックスに表示します。
次に、WebSocket の基本的な例を使用してリアルタイム更新をセットアップします。
// my-real-time-app/app/chat-interface.js const [socket, setSocket] = useState(null); useEffect(() => { const ws = new WebSocket("ws://your-backend-url/ws"); ws.onmessage = (event) => { const newMessage = JSON.parse(event.data); setMessages(prevMessages => [...prevMessages, newMessage]); }; setSocket(ws); return () => { ws.close(); }; }, []);
このフックは WebSocket 接続を確立し、新しいメッセージを受信するとメッセージ リストを更新します。
UX を向上させるために、新しいメッセージをユーザーに通知しましょう。
// my-real-time-app/app/chat-interface.js useEffect(() => { if (messages.length && "Notification" in window && Notification.permission === "granted") { const lastMessage = messages[messages.length - 1]; new Notification(`New message from ${lastMessage.sender}: ${lastMessage.content}`); } }, [messages]);
この効果は、メッセージ リストが新しいメッセージで更新されるたびにブラウザ通知を送信します。
スムーズなエクスペリエンスを確保するには:
const HeavyComponent = React.lazy(() => import('./HeavyComponent')); function Chat() { return ( <React.Suspense fallback={<div>Loading...</div>}> <HeavyComponent /> </React.Suspense> ); }
React Server Components
を使用してロジックを分割します。
以前のドキュメントで説明したように、サーバー コンポーネントは非対話型部分に使用でき、クライアント コンポーネントは対話型部分を処理できるため、クライアントに送信される JavaScript の量が削減されます。
たとえば、チャットでは、メッセージ履歴をサーバー コンポーネントにすることができますが、クライアント側の対話性が必要な入力フィールドと送信ボタンはクライアント コンポーネントにすることができます。
リアルタイム アプリケーションのコア コンポーネントを適切に配置したら、それらが期待どおりに機能し、パフォーマンス、拡張性、堅牢性を確保することが重要です。このセクションではmy-real-time-app
のようなリアルタイム システムに合わせたさまざまなテスト アプローチに光を当てます。
リアルタイム アプリケーションの場合、エンドツーエンドのテストが重要です。 Cypress を使用して例を設定してみましょう。
// cypress/integration/chat.spec.js describe('Chat functionality', () => { it('should send and receive messages in real-time', () => { cy.visit('/chat'); cy.get('[data-cy=messageInput]').type('Hello, World!'); cy.get('[data-cy=sendButton]').click(); cy.contains('Hello, World!').should('exist'); }); });
これは、多数のユーザーまたはメッセージが存在する場合にシステムがどのように動作するかを理解するのに役立ちます。
# artillery-config.yml config: target: 'http://my-real-time-app.com' phases: - duration: 300 arrivalRate: 20 scenarios: - flow: - emit: channel: 'chat' payload: message: 'Hello, World!'
$ artillery run artillery-config.yml
Node.js にはプロファイリング用の組み込みツールが用意されており、Next.js 開発サーバーで--inspect
フラグを使用して Node.js インスペクターを有効にすることができます。 Chrome の DevTools を使用すると、パフォーマンスのボトルネックについての洞察を得ることができます。
クライアント側の場合、Chrome DevTools のPerformance
タブのようなツールは、レンダリングのボトルネックを特定するのに役立ちます。特にリアルタイム更新の場合は、不必要なレンダリングが発生しないようにしてください。
リアルタイム アプリケーションでは、多くの場合、クライアントの状態をサーバーと同期させます。 SWR や React Query などのライブラリは、自動再フェッチ、キャッシュ、リアルタイム同期などの機能を提供することで、これを容易にします。
SWR を使用した例:
// my-real-time-app/app/chat-interface.js import useSWR from 'swr'; function ChatInterface() { const { data: messages } = useSWR('/api/messages', fetcher); // ... rest of the component }
バックエンドのスケーラビリティ (特に WebSocket の場合) については、Redis などのソリューションを使用してサーバーの複数のインスタンス全体の状態を管理することを検討してください。このようにして、1 つのサーバー インスタンスがメッセージを受信すると、そのメッセージを他のサーバー インスタンスに接続されているクライアントにブロードキャストできます。
データベース クエリ、特にリアルタイム アプリケーションで頻繁に実行されるクエリが最適化されていることを確認します。重要な列にインデックスを付け、頻繁にアクセスされるデータにはデータベース キャッシュ ソリューションの使用を検討してください。
注:リアルタイム アプリケーションをテストするには、標準的なソフトウェア テスト手法と、リアルタイム システムの課題や特性に合わせて特別に調整されたいくつかの手法を組み合わせる必要があります。 my-real-time-app
の厳格なテスト体制を確保することで、ユーザー トラフィックやデータ フローの規模に関係なく、スムーズで応答性の高いユーザー エクスペリエンスを保証できます。
リアルタイム アプリケーションの基本アーキテクチャがしっかりと確立されたので、今度はその機能とパフォーマンスを改良することに注意を向けます。ユーザー エクスペリエンスを向上させ、 my-real-time-app
を最適化するためのいくつかの戦略を次に示します。
受信者がメッセージを読んだときに、ユーザーに視覚的なフィードバックを提供します。これにより、リアルタイム チャットのインタラクティブな性質が強化されます。
// my-real-time-app/app/components/Message.js function Message({ content, status }) { return ( <div> <p>{content}</p> {status === 'read' && <span>✓ Read</span>} </div> ); }
ユーザーがオンラインの場合、ユーザーの名前またはアバターの横にインジケーターを表示します。
// my-real-time-app/app/components/UserStatus.js function UserStatus({ isOnline }) { return ( <div> {isOnline ? <span className="online-indicator"></span> : <span className="offline-indicator"></span>} </div> ); }
可能な場合はサーバー側の更新をバッチ処理して、クライアントに送信されるメッセージの数を減らします。
更新頻度が高いアプリケーションの場合は、WebSocket メッセージを圧縮して転送されるデータを削減し、速度を向上させることを検討してください。
// Example: Setting up compression with a WebSocket server const WebSocket = require('ws'); const wss = new WebSocket.Server({ perMessageDeflate: { zlibDeflateOptions: { // Add compression options here } } });
クライアントからの急速な連続更新に気付いた場合は、これらをデバウンスして、より少数の、より意味のある更新に統合することを検討してください。
データの整合性が最重要であるアプリの重要なセクションでは、イベント ソーシング パターンの採用を検討してください。これにより、アプリケーションの状態に対するすべての変更がイベントとして確実にキャプチャされ、イベントの信頼性の高い回復と再生が可能になります。
ネットワークの問題によりメッセージの送信に失敗した場合、または更新が完了しなかった場合には、再試行メカニズムが導入されていることを確認してください。
// Example: Simple retry logic with fetch let retries = 3; function fetchData(url) { fetch(url) .then(response => response.json()) .catch(error => { if (retries > 0) { retries--; fetchData(url); } else { console.error('Failed to fetch data after 3 retries'); } }); }
データを定期的にバックアップし、障害が発生した場合にデータを回復するための明確な計画とプロセスを確保してください。フォールト トレランスのために、データベース レプリケーションまたは Cassandra などの分散データベースを使用します。
注: my-real-time-app
の継続的な成功は、そのコア機能だけでなく、摩擦のないユーザー エクスペリエンスを保証する微妙な機能強化と継続的な最適化にもかかっています。上記の戦略を組み込むことで、信頼性が高く楽しい優れたチャット エクスペリエンスをユーザーに提供する準備ができています。
my-real-time-app
での取り組みでは、Next.js 13.4 での初期セットアップから、サーバー アクションを使用したバックエンドの構築、シームレスなフロントエンド エクスペリエンスの設計、リアルタイム機能のテストと最適化の確認までを行いました。私たちはサーバーとクライアントのコンポーネントの微妙な違いを深く掘り下げ、サーバー側のレンダリングとクライアント側の対話性の間の効果的なバランスを確保しました。
Next.js 13.4 でのサーバー アクションの導入により、リアルタイム アプリケーションへのアプローチに革命が起こりました。これにより、サーバーとクライアントの両方のレンダリングの長所を活用する、高度にインタラクティブなチャット アプリケーションを構築できるようになりました。これにより、パフォーマンスが最適化されただけでなく、セキュリティや効率を損なうことなくシームレスなユーザー操作が容易になりました。
my-real-time-app
長い道のりを歩んできましたが、将来の機能拡張の可能性は依然として膨大です。
リアルタイム アプリケーションへの取り組みを開始し、Next.js の機能と複雑さをさらに深く掘り下げる際に、ガイド、インスピレーション、およびさらなる教育に役立つ厳選されたリソースのリストを以下に示します。
まず最初に、 Next.js の世界のこの複雑な迷路を一緒に旅してくれて、本当にありがとうございます。ここまで進んだなら、おめでとうございます!もしあなたがいくつかの部分をざっと読んだとしても、私はあなたを責めません。私もそれらを書くのをスキップしたかったときがありました。
リアルタイム アプリケーションの構築は、さまざまな意味で感情のジェット コースターです。自分がコーディングの天才であると感じる日もあれば、開発者になるきっかけとなった人生のあらゆる選択に疑問を感じる日もありました。
問題のデバッグに何時間も費やした後、セミコロンを見逃していたことに気づいたという経験はありませんか?あるいは、コードの重要な部分を誤って削除してしまい、Ctrl + Z があればいいのにと思ったときはありませんか?ああ、プログラミングの楽しさよ!
しかし、問題はここにあります。あらゆる手のひらを手のひらに当てたり、時折髪の毛を引っ張ったりする中で、自分の作品にリアルタイムで命が吹き込まれていくのを見ると、言葉では言い表せない魔法がかかります。それは、コードがエラーなしで実行されたときの小さな喜び、ユーザーがアプリを気に入ったときの満足感、そして何かをゼロから構築したことを知る誇りです。
これを読んでいるすべての新進開発者へ: 挫折、挫折、そして「なぜこれがうまくいかないのか!」瞬間は私たちの旅の一部です。それらはあなたが失敗しているという兆候ではなく、むしろより良くなるための足がかりです。
したがって、次回あなたのコードが連携を拒否したときは、深呼吸してコーヒー (またはお茶、私は判断しません。私自身マテコシドのファンです) を飲み、この問題に陥っているのはあなただけではないことを思い出してください。
限界を押し広げ、学習を続けてください。機能するか壊れるかにかかわらず、コードのすべての行が開発者ストーリーに章を追加することを忘れないでください。
そして、もしあなたが笑いや肩を寄せて泣いてほしいと思ったことがあるなら(もちろん事実上)、私もそこにいて、それをし、ラップトップを窓から投げ捨てることを考えるほどイライラしたことがあるということを知ってください。
コーディングの冒険をさらに増やし、セミコロンによって引き起こされるバグを減らしましょう。
乾杯、コーディングを楽しんでください!