开发者
Expo Router vs React Navigation: Which One Should You Use in 2026?
If you've spent any time building React Native apps, you've already bumped into the question. You're setting up a new project, you need to move users between screens, and suddenly you're 40 minutes deep in a documentation rabbit hole wondering whether to go with the familiar React Navigation setup or take the leap to Expo Router. This article is going to break it all down, no hype, no fanboy energy, just an honest look at both options so you can make the call that actually fits your project. First, What Does "Routing" Even Mean in a Mobile App? On the web, routing is pretty intuitive. You type a URL, the browser goes to a page. Simple. In mobile apps, there's no URL bar, no browser history button, nothing like that. But users still need to move between screens, go back to where they came from, open modals, tab between sections, and all of that has to feel smooth and natural. So in mobile development, routing is basically the system you use to manage how screens stack on top of each other, how state is preserved when you go back, how deep links work, and how the app knows which screen to show based on where the user is in the flow. Think of it like this: routing is "moving between screens while keeping your app's memory intact." When someone logs in, fills out a form, gets distracted and opens a modal, then comes back, the app should remember all of that. Routing is the machinery underneath that makes it happen. In React Native, this doesn't come out of the box. The framework gives you the building blocks, but you have to wire up the navigation yourself. That's where libraries come in. Why Navigation Is Such a Big Deal in React Native React Native apps are essentially single-page applications. Everything runs in one JavaScript thread, rendered to native views. There's no browser doing the heavy lifting of managing history or transitions. You're responsible for it all. Bad navigation kills good apps. A janky transition, a broken back button, a modal that doesn't dismi
AI 资讯
I Spent 2 Months Building a 150+ Tool Website with $0 Server Cost
📚 This is Part 1 (Opening) of the UtlKit Tech Series — Next: [Architecture & Trade-offs →] As a frontend developer, I've used countless online tools. And almost all of them suck: Sign-up required — just to format a JSON string? Ad overload — the actual tool gets squeezed into a corner Privacy concerns — your JSON might contain API keys, and the tool sends it to a server Fragmented — formatters on one site, Base64 on another, hashing on a third So I decided to build one that doesn't: no sign-up, no ads, pure client-side computation, data never leaves the browser. The goal was simple — if I need this tool, someone else does too. The result is utlkit.com : 150+ tools, 8 categories, zero server costs. Requirements Requirement Meaning Pure client-side All logic runs in the browser Zero server cost Static hosting, no Node.js backend 150+ pages One page per tool, SEO-friendly Bilingual (EN/ZH) i18n support Dark/Light mode User preference Mobile responsive Works on all devices Why Not Other Frameworks? Option Pros Cons Verdict Vanilla HTML/JS Simple Managing 150+ pages is painful Too slow VuePress / VitePress Fast Docs-oriented, not for interactive tools Not flexible enough Nuxt SSR Powerful Needs a server Violates zero-cost principle Next.js 15 + output: 'export' SSR SEO + client interactivity + static hosting Has pitfalls (covered later) ✅ Best balance The Key Decision: output: 'export' // next.config.js const nextConfig = { output : ' export ' , // Static export trailingSlash : true , // Required for static files images : { unoptimized : true }, // No image optimization server } This means: ✅ Build output is plain HTML/CSS/JS files ✅ Deployable to any static host (Cloudflare Pages, Vercel, GitHub Pages) ✅ Zero server cost ❌ No API Routes, no Server Components, limited dynamic routing Deployment: Zero Cost on Cloudflare Pages Build output : out/ directory, ~14 MB Hosting : Cloudflare Pages Domain : utlkit.com Monthly cost : $0 Build Pipeline npm run build → next build ( o
AI 资讯
From Axios to alova: how we cut 80 lines to 5
Frontend request code often involves repetitive state management. This article compares Axios and alova through a paginated list example, analyzing how request strategization reduces boilerplate and when it's a good fit. The Pattern: Paginated List in Two Ways A common requirement: fetch a user list with pagination. Approach 1: Axios const [ data , setData ] = useState ([]); const [ page , setPage ] = useState ( 1 ); const [ total , setTotal ] = useState ( 0 ); const [ loading , setLoading ] = useState ( false ); const [ error , setError ] = useState ( null ); const fetchUsers = async ( currentPage ) => { setLoading ( true ); setError ( null ); try { const res = await axios . get ( ' /api/users ' , { params : { page : currentPage , pageSize : 10 }, }); setData ( res . data . list ); setTotal ( res . data . total ); } catch ( e ) { setError ( e . message ); } finally { setLoading ( false ); } }; useEffect (() => { fetchUsers ( page ); }, [ page ]); This pattern appears in nearly every data-fetching component. The actual business logic — GET /api/users — occupies a single line. The rest is infrastructure: state declarations, loading toggles, error handling, and effect management. Approach 2: alova with usePagination const { data , total , loading , error , page , pageSize , nextPage , prevPage , } = usePagination ( ( page , pageSize ) => alovaInstance . Get ( ' /api/users ' , { params : { page , pageSize }, }), { page : 1 , pageSize : 10 } ); Both implementations are functionally identical. The key difference is where the state management logic lives: in the component (Axios) vs. inside the hook (alova). What Changed Component of Axios version Handled by alova loading state + toggling Managed internally by usePagination error state + try/catch Managed internally by usePagination data state + assignment Returned as reactive value page state + change handler Built-in nextPage / prevPage total state extraction Extracted from response automatically useEffect dependency tr
AI 资讯
Why your React tournament bracket breaks in Safari (and a 4 KB pure-CSS fix)
You build a tournament bracket with a popular React library. In Chrome it's perfect — neat columns, clean connector lines. Then you open it on an iPhone, or in Safari, or inside your Capacitor app… and every match is crammed into the top-left corner, stacked on top of the round headers. If you've ever shipped a bracket to iOS, you've probably seen this exact bug. Here's why it happens — and a tiny library that fixes it for good. The symptom It looks fine everywhere Chromium runs (Chrome, Edge, Android WebView) and completely broken everywhere WebKit runs: Safari (macOS and iOS) iOS WKWebView Capacitor / Cordova apps Electron-on-WebKit The matches don't just shift a little — they all render at coordinate (0,0) of the bracket, piling on top of each other and the headers. The cause: SVG <foreignObject> in WebKit Most React bracket libraries — @g-loot/react-tournament-brackets , react-tournament-bracket , and friends — render the bracket as an SVG and place each match's HTML inside a <foreignObject> positioned with x / y attributes. WebKit has a long-standing bug: it ignores x , y , and transform on <foreignObject> and positions the content relative to the top-level <svg> instead of the foreignObject's own coordinates. Every match therefore collapses to the origin. And there's no CSS escape hatch — x , y , and transform are all ignored on foreignObject in Safari, so you can't nudge the content back into place. I even tried patching a library to wrap each match in a <g transform="translate(x,y)"> instead of a nested <svg x y> ; WebKit ignores ancestor transforms for foreignObject positioning too. The SVG approach is simply a dead end on WebKit. The fix: don't use SVG at all A bracket is really just columns of cards joined by connector lines — and both are expressible in plain CSS. Here's the key insight. Put each round in a flex column where every match sits in an equal flex: 1 slot. Because each round has half the matches of the previous one, a match's slot spans exactl
AI 资讯
# Agentic AI: Architecture of Autonomous Systems
"A language model that answers questions is a tool. A language model that decides which questions to ask and then acts on the answers is something else entirely." Introduction: When Models Started Deciding For the first several years of modern NLP, the task was always the same: given input, produce output. One forward pass. One completion. Done. In 2022, a paper from Google Brain asked a different question. What if, instead of producing an answer directly, a model could reason about what information it needs, act to retrieve it, and revise its thinking based on what it found? The paper was ReAct: Synergizing Reasoning and Acting in Language Models (Yao et al., 2022). Applying it to an LLM created something qualitatively different: a model that could take real-world actions and adapt its reasoning based on what came back. A completion model is a calculator. An agent is a process: it has a goal, takes steps toward it, and updates when things go wrong. This week I went deep on the architecture behind these systems, the frameworks that define them, and what the open problems look like from a research perspective. Part 1: What Makes a System "Agentic"? The word "agent" gets used loosely in current literature. A clean definition comes from Russell and Norvig's Artificial Intelligence: A Modern Approach : An agent is anything that perceives its environment through sensors and acts upon that environment through actuators. For an LLM-based system, this is a loop: perceive an observation, reason about what to do, act via a tool call or output, observe the result, and loop again. But not every loop qualifies as agentic. Three properties distinguish genuinely agentic systems from tool-augmented chatbots: Property What It Means Goal persistence Maintains the original goal across multiple steps without re-prompting Adaptive planning Revises its approach based on intermediate results Tool autonomy Decides when and which tools to use, not just how to use one it was told to call Mos
AI 资讯
Building a Native QR/Barcode Scanner for React Native — New Architecture Ready
Most QR scanner libraries for React Native share the same problems — they're unmaintained, they don't support the New Architecture, or they pull in a full camera SDK for what is a single-feature module. I wanted something lean, production-grade, and built the right way. So I built it. This is react-native-qr-camera-pro — a QR and barcode scanner for React Native built entirely with native code. No JavaScript frame processing. No unnecessary dependencies. Swift on iOS, Kotlin on Android, TurboModules and Fabric throughout. Why Native-Only? The common alternative is running frame analysis in JavaScript — grabbing frames via a JS-accessible camera API and running a WASM or JS barcode decoder on them. It works, but it puts real pressure on the JS thread and limits your frame rate. With native-only processing: iOS uses AVCaptureMetadataOutput — Apple's own pipeline for detecting machine-readable codes. Frames are never copied to user space; the kernel hands off a reference to the same buffer. Android uses CameraX ImageAnalysis + ML Kit — Google's on-device barcode scanner backed by hardware-accelerated inference where available. The JS bridge is touched at most once every 500ms to deliver a result. Everything else stays native. Architecture The module is three layers: Architecture The module is three layers, each with a single responsibility: Layer What it does JavaScript / TypeScript Public API — QrCameraProView , startScanning() , stopScanning() , toggleTorch() , useBarcodeScanner() , useCameraError() Native Bridge (TurboModules + Fabric) Type-safe JSI communication between JS and native. Codegen spec drives both the iOS C++ adapter and the Android Kotlin stub. Native Platform (iOS + Android) All camera and barcode logic. AVFoundation on iOS, CameraX + ML Kit on Android. Zero JS involvement in frame processing. iOS (Swift) Class Responsibility QrCameraProSwift Owns the AVCaptureSession lifecycle BarcodeThrottler Throttle + dedup logic BarcodeTypeMapper Maps AVMetadataO
AI 资讯
The Simplest Way I Found to Build Drag and Drop in React and Next.js
My Experience Using dnd-kit in React and Next.js For a long time, I avoided building drag-and-drop features in frontend projects 😅 Not because I did not need them. Mostly because drag and drop always felt unnecessarily complicated. When you think about implementing it, your brain immediately jumps to: animations sorting logic touch support accessibility performance state synchronization and suddenly a simple UI interaction feels like a massive feature. But recently, in one of my React and Next.js projects, I decided to finally try dnd-kit. Honestly, it changed my perspective completely. I used AI to help me with the initial setup and understanding some concepts like sortable contexts and drag events, but after that, working with the library felt surprisingly smooth. And that's what impressed me most. dnd-kit feels lightweight, modern, and flexible without becoming overwhelming. It gives you the tools you need without forcing a huge architecture or complicated patterns on your app. Things I Personally Liked About dnd-kit Very clean React-first API Lightweight and composable Works really well in React and Next.js projects Building sortable lists feels much simpler than expected Flexible enough for custom UI and interactions Good developer experience overall Something Interesting I Noticed When a library has a clean architecture and predictable patterns, AI becomes much more useful while learning it. The generated examples were easier to understand, easier to debug, and easier to customize compared to many older drag-and-drop solutions. If you are building things like: kanban boards sortable lists draggable cards dashboards reorderable tables I definitely recommend taking a look at dnd-kit. It ended up being much simpler and more enjoyable than I expected. Website https://dndkit.com/
AI 资讯
Advanced Hooks & State Management Patterns in React
Read Time: ~14 minutes | Building on React fundamentals to master state management at scale Prerequisites : Familiarity with React basics, useState, useEffect (Part 1) 🔗 Series Navigation ← Part 1: Complete Guide from Zero to Production Part 2: Advanced Hooks & State Management ← YOU ARE HERE → Part 3: Performance Optimization (coming next) 📌 What You'll Learn By the end of this guide, you'll understand: ✅ Creating powerful custom hooks ✅ When and how to use useReducer ✅ Managing state globally with Context API ✅ Redux fundamentals and when to use it ✅ Modern alternatives: Zustand and Jotai ✅ Choosing the right pattern for your project ✅ Real-world shopping cart implementation 🎣 Custom Hooks: Reusing Logic Across Components Custom hooks are regular JavaScript functions that let you extract component logic into reusable functions. They're one of the most powerful React patterns. Rule #1: Custom Hooks Must Start with "use" // ✅ Correct - starts with "use" function useFormInput ( initialValue ) { const [ value , setValue ] = useState ( initialValue ); return { value , bind : { value , onChange : e => setValue ( e . target . value ) }, reset : () => setValue ( initialValue ) }; } // ❌ Wrong - doesn't start with "use" function formInput ( initialValue ) { ... } Example #1: useFormInput Hook import { useState } from ' react ' ; function useFormInput ( initialValue = '' ) { const [ value , setValue ] = useState ( initialValue ); return { value , setValue , bind : { value , onChange : e => setValue ( e . target . value ) }, reset : () => setValue ( initialValue ) }; } // Using the custom hook function LoginForm () { const email = useFormInput ( '' ); const password = useFormInput ( '' ); const handleSubmit = ( e ) => { e . preventDefault (); console . log ( email . value , password . value ); email . reset (); password . reset (); }; return ( < form onSubmit = { handleSubmit } > < input {... email . bind } placeholder = " Email " type = " email " /> < input {... password .
AI 资讯
Frontend Engineering in 2026: Mastering Performance and DX
The Redefinition of "Frontend Engineer" in 2026 The era of the frontend engineer as a purely visual specialist is over. In 2026, companies like Vercel, Linear, Figma, Shopify, and major FAANG divisions expect their frontend engineers to think in terms of systems, not just components. A modern frontend engineer must understand rendering pipelines, browser internals, network optimization, and component architecture at the same depth that a backend engineer understands database indexing or API design. This shift is reflected directly in how companies interview frontend candidates. If you walk into a 2026 frontend interview expecting to answer "what's the difference between let and const ," you will be humbled. This guide covers everything you need to know to pass a senior-level frontend interview at a top tech company. Core Web Vitals: The Mandatory Topic You Can't Skip Google's Core Web Vitals have become a standard lens through which senior frontend engineers are evaluated. Interviewers now routinely ask candidates to diagnose performance bottlenecks using CWV metrics. The three primary metrics are: LCP (Largest Contentful Paint): Measures perceived load speed. Target under 2.5 seconds. Optimized via image preloading, server-side rendering, and CDN caching. INP (Interaction to Next Paint): Replaced FID in 2024. Measures responsiveness. Optimized by breaking up long tasks, using web workers, and deferring non-critical JavaScript. CLS (Cumulative Layout Shift): Measures visual stability. Prevents jarring layout shifts by pre-defining dimensions for images, iframes, and dynamic content. Be prepared to walk through a real-world scenario: "Given an LCP score of 4.2s, what is your systematic debugging and optimization approach?" This is now a standard senior frontend interview question. React 19 and the Concurrent Rendering Model React 19 introduced a fully concurrent rendering model that fundamentally changes how components behave. Key concepts interviewers probe in 2026
AI 资讯
Discovering Google Lighthouse . A Small Tool That Changed How I See Web Development
Today I discovered something I honestly should have explored a long time ago: Google Lighthouse. Funny enough, revamping my portfolio is one of those projects I kept pushing forward with the classic “I’ll do it tomorrow” mindset — and somehow tomorrow kept winning. But today I finally sat down and started improving it, and during that process, I came across Lighthouse. For anyone who hasn’t heard of it yet, Google Lighthouse is an open-source automated tool designed to help developers improve the quality of web pages. You can run it on almost any page — whether it’s public or behind authentication. What immediately caught my attention is that it audits things like: Performance Accessibility SEO Best Practices And probably a few more things I’m still discovering You can run Lighthouse directly inside Chrome DevTools, through the command line, or even as a Node.js module. The process is simple: You give Lighthouse a URL, it scans the page, runs a series of audits, and then generates a detailed report showing how your website performs. What makes it powerful is that it doesn’t just tell you what’s wrong it also explains: _ Why the issue matters How it affects users And how you can fix it _ As a beginner software engineer and developer, I’m slowly realizing that writing code is only one part of building great applications. Performance, accessibility, maintainability, and user experience matter just as much. And honestly, tools like Lighthouse make the learning process feel less overwhelming because they point you in the right direction. One thing I’ll say though don’t fall into the trap of chasing a perfect Lighthouse score instead of building useful projects. A lot of developers start optimizing numbers before validating whether the product itself solves a real problem. Lighthouse is a guide, not the final goal. For my portfolio specifically, Lighthouse exposed a few weaknesses immediately: Large unoptimized images Accessibility issues Slow-loading assets Missing metad
AI 资讯
Building a Browser MMD Studio with Three.js
MikuMikuDance still lives mostly on the desktop: PMX models, VMD motion, skirt physics, camera work. We built AnimaStage Lite — an open-source browser studio so you can load assets, preview motion, add FX, and export vertical Shorts without installing MMD. 🔗 Repository: https://github.com/FBNonaMe/animastage-lite 🌐 Live demo: https://animastage-lite.app/ 🎬 Open the studio: https://animastage-lite.app/app Why the browser? Short-form creators need: 9:16 framing and 1080×1920 export Fast PMX + VMD iteration Stable WebGL on everyday laptops AnimaStage Lite is not a full MMD clone — it’s a focused stage : load, animate, light, record. Stack Layer Tech UI React 19 + TypeScript 3D Three.js + React Three Fiber Build Vite 6 Physics Bullet (Ammo.js) HQ video WebCodecs + mp4-muxer Live video MediaRecorder All core features run client-side . What it does Drag & drop PMX/PMD, VMD, textures, HDR Timeline + dopesheet + Bézier curves + VMD export Bullet physics — skirt, hair, accessories RTX Lite — bloom, DOF, weather, style presets MP4 HQ (frame-by-frame) and Live recording Clean capture — no gizmos in the final video 9:16 Lite — lighter render path to reduce WebGL context loss Optional: MediaPipe mocap, Gemini AI keys, Local/WebRTC collab. Try it Online: https://animastage-lite.app/app — drop your PMX + VMD. Locally: bash git clone https://github.com/FBNonaMe/animastage-lite.git cd animastage-lite npm install npm run dev https://animastage-lite.app/ — landing http://localhost:3000/app — studio (local) Optional AI: copy .env.example → .env and set VITE_GEMINI_API_KEY. Open source Star ⭐ the repo, open issues, send PRs: https://github.com/FBNonaMe/animastage-lite MMD models are not bundled — use only content you have rights to publish. What would you use this for — Shorts, VTuber previews, or learning Three.js? Comments welcome. ---