今日已更新 211 条资讯 | 累计 20183 条内容
关于我们

标签:#javascript

找到 546 篇相关文章

AI 资讯

My code reviewer kept asking for JSDoc — so I built a zero-dep CLI that catches it first

I kept running eslint and thinking my codebase was fine — then someone opened a PR and the first comment was "this function needs JSDoc." The problem: linters check your syntax . Nobody checks whether your exported API is actually documented. Those are two very different things. So I built jsdocscan — a zero-dependency CLI that walks your JS/TS files and flags every exported function or class that is missing JSDoc, or has undocumented parameters. What it catches Errors — exported function or class with no /** … */ block at all: ✗ src/api.js:12 fetchUser missing JSDoc ✗ src/utils.js:34 formatDate missing JSDoc Warnings — JSDoc exists but a parameter has no @param tag: ! src/render.js:7 renderCard undocumented params: opts Exit codes are 0 (all clean), 1 (issues found), 2 (usage error) — pipe-friendly. How to use it # scan a directory npx jsdocscan src/ # Python version pip install jsdocscan jsdocscan src/ # skip @param checks — just verify JSDoc exists npx jsdocscan --no-params src/ # machine-readable output npx jsdocscan --json src/ | jq '.[].findings' # summary line only npx jsdocscan --quiet src/ # custom extensions npx jsdocscan --ext .js,.ts src/ What it skips (intentionally) Non-exported functions and internal helpers — these are implementation details Destructured params ({ a, b }) — too many valid @param opts patterns TypeScript type annotations on params — name: string is stripped, @param name is still required Zero dependencies No parsers, no AST, no require("typescript") . It uses a line-by-line scanner that: Detects export function/const/class patterns via regexes Walks backwards to find a preceding /** */ block Compares @param names in the JSDoc against the actual parameter list npx jsdocscan works with zero install time. pip install jsdocscan brings in nothing extra. Links npm: npmjs.com/package/jsdocscan PyPI: pypi.org/project/jsdocscan GitHub (Node): jjdoor/jsdocscan GitHub (Python): jjdoor/jsdocscan-py Both versions pass the same 38-test suite. Same

2026-06-23 原文 →
开发者

Ever had a renamed column quietly break a CSV export? csv-pipe makes it a compile error, reads and writes both ways, and parses several times faster than papaparse. Live playground in the post to try your own data.

csv-pipe: read and write CSV in TypeScript, several times faster than papaparse Myroslav Martsin Myroslav Martsin Myroslav Martsin Follow Jun 22 csv-pipe: read and write CSV in TypeScript, several times faster than papaparse # javascript # typescript # webdev # node 1 reaction Add Comment 2 min read

2026-06-23 原文 →
开发者

10 Things Nobody Tells You About process.env

10 Things Nobody Tells You About process.env I've burned myself on most of these so you don't have to. Here's what I wish someone had told me early on. 1. Keys are case-sensitive on Linux, case-insensitive on Windows process . env . PORT = " 3000 " console . log ( process . env . port ) // undefined on Linux, "3000" on Windows This one got me during a "works on my machine" incident. My Windows dev box ran fine. The Linux CI server crashed because a teammate typed env.port instead of env.PORT . Your CI runs Linux. Your dev box probably runs macOS or Windows. Case-sensitivity differences will bite you. How to handle it : Use a validation layer that throws on missing keys. A simple getEnv("PORT") will catch typos at startup. 2. Values are always strings console . log ( typeof process . env . PORT ) // "string" even if you set PORT=3000 Number(process.env.PORT) can return NaN without throwing. Boolean values like "false" are truthy strings. How to handle it : Always parse. If you use a schema library like CtroEnv, it coerces types and throws on invalid input. 3. process.env is NOT the same as .env This confused me for way too long. process.env is whatever the shell gave the process. A .env file is just a text file dotenv reads to populate process.env . Node doesn't touch .env files on its own. // This won't read .env automatically console . log ( process . env . MY_VAR ) // undefined How to handle it : Call dotenv.config() at entry, or use @ctroenv/node which loads .env files automatically. 4. You can set env vars per-command PORT = 4000 node app.js This sets PORT only for that single process. It doesn't pollute your shell session. Super useful for one-off runs or testing different configurations without editing files. console . log ( process . env . PORT ) // "4000" 5. process.env is mutable at runtime process . env . DATABASE_URL = " postgres://hacker:gotme@evil.com/db " I've seen code that modifies process.env to "fix" config at runtime. Don't do this. If something i

2026-06-23 原文 →
AI 资讯

I got tired of rewriting the same AI boilerplate so I built a library to fix it

Every time I added AI to a React app, I rewrote the same 200+ lines. Streaming loop. Manual message history. Tool call orchestration. Error handling. setIsLoading(false) only if I remembered. After the third project I stopped and asked: why is nobody solving this the way RTK Query solved REST APIs? So I built Strand ( https://github.com/strand-js/strand ). Before const [messages, setMessages] = useState([]) const [isLoading, setIsLoading] = useState(false) async function send(text) { setIsLoading(true) manually stream tokens manually detect tool calls manually loop until done setIsLoading(false) only if you remembered } After const { messages, send, isPending, isStreaming, cancel } = useConversation({ system: 'You are a helpful assistant.', }) Streaming, history, tool calls, cancellation, retry; all handled. The thing nobody else has: useToolCall Works from ANY component; no prop drilling function WeatherStatus() { const { status, input, output } = useToolCall('get_weather') if (status === 'running') return <div>Checking {input?.location}…</div> if (status === 'done') return <div>{output?.temp}°F</div> return null } Live tool state: pending → running → done. Its observable anywhere in your tree. Fixing the isLoading design flaw The Vercel AI SDK has 4+ open issues ( https://github.com/vercel/ai/issues ) about isLoading getting stuck. The reason is architectural because "request sent" and "tokens arriving" are different states. Strand tracks four: const { isPending, isStreaming, isDone, error } = useConversation() // isPending: waiting for first token // isStreaming: tokens arriving // isDone: just completed // error: something failed Works with Anthropic, OpenAI, and Google Gemini npm install @strand-js/core @strand-js/react zod npm install @strand-js/anthropic # or openai, or google Swap providers by changing one server import. Zero frontend changes. v0.1.8, MIT, open source. → https://github.com/strand-js/strand

2026-06-23 原文 →
AI 资讯

Tired of Searching for Different Base64 Tools? I Built One Place for Everything

As developers, we've all been there. Q: Need to decode a Base64 string? Open one website. Q: Need to convert an image to Base64? Open another website. Q: Need to validate a Base64 string? Search Google again. Q: Need to compare two Base64 values? Yet another tool. I found myself repeatedly switching between different websites, browser tabs, and terminal commands just to perform simple Base64-related tasks. So I decided to build something that solved this problem for me. The Goal Keep every commonly used Base64 utility in one place and make it work directly in the browser. No installations. No command-line knowledge required. No account creation. Just open the website and use the tool What You'll Find Instead of only providing an encoder and decoder, I wanted to cover the complete Base64 workflow. Some of the available tools include: Base64 Encode / Decode Image to Base64 Audio to Base64 Video to Base64 Base64 Validator Base64 Detector Base64 Compare Base64 Repair Base64 URL Encode Base64 File Decoder CSS Data URI Converter And more are being added regularly. Why I Built It Honestly, this started as a personal productivity project. I was using different Base64 tools almost every week and got tired of bookmarking multiple websites for related tasks. Having everything in one place turned out to be surprisingly useful, so I decided to make it public. Give It a Try https://base64converters.com I'm continuously improving it and would love feedback from fellow developers. Are there any Base64-related tools or workflows you use frequently that should be included?

2026-06-23 原文 →
AI 资讯

Browser Scroll Restoration Is Broken on SPAs. Here's How a Chrome Extension Fixes It.

Chrome has had scroll restoration support since 2015. You can even control it: history.scrollRestoration = 'manual' . But if you've ever tried to reliably restore a user's position on a React or Next.js app, you know it doesn't work the way you'd expect. Here's what breaks, why it breaks, and how a browser extension can sidestep the entire problem. What the Browser Actually Does The default behavior is history.scrollRestoration = 'auto' . When you navigate back to a page, the browser tries to scroll to where you were. This works fine for static pages. It falls apart for: SPAs where content is injected into the DOM after navigation Infinite scroll pages where the content at a given Y position changes depending on what was previously loaded Lazy-loaded images that push content down after the scroll restore fires The fundamental problem: the browser fires scroll restoration when the page HTML is parsed, not when the page content is fully rendered. A React app that loads a skeleton → fetches data → renders actual content will restore scroll into a partially-rendered DOM. The history.scrollRestoration = 'manual' Trap If you set manual , you own scroll restoration completely. Most Next.js apps do this. The typical approach: // Save position before navigation router . beforeEach (( to , from ) => { savedPositions [ from . path ] = window . scrollY ; }); // Restore after navigation router . afterEach (( to ) => { const position = savedPositions [ to . path ]; if ( position !== undefined ) { nextTick (() => window . scrollTo ( 0 , position )); } }); The nextTick is the problem. It fires after the Vue/React render cycle, but before async data fetching completes. The page renders empty containers, scroll restores to Y=800, then data loads and pushes everything down. User ends up at Y=800 in a now-different page position. The correct fix is to wait until the content that was at Y=800 actually exists. There's no clean hook for this — you'd need to observe the DOM until the expec

2026-06-22 原文 →
AI 资讯

5 Cookie Tricks for Debugging Auth Issues in Chrome (No More Creating Test Accounts)

Debugging authentication in web apps is painful. You need to test the same flow as five different user types — new visitor, returning user, admin, expired session, logged-out — and the easiest way is to constantly create new accounts or clear all your cookies and start over. There's a faster way. These five techniques use direct cookie manipulation to simulate any auth state without touching your database or creating dummy accounts. I use CookieJar for most of this — a free Chrome extension built natively on MV3 that gives you a proper UI for cookie editing. But I'll show you the underlying Chrome DevTools method too, so you understand what's actually happening. 1. Simulate a Logged-Out State Without Clearing Everything The naive approach: clear all cookies and reload. The problem: you just nuked your dev server session token, your local storage flags, your Stripe test mode cookie, and everything else you carefully set up. The targeted approach : identify and delete only the session/auth cookie. Most session cookies are named session , sid , auth_token , _session_id , or something close. In DevTools: Application → Cookies → [your domain] → find the session cookie → right-click → Delete With CookieJar: open the extension, search session , click the trash icon next to just that cookie. Your dev environment stays intact. The user state resets to logged-out. 2. Test the "Returning User" vs "New User" Path Without a Second Account Session cookies tell the server you're authenticated. But many apps use separate cookies to track whether a user has seen the onboarding flow, completed setup, or visited before. Look for cookies like onboarding_complete , setup_done , first_visit , or custom flags in your app code. To test the new user experience: Export your current cookies (CookieJar → Export → JSON format, or copy from DevTools) Delete the specific onboarding/first-visit flag cookie Reload and test the new user path Re-import or re-set the cookie to restore your state This

2026-06-22 原文 →
AI 资讯

Building Margin: A Privacy-First News Reader Inside Chrome's Side Panel

I built a Chrome extension called Margin — a news reader that lives in the browser's side panel and shows one bite-sized story at a time, instead of an infinite-scroll feed. This is a build log: the decisions, the constraints that pushed back, and a couple of things I had to solve in slightly unusual ways. Why the side panel Chrome shipped chrome.sidePanel in MV3 a while back and most uses I saw were utility tools — note-taking, translation helpers. Nobody was using it for content consumption. News felt like a good fit: a side panel that stays open next to whatever you're working on, where you tap through headlines in a couple of minutes without leaving the page. The reading model is intentionally narrow: one card, one headline, one short summary, tap to read the full article at the source . No infinite scroll, no algorithmic feed. If you've used InShorts, the shape will be familiar. The stack Preact + Vite + @crxjs/vite-plugin . Preact because the side panel is a small UI surface and I didn't want React's weight for what's essentially a card stack and a settings screen. @crxjs/vite-plugin handles the MV3-specific build wiring (manifest generation, service worker loader, HMR for the extension context) that would otherwise be a lot of manual plumbing. The constraint that shaped onboarding chrome.sidePanel.open() requires a user gesture . You cannot call it from a background service worker on install — Chrome will throw. That one constraint shaped the whole first-run experience. My first instinct was "just auto-open the panel on install so people see it immediately." Doesn't work. The fix ended up being two-pronged: On chrome.runtime.onInstalled with reason === 'install' , open a real browser tab with a short walkthrough (find the icon → pin it → open the panel). The button on that page calls sidePanel.open() — valid, because the click is the gesture. The first time the panel itself is opened, show an in-panel welcome screen before onboarding, nudging the user to pin

2026-06-22 原文 →
AI 资讯

Why your monorepo audits are lying to you (and how to fix the rot)

We’ve all been there: running a dependency audit, seeing a tool report 100 "unused" files, and realizing with horror that half of those files are actually critical architectural hubs. Static analysis tools in the JavaScript ecosystem are historically built to be "safe"—they flag anything they cannot explicitly trace. But in a complex monorepo with circular dependencies, alias-heavy build tools like Vite, and custom workspace configurations, these tools often collapse. They stop auditing and start "pruning"—treating your architecture as a pile of junk to be deleted. Most tools rely on simple pattern matching or basic Abstract Syntax Tree (AST) walks. They struggle to build a true Control Flow Graph (CFG) or identify Strongly Connected Components (SCCs). When an engine encounters a cycle in a monorepo, it doesn't see a complex architectural component; it sees a disconnected node, labels it "orphaned," and suggests a deletion plan that would effectively brick your build. To audit an architecture correctly, you need to move beyond simple string resolution. You need deep AST and CFG parsing, utilizing high-performance parsers (like OXC) to map actual execution paths. You also need SCC analysis to detect circular dependency chains across package boundaries, coupled with worker-pool parallelization, because auditing 10,000 files in a monorepo shouldn't block the main process. By leveraging these core concepts, I developed entkapp to validate the structural integrity of a workspace. Consider this audit log from an intentionally broken repository: [Linker-DEBUG] Attempting to resolve package-a ... Resolved to: C:/.../package-a/index.js 🔄 Detecting circular dependencies... ⚠️ Detected 1 circular dependencies: Cycle #1: packages/package-a/index.js -> packages/package-a/index.js Here, the engine is forced to acknowledge the structural reality, not just the file list. It validates the boundary, identifies the cycle, and reports the smell without blindly nuking the project. The g

2026-06-22 原文 →
开源项目

Setting up socket.io

This article covers what I learned or maybe didn't really learn. The Problem With Traditional HTTP Most web applications use HTTP. The flow looks like this: Client → Request → Server Client ← Response ← Server Once the server sends the response, the connection is closed. This works perfectly for: Authentication CRUD operations Fetching data Form submissions But what happens when the server needs to send information without being asked? For example: A new task is assigned Someone comments on a task A project status changes A teammate updates a board With traditional HTTP, the browser would need to keep asking: "Anything new?" "Anything new?" "Anything new?" This technique is called polling, and it's inefficient. That's where Socket.io comes in. What Socket.io Actually Does Socket.io creates a persistent connection between the client and server. Instead of repeatedly opening and closing connections, the connection stays alive. Now communication becomes two-way: Client ↔ Server The client can send data whenever it wants. The server can also send data whenever it wants. This is what makes real-time applications possible. Why Express Alone Isn't Enough One thing that confused me initially was why Socket.io couldn't simply be attached directly to my Express app. The answer lies in how Express works. When you write: app . listen ( 5000 ); Express creates the HTTP server internally. You don't have direct access to it. Socket.io, however, needs access to the raw HTTP server. So instead of: app . listen ( PORT ); The flow becomes: const httpServer = createServer ( app ); Then Socket.io attaches to that server: const io = new Server ( httpServer ); Finally: httpServer . listen ( PORT ); This architecture allows Socket.io and Express to share the same server. Understanding Events Socket.io is event-driven. Everything revolves around two methods: socket . emit () and socket . on () Think of them as: emit = send on = listen For example: Client: socket . emit ( " join-project " ,

2026-06-22 原文 →
AI 资讯

5 Cookie Tricks for Debugging Auth Issues in Chrome (No More Creating Test Accounts)

Debugging authentication in web apps is painful. You need to test the same flow as five different user types — new visitor, returning user, admin, expired session, logged-out — and the easiest way is to constantly create new accounts or clear all your cookies and start over. There's a faster way. These five techniques use direct cookie manipulation to simulate any auth state without touching your database or creating dummy accounts. I use CookieJar for most of this — a free Chrome extension built natively on MV3 that gives you a proper UI for cookie editing. But I'll show you the underlying Chrome DevTools method too, so you understand what's actually happening. 1. Simulate a Logged-Out State Without Clearing Everything The naive approach: clear all cookies and reload. The problem: you just nuked your dev server session token, your local storage flags, your Stripe test mode cookie, and everything else you carefully set up. The targeted approach : identify and delete only the session/auth cookie. Most session cookies are named session , sid , auth_token , _session_id , or something close. In DevTools: Application → Cookies → [your domain] → find the session cookie → right-click → Delete With CookieJar: open the extension, search session , click the trash icon next to just that cookie. Your dev environment stays intact. The user state resets to logged-out. 2. Test the "Returning User" vs "New User" Path Without a Second Account Session cookies tell the server you're authenticated. But many apps use separate cookies to track whether a user has seen the onboarding flow, completed setup, or visited before. Look for cookies like onboarding_complete , setup_done , first_visit , or custom flags in your app code. To test the new user experience: Export your current cookies (CookieJar → Export → JSON format, or copy from DevTools) Delete the specific onboarding/first-visit flag cookie Reload and test the new user path Re-import or re-set the cookie to restore your state This

2026-06-21 原文 →
AI 资讯

Building Real-Time Dashboards in Angular with WebSockets — A Complete Guide

Most dashboards are built the same way: the user lands on the page, data loads, and then... it sits there. Stale. Until the user hits refresh or you set up an awkward polling interval that hammers your server every few seconds. There's a better way. WebSockets give you a persistent, two-way connection between your Angular app and your server — meaning your dashboard updates the moment new data exists, with zero wasted requests. In this article we'll build a complete real-time dashboard in Angular from scratch — WebSocket service, Signal-based components, auto-reconnection, and production-ready patterns. How WebSockets Differ From Regular HTTP Before writing any code, it's worth understanding what makes WebSockets special. Regular HTTP: Client → "Give me data" → Server Client ← "Here's your data" ← Server [Connection closes] WebSocket: Client ←→ Server [Connection stays open] Server → "New data!" → Client (anytime) Server → "More data!" → Client (anytime) Client → "Send this" → Server (anytime For a real-time dashboard showing live metrics, user activity, or financial data — the WebSocket model is a natural fit. The server pushes updates the moment they happen. No polling, no refresh button, no stale data. Project Setup For this article we'll build a dashboard that shows three live metrics: active users, requests per second, and server CPU usage. Start with a fresh Angular 22 project: ng new realtime-dashboard --standalone cd realtime-dashboard ng serve RxJS ships with Angular so no extra dependencies are needed — webSocket from rxjs/webSocket handles everything. Step 1 — Define Your Data Model Start with a clear TypeScript interface for the data your server will push: // core/models/dashboard.model.ts export interface DashboardMetrics { activeUsers : number ; requestsPerSecond : number ; cpuUsage : number ; timestamp : Date ; } export interface MetricAlert { type : ' warning ' | ' critical ' ; metric : string ; value : number ; message : string ; } export type Dashb

2026-06-21 原文 →
AI 资讯

Show OS: Universal Uploader – Zero-dependency, stream-based file uploading with transparent XHR fallback

Hey everyone, I wanted to share an open-source library I’ve been developing to solve a persistent issue in frontend file ingestion: handling large-file uploads efficiently without blocking the main thread, consuming excessive client-side memory, or introducing heavy npm dependencies. The core architecture leverages Fetch Duplex streams combined with Web Streams API to achieve constant memory usage during large file transfers. For browsers lacking full duplex stream support (such as Safari), it seamlessly switches to an automated chunked XHR fallback at runtime. ⚙️ Core Architecture & Features Constant Memory Footprint: Streams large chunks sequentially using Fetch duplex streaming where supported. Intelligent Runtime Fallback: Detects capabilities instantly and falls back to a robust, chunked XMLHttpRequest pipeline to ensure cross-browser compatibility (including Safari). Resilient Lifecycle Management: Built-in hooks for pause, resume, manual abort, and automated chunk-level retries with a configurable exponential backoff algorithm. Zero Dependencies & Tree-shakeable: Written entirely in vanilla TypeScript with no external runtime dependencies (npm install u/universal-uploader/core). The architecture is highly modular, ensuring that unused upload strategies are completely tree-shaken during compilation. React Primitive Included: Ships with a declarative React hook that maps the entire upload lifecycle to state primitives without causing redundant re-renders. 🛠️ Why Existing Solutions Didn't Fit Most mainstream uploading libraries either rely on heavy multi-part form encodings that require buffering files entirely into browser memory, or pull in heavy polyfill architectures that bloating the initial bundle size. I designed this to isolate the transport layer logic via a composition-based approach, separating the stream controller from the network client. To ensure deterministic behavior, the codebase is fully covered by 127 integration/unit tests validating network

2026-06-21 原文 →
AI 资讯

When an AI Agent Joins Your Yjs Room, Three Assumptions Break

Wiring an LLM as a first-class Yjs peer is architecturally sound — but it invalidates three silent assumptions your collaboration stack already makes about peer symmetry: throughput, undo ownership, and presence cadence. You've tuned a Yjs provider under real collaborative load. You know the feeling before you can name it — one heavy client starts lagging the room, presence updates stutter, and you end up adding a debounce somewhere and calling it done. Now imagine that client generates text at 3,000 words per minute, never goes offline, and has its own awareness cursor. That's not a sidebar feature. That's a new class of peer, and your collaboration architecture wasn't designed for it. The Demo Is Real — But It Skips the Hard Parts In April 2026, a working demo wired an LLM as a genuine server-side Yjs document peer — same transport as the human editors, same CRDT, its own awareness state. The implementation uses y-prosemirror and the standard awareness protocol directly. If you've shipped TipTap collaboration, you already have every dependency it needs. The architecture is correct. Making the agent a server-side peer — rather than a client-side bolt-on posting diffs over a REST endpoint — gives you one convergence model instead of two, real presence semantics for the agent, and a clean separation between the LLM streaming layer and the document state layer. But the demo establishes the peer model. It doesn't stress-test what happens to your existing assumptions once that peer is running. The Silent Assumption Every CRDT Implementation Makes Here it is — the assumption baked into the Yjs awareness protocol, the undo manager, and your backpressure strategy, the one nobody wrote down because it was always true until now: All peers produce operations at roughly human speed. Not identical speed. Human typists vary. But they land in the same order of magnitude. The entire design space — how often you broadcast awareness, how you scope undo history, whether you need per-

2026-06-21 原文 →
AI 资讯

A free, no-sign-up worksheet generator that runs entirely in the browser

Teachers and parents lose a surprising amount of time hunting for printable practice sheets, then hitting a sign-up wall or a paywall. So I built a small set of free tools that make the sheet you need in a couple of clicks, with no account and no email. They run entirely client-side in the browser, so nothing is uploaded or stored, and every sheet prints straight to paper or saves as a PDF. What is in the set so far: A maths worksheet generator (addition, subtraction, multiplication, division, mixed) with an answer key A name-tracing sheet generator for early writers A spelling worksheet generator A word search maker Routine and chore chart makers The hub is here: Free printable tools A few build notes for anyone making something similar: Keeping it fully client-side meant zero backend cost and instant load, which matters when a teacher opens it on a school tablet on a slow connection. The fiddly part was the print layout. A dedicated print stylesheet with CSS page breaks gave a much cleaner result than forcing a PDF library. Removing the sign-up step takes out all the friction, which is the whole point for a busy classroom. I run a small Brisbane children's book imprint, Lantern Path Books , and these started as a side project to help the parents and teachers who read our picture books. They are free to use and share. Happy to talk through the print-layout approach if it is useful to anyone.

2026-06-21 原文 →
开发者

Introducing Stardust API Engine

Hey developers! 🚀 I wasted too much time setting up dummy backends just to test my frontend designs. So, I built Stardust API Engine — a completely free, serverless mock server. What it does: Instant live endpoints for /users and /products (Ready to fetch() ). In-built Custom JSON Data Generator to structure your own schemas. 100% serverless, zero login friction, and lightning fast. Check it out here: https://stardustofficial.github.io/stardust-api/ Feedback is highly appreciated! Built with 🌌 by Zishan.

2026-06-21 原文 →