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

标签:#EV

找到 3542 篇相关文章

开发者

The New HTTP QUERY Method

If you've ever built a search endpoint, you've hit this wall. Your query has filters, sort orders, a nested set of facets, maybe a geo bounding box. It doesn't fit in a URL, and cramming it into query string params is ugly and fragile. So you reach for POST /search , send the whole thing as a JSON body, and quietly accept that you've just lied about what the request does. It's not creating anything. It's a read. But POST is the only tool that lets you attach a body without fighting the platform. That gap finally got filled. In June 2026 the IETF published RFC 10008 , which defines the HTTP QUERY method: a new verb built for exactly this case. The two bad options Every read that needs structured input has been stuck choosing between GET and POST, and both are wrong in their own way. GET is the semantically correct choice. It's safe (the client isn't asking to change anything), it's idempotent (retrying it is fine), and it's cacheable. The problem is the body. RFC 9110 is explicit that content in a GET request has no defined semantics , and sending one may cause some implementations to reject the request. So your query has to live in the URI, where you run into unknown length limits across proxies and servers, encoding overhead, and the query landing in access logs and browser history. POST solves the body problem and creates a new one. It carries any payload you want, but it's neither safe nor idempotent by definition. Intermediaries won't cache it, clients won't retry it automatically after a dropped connection, and anything inspecting traffic has to assume the request might have side effects. You get the body, you lose everything that made the request honest. QUERY is the missing third option: a method that carries a body and keeps the semantics of a read. What QUERY actually is The spec, authored by Julian Reschke, James Snell , and Mike Bishop, describes it in one sentence: A QUERY requests that the request target process the enclosed content in a safe and idempo

2026-07-08 原文 →
AI 资讯

What We Learned Rewriting an Interactive Map Editor: Fabric.js, CORS, and 20,000 Lines of Legacy TypeScript

A story about how migrating an interactive office map editor turned into an engineering investigation involving Fabric.js, tainted canvas , and an architecture that's finally easy to extend. In most software projects, one sentence usually makes every developer nervous: "Let's rewrite this module from scratch." It often means months of development, regression risks, and endless architecture discussions. Our project was no different. We develop, a workspace management platform that allows companies to manage office spaces and book desks. One of its core features is an interactive office map editor, where administrators upload floor plans, place desks and meeting rooms, and publish maps for employees. Over the years, this editor slowly evolved into a real monolith. And the problem wasn't simply the number of lines of code. Where It All Started The editor dated back to the AngularJS era. The main component had gradually grown into a single file responsible for almost everything: loading maps working with Fabric.js CRUD operations keyboard shortcuts dialogs saving event handling The main editor component alone contained nearly 2,270 lines of code . Behind it lived another codebase — the map engine itself. Almost 20,000 lines of TypeScript spread across more than 230 files. One of the biggest architectural issues was an infinite rendering loop. fabric . util . requestAnimFrame (() => this . tick ()); Even when the user wasn't interacting with the editor, rendering continued forever. It worked. But every new feature became more expensive to build. Why We Decided to Rewrite It The motivation wasn't AngularJS itself. The real reason was business requirements. The product needed completely new capabilities: map drafts safe publishing high-quality printing multiple workspace modes easier support for new object types Every new feature pushed harder against the existing architecture. Eventually it became obvious: We weren't fighting individual bugs anymore. We were fighting the

2026-07-08 原文 →
AI 资讯

The Next DEV Weekend Challenge Launches on July 9 - 13. Mark Your Calendar!

We're back with another installment of the DEV Weekend Challenge ! If you missed the earlier editions, these are short-form, high-energy challenges designed to fit right into your weekend. We're giving you the heads-up now so you can clear your schedule! How It Works Our challenge prompt will be revealed at launch. Follow #weekendchallenge for updates. You can also keep an eye on the DEV Weekend Challenge page or look out for the official announcement post from the DEV Team . From there, you'll have the entire weekend to build, document, and submit your project. That's all there is to it! Because our community spans every timezone on the planet, we've set the window so that everyone around the world gets at least a full weekend to participate. Important Dates Launch Time: July 10 at 2:00 AM UTC Submissions Due: July 13 at 6:59 AM UTC Here's what that looks like across a few timezones: Timezone Launch Time (Local) Submissions Due (Local) PDT Thursday, Jul 9 at 7:00 PM Sunday, Jul 12 at 11:59 PM EDT Thursday, Jul 9 at 10:00 PM Monday, Jul 13 at 2:59 AM GMT Friday, Jul 10 at 2:00 AM Monday, Jul 13 at 6:59 AM CEST Friday, Jul 10 at 4:00 AM Monday, Jul 13 at 8:59 AM IST Friday, Jul 10 at 7:30 AM Monday, Jul 13 at 12:29 PM JST Friday, Jul 10 at 11:00 AM Monday, Jul 13 at 3:59 PM AEST Friday, Jul 10 at 12:00 PM Monday, Jul 13 at 4:59 PM While the window technically spans more than 48 hours, our goal is to ensure everyone has a full, uninterrupted weekend to work on their project regardless of where they live. What else is happening? Mark your calendars for the upcoming Summer Bug Smash . Bug Smash - Register Now We can't wait to see what you build!

2026-07-07 原文 →
AI 资讯

Isolation Level — Read Committed

Read Committed: snapshot mỗi statement, và vì sao hai SELECT trong cùng transaction có thể trả khác nhau READ COMMITTED là isolation level mặc định của PostgreSQL, và là level mà phần lớn workload OLTP đang chạy mà không biết. Khác với mô hình "transaction lấy một snapshot rồi giữ nguyên" mà nhiều dev tưởng tượng từ MVCC, ở Read Committed mỗi statement lấy một snapshot mới tại thời điểm statement bắt đầu , không phải tại thời điểm BEGIN . Hậu quả thực tế: hai SELECT liên tiếp trong cùng một transaction có thể trả về dữ liệu khác nhau nếu giữa hai lần đó có transaction khác commit. Đây là non-repeatable read — đúng spec của Read Committed, không phải bug — và là nguồn của một class lỗi rất hay gặp: code đọc một giá trị, ra quyết định, rồi cập nhật dựa trên giá trị đã đọc, trong khi giá trị thực tế đã thay đổi. Cơ chế hoạt động Một transaction ở Read Committed không có transaction-level snapshot . Khi mỗi statement (mỗi SELECT , UPDATE , DELETE , INSERT ... SELECT ...) bắt đầu thực thi, backend lấy một snapshot mới gồm xmin , xmax và xip list — chính cái snapshot quyết định row version nào "visible" theo MVCC. Statement chỉ thấy: row có xmin đã commit trước thời điểm statement bắt đầu , và xmax chưa tồn tại hoặc thuộc một transaction chưa commit / đã abort. Ngay sau khi statement kết thúc, snapshot đó bị bỏ. Statement kế tiếp lấy snapshot mới — nếu trong khoảng giữa có transaction khác commit, statement này sẽ thấy dữ liệu mới đó. -- T1 BEGIN ; -- KHÔNG lấy snapshot ở đây SELECT balance FROM accounts WHERE id = 1 ; -- snapshot S1 -> trả 1000 -- ... T2 chạy: UPDATE accounts SET balance=500 WHERE id=1; COMMIT; SELECT balance FROM accounts WHERE id = 1 ; -- snapshot S2 -> trả 500 COMMIT ; Với UPDATE / DELETE / SELECT ... FOR UPDATE / FOR NO KEY UPDATE / FOR SHARE , Read Committed làm thêm một bước đặc biệt mà SELECT thường không làm: nếu target row bị một transaction khác đang lock (chưa commit), statement đợi transaction đó kết thúc. Khi unblock: nếu transaction kia ROL

2026-07-07 原文 →
AI 资讯

How to Use Stream Analyzers for Digital TV Broadcasting: A Practical Guide

Part 1: Solving GOP Structure and Compatibility Issues Operating a digital television network isn't just about keeping channels on air—it's about maintaining quality that viewers expect and troubleshooting issues before they escalate. When something goes wrong in live broadcasting, every second counts. But how do you quickly pinpoint whether the problem lies in encoder settings, transport stream structure, or temporal metadata? This is where specialized stream analysis tools become essential. In this series of articles, we'll walk through real-world scenarios that broadcast engineers face daily and show practical approaches to diagnosing and resolving them. When File Analysis Becomes Critical While live monitoring catches issues as they happen, file-based analysis is your diagnostic microscope. Here's the typical workflow: something breaks in production, engineers capture a few minutes of the problematic stream, and now they need to understand exactly what went wrong. File analyzers serve three primary purposes: Troubleshooting: Identifying the root cause of broadcast issues Encoder optimization: Fine-tuning compression settings Quality control: Validating compliance with standards and specifications Let's explore how this works in practice with actual tools and techniques. The GOP Structure Problem Here's a scenario every broadcast engineer has encountered: legacy set-top boxes or older TV models suddenly can't play your stream. The audio works, video starts and stops, or you see freezing. The culprit? Often, it's the GOP (Group of Pictures) structure. H.264 has been around since 2003—over 20 years. Almost everything supports it, yet you'll still find legacy equipment that struggles with certain configurations. Specifically, the number of B-frames can make or break compatibility. Why B-frames matter: They enable lower bitrates while maintaining quality by increasing encoding complexity through bidirectional prediction. But this comes at a cost—a more complex refere

2026-07-07 原文 →
AI 资讯

How do you balance speed and security in CI/CD?

Modern software development thrives on rapid iteration. Organizations deploy new features, bug fixes, and infrastructure updates multiple times each day to remain competitive and respond quickly to customer needs. Continuous Integration and Continuous Delivery (CI/CD) have transformed software delivery by automating repetitive tasks and accelerating release cycles. However, speed without security creates significant risk. A fast deployment pipeline that introduces vulnerable code into production can expose organizations to data breaches, service disruptions, and compliance violations. Conversely, excessive manual security reviews can slow innovation and delay valuable releases. The solution lies in integrating security directly into the CI/CD pipeline rather than treating it as a separate checkpoint. This philosophy, commonly known as DevSecOps, enables organizations to deliver software rapidly while maintaining a strong security posture. Understanding CI/CD Pipelines What Is Continuous Integration? Continuous Integration (CI) is the practice of frequently merging code changes into a shared repository. Every commit automatically triggers builds and tests, allowing development teams to identify integration issues early instead of waiting until the end of a project. Frequent integration encourages collaboration, reduces merge conflicts, and improves overall software quality. What Is Continuous Delivery? Continuous Delivery extends Continuous Integration by ensuring that validated code is always in a deployable state. Automated testing, packaging, and release preparation make it possible to deploy new versions with minimal manual effort whenever the business is ready. What Is Continuous Deployment? Continuous Deployment goes one step further by automatically releasing approved changes to production once they pass all quality and security checks. This approach significantly shortens release cycles while requiring a high level of confidence in pipeline automation. Benefi

2026-07-07 原文 →
AI 资讯

Signal Forms vs. Reactive Forms: When Should You Upgrade Your Forms? (Angular 22 Guide)

TL;DR — Angular 22 promoted Signal Forms from experimental to stable. This is not "Reactive Forms are dead." It's a real architectural trade-off, and this post walks through both APIs in full, with production-realistic code, so you can decide feature-by-feature instead of framework-war-by-framework-war. Table of Contents Why This Matters Now The Core Question Reactive Forms: Why It Became the Standard Full Example: Reactive Forms Login Where Reactive Forms Still Excel Signal Forms: What Actually Changed in Angular 22 Full Example: Signal Forms Login Where Signal Forms Shine Side-by-Side: Core Concepts Mapped Deep Dive: Validation Synchronous Validation Cross-Field Validation Conditional Validation with when() Async Validation Deep Dive: Dynamic and Nested Forms Nested Form Groups Dynamic Collections (FormArray-style) Deep Dive: Form State — Dirty, Touched, Errors, Submission Developer Experience and Testing Performance Considerations Interop: Migrating Without a Big-Bang Rewrite Migration Strategy for Enterprise Teams When NOT to Migrate Decision Framework FAQ Closing Thoughts Why This Matters Now With Angular 22 (released June 3, 2026), Signal Forms left experimental status and became part of the stable, supported API — alongside resource() and httpResource() . That's a meaningful milestone: it means the Angular team ran extensive internal case studies across real form-heavy applications at Google before committing to stability, and the interop story with Reactive Forms has matured enough that a big-bang rewrite is no longer the only migration path. At the same time, Angular 22 also flips two important defaults: components now use OnPush change detection by default, and zoneless change detection continues its push toward becoming the standard. Signal Forms is part of that same story — Angular's reactivity model finally speaking one dialect end-to-end, from component state to form state to async data. None of this makes Reactive Forms obsolete. It changes what "the

2026-07-07 原文 →
AI 资讯

No createStore, No combineReducers, No Provider — Setting Up State in 3 Lines

Redux setup is a ceremony. You create a store, compose your reducers into a root tree, wrap your app in a Provider, register middleware, and configure enhancers — all before you write a single line of feature logic. SDuX Vault™ replaces that entire ceremony with two function calls and zero root configuration. Redux Store Ceremony A typical Redux application requires several files and configuration steps before state management is operational. Here is what a minimal Redux setup looks like for a single feature: // store.ts import { createStore , combineReducers , applyMiddleware } from ' redux ' ; import thunk from ' redux-thunk ' ; import { userReducer } from ' ./reducers/userReducer ' ; const rootReducer = combineReducers ({ users : userReducer , }); export const store = createStore ( rootReducer , applyMiddleware ( thunk ) ); // App.tsx — Provider wrapper required import { Provider } from ' react-redux ' ; import { store } from ' ./store ' ; function App () { return ( < Provider store = { store } > < UserList /> < /Provider > ); } That is 20+ lines of configuration across multiple files — and it only covers one feature. Add a second feature and you are back in the combineReducers file, composing another slice into the tree. Add middleware and you are threading enhancers through applyMiddleware . Add DevTools and you are composing composeWithDevTools on top. Every new feature touches the root configuration. Redux Requirement What It Does createStore() Creates the single global store instance combineReducers() Composes feature reducers into a root tree applyMiddleware() Registers middleware (thunk, saga, etc.) Provider Makes the store available to all components via context composeWithDevTools() Enables Redux DevTools integration ⚠️ Warning: Every entry in that table is root-level configuration. Adding a new feature means editing the root reducer composition, possibly the middleware stack, and potentially the Provider hierarchy. Root configuration is a shared depende

2026-07-07 原文 →
开发者

Building a SaaS solo, as a Graphic designer

I came into this as a graphic designer, not a software engineer. I didn't have a computer science background, and a lot of what BrandStack needed — authentication, databases, payments, deployment — was new territory for me when I started. What made it possible wasn't some shortcut. It was breaking the problem down into pieces I could actually learn: how user accounts work, how a database should be structured so one person's data never leaks into another's, how to move from test payments to real ones without breaking checkout for actual customers. I made real mistakes along the way. Early on, every user shared the same underlying brand data because I hadn't scoped the database correctly to each account — a serious bug that I only caught by testing with two separate accounts myself. Finding and fixing that taught me more about proper application architecture than any tutorial could have. I don't think being a designer first is a disadvantage for building product. If anything, it means the interface and the experience get real attention, not just the backend logic. But it does mean being honest about what you don't know yet, and being willing to slow down and actually understand a problem instead of copying a fix you don't understand. BrandStack is still a work in progress. But it's a real, working product — built by someone who had to learn most of this from scratch, in public, one bug at a time.

2026-07-07 原文 →
开发者

How to Monitor Website Changes Automatically (Visual Diff Tutorial)

How to Monitor Website Changes Automatically I run a few websites and need to know immediately when something breaks. A CSS regression, a broken layout, a missing section. Manual checking doesn't scale, and text-based monitoring misses visual issues. The {{screenshot-diff}} on Apify takes two screenshots and produces a pixel-level comparison with an overlay showing exactly what changed. How It Works Take a baseline screenshot of the correct state. Then take a current screenshot of the live page. The actor compares pixel by pixel and returns a diff image with changed pixels highlighted, plus a percentage telling you how much changed. import requests , time API_TOKEN = " YOUR_APIFY_TOKEN " def capture_screenshot ( url ): resp = requests . post ( " https://api.apify.com/v2/acts/weeknds~website-screenshot-api/runs " , headers = { " Authorization " : f " Bearer { API_TOKEN } " }, json = { " url " : url , " fullPage " : True } ) run_id = resp . json ()[ " data " ][ " id " ] time . sleep ( 15 ) items = requests . get ( f " https://api.apify.com/v2/acts/weeknds~website-screenshot-api/runs/ { run_id } /dataset/items " , headers = { " Authorization " : f " Bearer { API_TOKEN } " } ). json () return items [ 0 ][ " screenshotUrl " ] def compare_screenshots ( baseline_url , current_url ): resp = requests . post ( " https://api.apify.com/v2/acts/weeknds~screenshot-comparison-tool/runs " , headers = { " Authorization " : f " Bearer { API_TOKEN } " }, json = { " baselineImageUrl " : baseline_url , " currentImageUrl " : current_url , " threshold " : 0.01 } ) run_id = resp . json ()[ " data " ][ " id " ] time . sleep ( 10 ) items = requests . get ( f " https://api.apify.com/v2/acts/weeknds~screenshot-comparison-tool/runs/ { run_id } /dataset/items " , headers = { " Authorization " : f " Bearer { API_TOKEN } " } ). json () return items [ 0 ] baseline = capture_screenshot ( " https://mysite.com " ) current = capture_screenshot ( " https://mysite.com " ) result = compare_screenshots ( b

2026-07-07 原文 →
AI 资讯

How I Built 7 Apify Actors and Started Earning Passive Income from Web Scraping

How I Built 7 Apify Actors and Started Earning Passive Income from Web Scraping A few weeks ago I had zero Apify actors. Now I have seven, all published on the Apify Store, monetized with pay-per-event pricing, and slowly building a passive income stream. Here's exactly how I did it — the strategy, the tech stack, the mistakes, and what I'd do differently. The Strategy: Zero Competition Most new Apify developers go after hot categories. LinkedIn scrapers, Amazon product extractors, Twitter data. Makes sense — those have demand. But they also have dozens of established actors with hundreds of reviews. I took the opposite approach. Find niches with zero existing actors. This means lower total addressable market, but 100% of whatever traffic exists goes to you. No competing on price, no fighting for reviews, no SEO war against actors with years of history. How I found the niches: Browsed Apify Store categories sorted by actor count Searched for common developer pain points with no existing Apify solution Checked search volume for "[keyword] API" and "[keyword] scraper" Verified zero results on Apify Store for each candidate The winners: domain intelligence, screenshot comparison, Swedish company registry, IP geolocation, QR code generation, and link metadata extraction. The Tech Stack Every actor uses the same foundation. Apify Python SDK v3.4 handles input/output, storage, proxy, and deployment. Playwright for JavaScript-heavy sites and screenshots. aiohttp for lightweight API scraping (way faster than a full browser). Pillow for image processing. Deployment is one command: apify push The Actors {{domain-intel}} WHOIS, DNS, SSL, and tech stack in one API call. Uses socket + ssl + python-whois for data collection, no external API dependency. $0.005 per run. {{screenshot-api}} Full-page screenshots via Playwright. Handles lazy-loading, infinite scroll, and viewport sizing. $0.003 per run. {{metadata-extractor}} Open Graph, Twitter Cards, JSON-LD, and meta tags from any

2026-07-07 原文 →
AI 资讯

15 browser-based dev tools I use daily — no login, nothing uploaded

Like most developers, I have a handful of small utilities I reach for every day — formatting JSON, decoding a JWT, generating a UUID, testing a regex. For years I just googled "json formatter" and pasted my data into whatever site came up first. Then one day I caught myself pasting a production JWT into a random online parser that POSTs everything to its server. That felt bad. So I built my own toolbox that never sends data anywhere. It's called WeTool — free, no login, and every tool runs 100% in your browser . You can open DevTools → Network and confirm there are zero requests while you use it. Here are the 15 I use most: Everyday JSON formatter / validator URL encode / decode Base64 encode / decode Timestamp ↔ date converter Security & encoding Hash calculator (MD5 / SHA) JWT parser UUID generator QR code generator Text & format Regex tester Text diff Markdown preview SQL formatter Debugging Cron expression parser Color converter User-agent parser Two things that matter to me and might to you: Nothing is uploaded. No backend, no login, no tracking of what you type. Local-only. 15 languages. Most tool boxes are English-only; this one isn't. It's free and I'm actively adding tools — if something you use daily is missing, tell me in the comments and I'll add it. 👉 wetool.site

2026-07-07 原文 →
AI 资讯

How do you dedupe support tickets that don't share any words? Here's our messy attempt.

We build an internal helpdesk, and I want to talk through a problem we only partly solved — because I suspect a lot of you have hit it too, and I'd genuinely like to hear how you handled it. The most requested thing from our users was never "better ticket forms." It was "please make the duplicates stop." Here's the shape of it. A deploy goes slightly wrong at a 40-person company. Within ten minutes you have: a handful of chat messages : "login is broken", "can't get into dashboard???", "deploy looks weird" several error-tracker events (whatever you run — Sentry, Rollbar, an APM): TokenExpiredError ×2, a 401 spike on /api/auth , a 5xx spike on auth-svc a couple of emails to IT : "access token expired", "need login reset" Nine items across three channels. One root cause: token rotation broke in that deploy. Whoever's on rotation spends the morning proving that, instead of fixing anything. We wanted to automate the recognition step — "these are the same thing" — not the fixing step. This is the honest version: what we tried, the small thing we actually shipped, and the parts we haven't cracked. If you've built something similar, I'd love to be told what we got wrong. Attempt 1: rules and keywords (broke immediately) The obvious first cut: normalize ticket text, match on keywords and categories, merge on high overlap. It fails on the example above, and it fails structurally: "login is broken" and TokenExpiredError share zero tokens. The human on rotation isn't string-matching — they know a deploy just happened, they know what auth-svc does, they've seen this failure shape before. Rules encode none of that. Rule systems also rot. Every incident teaches you a new synonym for "it's down," and six months in you own a regex museum nobody wants to touch. Maybe you've kept one of these healthy long-term — if so I'd honestly like to know how. Attempt 2: embed everything, cluster by similarity (the one we didn't ship) The tempting next move: embed ticket text, cluster on cosine

2026-07-07 原文 →