AI 资讯
Data Scientist Learning JS: Promises and resolve()
Context: I'm a data scientist/analyst (in Python and R) learning development from scratch. Inevitably, I am learning these through the lens of what I already know. If you have a similar background and are a beginner developer, I hope these analogies help! Any comments, especially if you spot any misunderstanding, are appreciated. Commenting is caring <3 Motivation: I was building a mock data layer for a fitness social app — simulating what happens when users fetch new posts from a feed. The function needs to return mock posts after a delay, simulating a real network request. Working Code: `function fakeFetchPosts() { return new Promise((resolve) => { setTimeout(() => { resolve(posts); }, 2000); }); } async function main() { console.log("Fetching..."); const fetchedPosts = await fakeFetchPosts(); console.log("Fetched posts:", fetchedPosts); } main(); console.log("Sync code ran");` What do you expect to see as an output? I first confused the logic with blocking. For example, in webscraping, something like time.sleep() or Selenium's WebDriverWait(driver, 10).until(EC.presence_of_element_located(...)) . In this case, output will be Fetching..., Fetched posts: ..., then Sync code ran. However, the output gives Fetching..., Sync code ran, and then Fetched posts. In the former, the whole script (single thread) pauses and does nothing else until the wait ends or the condition is met. The latter is different in that the rest of your program keeps running during the wait, and thus the output where Sync code ran is printed first before the fetchedPosts. By the way, posts are arrays. const posts = [{ author: "j1wonkim", text: "Testing Physical", likes: 100, }, {author: "onewc0218", text: "Love love", likes: 55, }, {author: "gakbca", text: "You are good", likes: 10, } ];
AI 资讯
NPM vs Yarn vs pnpm vs Bun Which Package Manager Is Best for Modern Web Development?
As developers, we use package managers almost every day. Whether we are working with Node.js, React, Next.js, TypeScript, Express, Prisma, or other technologies in the JavaScript ecosystem, choosing the right package manager can have a meaningful impact on our development workflow. Recently, I spent some time comparing the most popular package managers: npm, Yarn, pnpm, and Bun. After looking at them from the perspective of performance, dependency management, disk efficiency, ecosystem compatibility, and developer productivity, my current preference is pnpm. Why pnpm? For me, pnpm provides one of the best overall balances between speed, disk efficiency, reliability, dependency management, and developer experience. One of the key differences is how pnpm handles dependencies. It uses a content-addressable store and links packages into projects instead of unnecessarily keeping separate copies of the same packages for every project. This can reduce disk usage and make package installation more efficient, especially when working on multiple JavaScript or TypeScript projects. Another advantage is pnpm's stricter dependency management. It encourages projects to explicitly declare the packages they actually depend on, which can help prevent accidental reliance on transitive dependencies. This becomes particularly useful when working on larger applications, monorepos, or team-based projects. What about Bun? Bun is extremely interesting because it is much more than a package manager. It provides a JavaScript/TypeScript runtime, package manager, test runner, and bundler. Its performance is impressive, especially when it comes to package installation and certain development workflows. However, I don't think raw speed should be the only factor when choosing a technology for production. Compatibility, ecosystem maturity, team familiarity, tooling support, and long-term maintainability are equally important. That is why I see Bun as an excellent and promising tool, but I would not
开发者
Download Multiple Files as a ZIP in React — Including Multi-GB Archives
A “Download all as ZIP” button in React starts simple. A production version also needs progress, cancellation, retry, useful errors, and a plan for archives that are too large for browser memory. In this tutorial, we’ll use Eazip , an open-source ZIP toolkit for JavaScript and React. Its React package gives you a hook for starting ZIP jobs and a ready-made tray for showing their status. Everyday files can be zipped entirely in the browser. When the same feature needs to handle multi-GB archives or thousands of remote URLs, it can move the job to Eazip Cloud without adding any backend code. Install the React package npm install @eazip/react @eazip/react requires React 18 or later. It includes the core ZIP engine, so you do not need to install another Eazip package. Build a working ZIP download component This component lets a user select several files and download them as one ZIP: import { useState } from ' react ' ; import { EazipTray , useEazip } from ' @eazip/react ' ; export function FileZipDownload () { const [ files , setFiles ] = useState < File [] > ([]); const zip = useEazip (); return ( < section > < label > Files to download < input type = "file" multiple onChange = { ( event ) => setFiles ( Array . from ( event . currentTarget . files ?? [])) } /> </ label > < button type = "button" disabled = { files . length === 0 || zip . isBusy } onClick = { () => zip . download ({ files , zipName : ' selected-files.zip ' , }) } > Download { files . length || '' } files as ZIP </ button > < EazipTray /> </ section > ); } There are three Eazip pieces in this example: useEazip() gives the component its download commands and current task. zip.download() starts the ZIP job and returns immediately. <EazipTray /> shows progress, cancel, retry, partial results, errors, and the completed download. No provider or CSS import is required. What happens to the selected files? Without a strategy option, Eazip uses its Local strategy. The selected File objects stay on the user’s devi
AI 资讯
Static File Caching in Nuxt: An Easy and Practical Strategy
Lighthouse kept warning me about inefficient cache lifetimes, even though I had already added caching for my static files. The missing piece was Nuxt Image and its generated /_ipx URLs . In this post, I’ll share the simple caching setup I use for Nuxt build files, public assets, and optimized images without risking stale content after deployment. The basic rule is simple: Cache files aggressively when changing the file also changes its URL. Be more careful when the same URL can serve different content later. You have probably seen the same Lighthouse warning I have: Use efficient cache lifetimes. Browser caching for static files is usually straightforward. You add a Cache-Control header, choose a reasonable lifetime, and the browser avoids downloading the same files again on every visit. However, in a Nuxt application, not every static-looking file should use the same caching policy. Nuxt build files are automatically versioned. Files inside public/ usually are not. Nuxt Image also creates transformed image URLs under /_ipx , which need their own cache rule. In this post, I’ll go through the setup I use, including the Nuxt Image rule that was missing during my latest Lighthouse audit. The simple caching rule The most important question is not whether a file is an image, font, or JavaScript file. The important question is: Will the URL change when the file changes? When the answer is yes, you can safely cache the file for a very long time. When the answer is no, you should use a shorter cache lifetime. Otherwise, visitors may continue seeing an old version after you deploy an update. What the cache directives mean Here are the main directives used in this setup: public allows browsers and shared caches such as CDNs to store the response. max-age controls how long the browser considers the file fresh. s-maxage controls how long shared caches such as Cloudflare consider it fresh. immutable tells the browser that the file is not expected to change while that URL exists.
AI 资讯
I Built 75+ Free Developer Tools — Here's What I Learned
Hey everyone! I'm jinyuan, an indie developer. I recently launched DevTools Box — a free online toolbox with 75+ developer tools. What's in the box? DevTools Box includes tools like: JSON Formatter — beautify and validate JSON Regex Tester — test regular expressions with live matching Base64 Encoder/Decoder — quick encoding and decoding QR Code Generator — generate QR codes instantly Hash Calculator — MD5, SHA-1, SHA-256 and more Color Picker — pick colors and convert between formats ...and 69 more tools! Why I built it I was tired of jumping between different websites for simple dev tasks. Each tool runs entirely in your browser — no login, no ads, no data sent to any server. Tech stack Next.js 14 with App Router TypeScript Tailwind CSS Static export to Cloudflare Pages Try it out Check it out at tdboxs.com . All tools are 100% free. Would love to hear your feedback! What tools would you add?
开发者
Why I Chose NestJS and Never Looked Back
A few years ago, I was just another developer trying to figure out how to build things that actually work, not just things that run once and fall apart the moment real users touch them. I tried a few paths. I read a lot. I broke a lot of things. And somewhere along that road, I found NestJS. At first, it looked like just another tool. Another framework to learn, another thing to add to my resume. But the more I used it, the more I realized something. NestJS wasn't just teaching me how to build backend systems. It was teaching me how to think like someone who builds things meant to last. I did not choose NestJS because it was trendy. I chose it because it made me feel organized in a way nothing else had. It gave structure to ideas that used to feel messy in my head. It made me feel like a professional, not just someone typing code and hoping it works. Here is the lesson I want you to take from this, even if you never write a single line of NestJS code. Anything you build, whether it is software, a business, or even your own life, lasts longer when it has structure. Not rules for the sake of rules, but structure that makes room for growth without everything falling apart. That is what NestJS taught me first, before it taught me anything technical. Organize your thinking, and the work becomes easier to carry. Today, when people ask me why I still use NestJS after all this time, my answer is simple. It is not just a tool I use. It is the reason I became confident in what I do. And once you experience that kind of confidence in your work, it is very hard to walk away from it. I write these thoughts as Peace Melodi, a backend software engineer who cares deeply about building things that hold up under real pressure, real users, and real growth. If any of this resonated with you, I would love to connect. LinkedIn: https://www.linkedin.com/in/melodi-peace-406494368 GitHub: https://github.com/PeaceMelodi
AI 资讯
The bug report that never left the browser
This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . There's a shape of bug I've learned to distrust: the one where the safety net is bolted to the thing it's supposed to catch. I was reading Element Web's reporting code looking for something worth fixing when I hit a function that builds the whole Sentry payload as a single object literal — with two await calls sitting inside it. One of them asks the crypto layer for diagnostics. Optional diagnostics. Nice-to-have detail on a report that is already complete without them. I stopped there, because I could already see how that sentence ends. If the optional thing rejects, the object never exists. If the object never exists, there is no capture call. And the same pattern was waiting one directory over, in the rageshake path. The subsystem being diagnosed could prevent the diagnostic report from leaving the browser. Somebody decides to tell you what broke, and the broken part gets a veto. One deliberate press of a button, both explicit channels gone: the rageshake bundle and the manual Sentry event. I measured it at the boundary that actually counts — a real Sentry Browser SDK with a local, network-free transport. Under the same synthetic failure: zero serialized events before the fix, exactly one after. Same synthetic crypto rejection Before After collectBugReport(): rejected report completed with available diagnostics Sentry envelopes: 0 Sentry events: 1 unrelated context families: retained auxiliary error message or stack: absent Project Overview Element Web is the web client behind Element, a Matrix-based communication app. Its bug-report dialog can send two independent things: a rageshake bundle — logs and diagnostics packed into multipart form data and posted to a configured endpoint — and, when Sentry is configured, a single manually captured Sentry event. Both are explicit. Nothing leaves the browser unless a person opens that dialog and submits it. That framing shaped every deci
开源项目
🔥 sveltia / sveltia-cms - Leading Git-based headless CMS. Successor to Netlify/Decap C
GitHub热门项目 | Leading Git-based headless CMS. Successor to Netlify/Decap CMS. Modern UX, first-class i18n support, mobile support + numerous improvements. Hundreds of real-world examples. Framework-agnostic, open source & free. | Stars: 2,687 | 40 stars this week | 语言: JavaScript
开源项目
🔥 rgthree / rgthree-comfy - Making ComfyUI more comfortable!
GitHub热门项目 | Making ComfyUI more comfortable! | Stars: 3,326 | 7 stars today | 语言: JavaScript
开源项目
🔥 BeiDouMS / BeiDou-Server - Global MapleStory Server BeiDou(冒险岛GMS服务端北斗)
GitHub热门项目 | Global MapleStory Server BeiDou(冒险岛GMS服务端北斗) | Stars: 615 | 2 stars today | 语言: JavaScript
开源项目
🔥 cobusgreyling / loop-engineering - Practical patterns, starters & CLI tools for loop engineerin
GitHub热门项目 | Practical patterns, starters & CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and Boris Cherny). Includes loop-audit, loop-init, loop-cost. | Stars: 10,105 | 83 stars today | 语言: JavaScript
开源项目
🔥 techjarves / Uncensored-Local-Studio - Uncensored local AI studio for Windows, Linux, and macOS. Ze
GitHub热门项目 | Uncensored local AI studio for Windows, Linux, and macOS. Zero-setup GUI for Image Generation, GGUF LLMs, Text to Speech & Speech to Text | Stars: 882 | 35 stars today | 语言: JavaScript
AI 资讯
How to Split PDF by File Size in the Browser with Vue 3 and pdf-lib
Splitting a PDF by file size is one of the most practical but technically tricky operations. Unlike splitting by page count (simple math) or bookmarks (tree traversal), size-based splitting requires estimating and controlling the output size of each chunk — and PDFs don't have a simple "size per page" property. Here's how to build a browser-based PDF splitter that respects file size constraints. The challenge PDFs are notoriously unpredictable in terms of size. Two PDFs with the same number of pages can differ by 10x in file size depending on: Image resolution and compression Font embedding Color space (RGB vs. CMYK) Content complexity (vector graphics vs. scanned images) This means you can't calculate split points with simple arithmetic. You need to estimate, test, and adjust . The stack Vue 3 with Composition API pdf-lib for PDF manipulation Vite for bundling The core implementation The approach is greedy accumulation with size estimation : < script setup lang= "ts" > import { ref } from ' vue ' import { PDFDocument } from ' pdf-lib ' const file = ref < File | null > ( null ) const targetSizeMB = ref < number > ( 10 ) const compression = ref < ' none ' | ' low ' | ' high ' > ( ' low ' ) const splitting = ref ( false ) const progress = ref ( 0 ) const progressTotal = ref ( 0 ) const results = ref < Record < string , Uint8Array >> ({}) async function splitBySize () { if ( ! file . value ) return splitting . value = true const arrayBuffer = await file . value . arrayBuffer () const pdf = await PDFDocument . load ( arrayBuffer ) const totalPages = pdf . getPageCount () const targetBytes = targetSizeMB . value * 1024 * 1024 const outputFiles : Array < { name : string ; data : Uint8Array } > = [] let currentPdf = await PDFDocument . create () let currentSize = 0 let pageNum = 0 for ( let i = 0 ; i < totalPages ; i ++ ) { progressTotal . value = totalPages progress . value = i + 1 // Try adding this page try { const [ copiedPage ] = await currentPdf . copyPages ( pdf , [
AI 资讯
Running a Private LLM Game Master Entirely in the Browser
I recently discovered that you can run a fully interactive, narrative-driven RPG in your browser without uploading a single byte of user data to a cloud server. For a developer who is tired of the "send prompt to API, wait for response, render text" latency loop, this felt like a breakthrough. The result is Starwright , an endless space adventure where the plot is generated dynamically by a private on-device AI model. The Wedge: Latency and Privacy as Features Most browser-based AI games rely on a constant handshake with a remote inference engine. This introduces two friction points: network latency, which breaks immersion during dialogue, and privacy concerns, where your creative inputs are processed by third-party servers. By shifting the compute burden to the client using WebGPU, we can run a small model that runs in your browser entirely offline. This isn't just about cost savings on inference tokens; it’s about the feel of the interaction. When there is no network round-trip, the "typing" feel of the AI game master disappears. The narrative flow becomes immediate, similar to a traditional text adventure but with the generative flexibility of large language models. For developers building AI-native applications, this architecture suggests a shift in how we think about "always-on" AI. Instead of treating AI as a service, we treat it as a local capability. Implementation: WebGPU and Quantization The technical challenge in bringing this experience to the browser was fitting a capable narrative model into the memory constraints of a client device while maintaining responsive performance. We utilized WebGPU to accelerate the matrix multiplications required for inference, allowing the model to run smoothly on both modern desktops and capable laptops. The model is quantized to reduce its footprint, ensuring it can load within seconds. Here is a simplified view of how the inference loop is structured in the application: // Simplified inference loop for the on-device mod
AI 资讯
When Crypto Price Charts Learned to Sing: Building Real-Time Sonification for 1400+ Trading Pairs
I never intended to create an audio trading app. It happened by accident during a particularly frustrating week where my eyes couldn't keep up with fourteen monitor windows simultaneously. I was watching BTC oscillate around $62k while SOL dropped another 0.92%, and my brain just... seized. Too many numbers. Too much noise. What if instead of looking, I listened ? That question led me down a rabbit hole called sonification—the practice of converting data into sound. Today, August 2026, I'm running Confrontational Meditation®, and we're sonifying real-time price movements across 1400+ cryptocurrency pairs. It's unconventional. It's chaotic. It's also the clearest way I've ever understood market movement. The Problem With Eyes Traditional charting is exhausting. You stare at candlesticks, watch moving averages, monitor volume bars. Your visual cortex becomes the bottleneck. Traders develop tunnel vision literally—focusing so hard on one chart that you miss the market context around it. When BICO spiked +28.57% today while VIC crashed -19.19%, the traditional trader has to toggle between windows. The audio listener hears it all at once . Sonification inverts this problem. Your auditory system evolved to detect patterns in sound simultaneously across a frequency spectrum. A symphony has dozens of instruments playing at once, and you parse it instantly. The same neurobiology applies to price sonification. How We Map Markets to Music At Confrontational Meditation®, each cryptocurrency generates a unique tonal signature: Pitch correlates to price. Higher prices = higher frequencies. Lower prices = lower frequencies. Volume (loudness) reflects trading volume. Silent = illiquid. Loud = significant volume. Timbre is determined by asset class or volatility profile. BTC gets a warm, stable tone. Volatility assets like PIVX (down -23.94% today) get harsh, bright timbres. Here's the core logic I built for price-to-frequency mapping: const mapPriceToFrequency = ( currentPrice , pr
AI 资讯
Error Monitoring in Next.js 15 with Sentry What I Actually Track
error.tsx` catches a failure and shows the user something reasonable. It does not tell you the failure happened at all unless you are actively watching. For a while my "monitoring" was a client messaging me that something was broken, which is not monitoring, it is finding out from the worst possible source. Here is the Sentry setup I actually use now, tuned to catch what matters without burying it in noise. 1. The Setup bash npx @sentry/wizard@latest -i nextjs The wizard generates the config files and wraps next.config.ts automatically. Worth reviewing what it creates rather than trusting it blindly, since the defaults capture more than most projects actually need. `ts // sentry.client.config.ts import * as Sentry from '@sentry/nextjs'; Sentry.init({ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, tracesSampleRate: 0.1, environment: process.env.NODE_ENV, }); ` `ts // sentry.server.config.ts import * as Sentry from '@sentry/nextjs'; Sentry.init({ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, tracesSampleRate: 0.1, }); ` tracesSampleRate: 0.1 matters more than it looks like it should. Setting this to 1.0 captures full performance tracing on every single request, which sounds thorough and quickly becomes expensive and noisy once real traffic shows up. Ten percent is a reasonable starting point for most projects, adjustable once you see actual volume. 2. Connecting It to error.tsx This is the piece that is easy to miss. error.tsx handles the user-facing fallback, but nothing about it reports the error anywhere by default. `tsx // app/dashboard/error.tsx 'use client'; import * as Sentry from '@sentry/nextjs'; import { useEffect } from 'react'; export default function DashboardError({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { useEffect(() => { Sentry.captureException(error); }, [error]); return ( Something went wrong. Try again ); } ` Without this useEffect , the error boundary works perfectly from the user's perspective, and you never find out it
AI 资讯
I Built a ₹15 Landing Page About Mumbai's Soul Food
A scroll-driven cinematic page about vada pav. No framework, no build step. Just HTML, CSS, and a story worth telling. Dev.to Frontend Challenge submission.
AI 资讯
How does Drizzle handle migrations - Part 2: Changing database structure
Drizzle is built for that. You change the TypeScript schema, Drizzle generates a new migration that alters your SQLite/D1 tables, and you apply it with Wrangler. High-level loop: Edit TS schema (add/rename/drop columns, tables, indexes, constraints). npx drizzle-kit generate → emits a new migrations/00xx_*.sql diff. Review the SQL (important for destructive changes). Apply it: wrangler d1 execute DB --local/--remote --file migrations/00xx_*.sql . Because D1 is SQLite, some changes are done via table rebuilds under the hood (SQLite can’t do every ALTER TABLE ). Drizzle handles that by: creating a temp table with the new shape, copying data over (mapping/transforming columns), dropping the old table, renaming the temp table. So yes-schema changes work; just be mindful of data migrations. Here are common recipes: Add a column (safe) TS: creditDelta : integer ( ' credit_delta ' ). notNull (). default ( 0 ) Run drizzle-kit generate . It will emit ALTER TABLE ... ADD COLUMN credit_delta INTEGER NOT NULL DEFAULT 0; (or a rebuild if needed). Apply with Wrangler. Make a column NOT NULL (with data) Backfill a default in a migration: UPDATE billing_price_map SET credit_delta = 0 WHERE credit_delta IS NULL ; Then change TS to .notNull() (and maybe .default(0) ), generate migration. Drizzle will rebuild the table so the constraint holds. Rename a column Change the field name in TS and use .as('old_column_name') ? (Not needed.) For SQLite, Drizzle will usually rebuild the table and map old → new : You’ll see a create/copy/drop sequence in the generated SQL. If you also need to transform data, add a custom UPDATE new_table SET new_col = old_col step between copy and drop (or tweak the generated SQL before applying). Change a column type Again, SQLite → rebuild. Drizzle generates new table, copies data (SQLite will try to coerce). If you need specific transforms, add an UPDATE in the migration file. Drop a column SQLite can’t drop columns directly → rebuild. Be careful : verify you
AI 资讯
Google Releases Angular v22 with Stable Signal Forms, OnPush by Default and Experimental WebMCP
Angular v22, Google's TypeScript-first framework, has introduced API stabilizations, ergonomic templates, and tooling enhancements for AI integration. Key developments include the stabilization of Signal Forms, improved change detection strategies, and a new @Service() decorator for dependency injection. The release supports TypeScript 6 and removes deprecated features. By Daniel Curtis
AI 资讯
Advanced Server-Side Caching Patterns in Next.js: From Basic ISR to Granular Control
Originally published on tamiz.pro . Caching in modern web development is no longer just about serving static assets faster; it is the primary mechanism for balancing performance, cost, and data freshness. In the context of Next.js, the caching architecture has evolved significantly, shifting from a simple getStaticProps / getServerSideProps dichotomy to a sophisticated, multi-layered system that spans the Edge Runtime, the Server Components architecture, and the Node.js server environment. For software engineers and systems architects, understanding the default behaviors of Next.js caching is insufficient. To build production-grade applications that handle high concurrency without hammering your database, you must master the advanced patterns: granular revalidation, cache tagging, and external cache management. This article dives deep into these mechanisms, explaining how they work under the hood and how to orchestrate them for optimal performance. The Evolution of Next.js Caching To appreciate advanced patterns, we must first contextualize the current caching model. Next.js 13+ (App Router) introduced a new caching paradigm that is both simpler by default and more powerful when customized. The default behavior is now: App Router (RSC): Components are cached by default. Server Components are rendered once and cached on the server. The next request for the same data returns the cached result. Static Generation: Pages and layouts are built at build time and served statically. Server Components: Fetched data is cached in memory on the server, not in the browser. The critical shift here is that caching is opt-out, not opt-in . Previously, you had to explicitly mark things as static. Now, you must explicitly invalidate cache when data changes. This inversion of control places the responsibility of consistency squarely on the developer, requiring precise tools to manage invalidation. Granular Revalidation: The Tag-Based System The most significant advanced caching pattern