惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Y
Y Combinator Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
L
LangChain Blog
美团技术团队
N
Netflix TechBlog - Medium
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog
博客园 - 司徒正美
爱范儿
爱范儿
D
DataBreaches.Net
月光博客
月光博客
U
Unit 42
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
腾讯CDC

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
97% of My App's Code Is in commonMain — A Field Report on...
wang jack · 2026-06-18 · via DEV Community

I shipped a small dev-news reader to Google Play with the entire client written
in one Compose Multiplatform codebase
— every screen in commonMain, no
per-platform UI. This is an honest field report on what that actually costs in
production: the numbers, the native seams, and the parts that still hurt (hi,
iOS). The repo is open source (MIT), so everything here is checkable.

TL;DR — For a content/list/detail app, CMP is comfortably production-ready
on Android. 96.9% of the shared module is commonMain; the native cost is
concentrated in ~10 expect/actual seams. iOS compiles and renders, but isn't
polished yet.

The numbers

Source set Files Lines Share
commonMain 59 ~7,700 96.9%
androidMain 2 123 1.6%
iosMain 3 127 1.6%

All 17 screens live in commonMain — trending list, aggregated feed, README
detail, profile with paging, settings, favorites — and there isn't a single
if (isAndroid) branch in the UI.

The 3% that isn't shared

The native cost isn't spread thinly across the codebase. It's concentrated in
~10 expect/actual seams, and this is the entire list:

  • Platform info — app version, system language, User-Agent string
  • System interaction — open URL, open app settings, share sheet
  • Analytics — a trackEvent hook (Android → Aptabase; iOS is deliberately a no-op for now)
  • WebView — the messy one (below)

Everything that touches a platform API is small and enumerable. Everything else
came for free.

Why expect/actual and not an interface + DI?

For these ~10 seams, expect/actual was the least ceremony: no DI wiring, and
the compiler refuses to build until every target implements the declaration. The
moment a seam has more than one implementation, or I'd want to fake it in tests,
an interface in commonMain with injected impls is the better tool. For a fixed
set of platform primitives, expect/actual wins on friction.

The ugliest boundary: WebView

I have two WebView paths, and I'll be precise because the repo is open:

  1. Rendering GitHub READMEs from an HTML string — inline expect/actual over android.webkit.WebView / WKWebView, JS disabled, theming done by injecting CSS colors so light/dark stays consistent. ~30–50 lines per side.
  2. Opening external links in-app — this one I pulled into a standalone library, kmp-webview, because the lifecycle/config surface (file chooser, media capture, title handling) got hairy enough to deserve its own home.

WebView is hands-down the least elegant part of the codebase. If you've wrapped
WKWebView / Android WebView behind a common composable, I'd genuinely welcome
a sanity check on the library's API.

Honest status: iOS is WIP

Android is live on Google Play. iOS compiles and every Compose screen renders in
the simulator — but it isn't polished:

  • iPad share crashes without a popoverPresentationController anchor (there's a literal TODO)
  • iOS has no analytics wired
  • the AI-chat screen is Android-only right now

Not vaporware, just not shipped. And honestly, iOS is where the KMP tax
actually shows up
— not in the shared code, but in the toolchain around it:
living with Xcode for the shell, slower clean builds when the iOS target is in
the loop, and fewer battle-tested libraries. The Kotlin/Compose side is smooth;
the iOS edge is where I spend my "fighting the tools" time.

Stack

Kotlin 2.3.21 · Compose Multiplatform 1.11.1 · Ktor 3.5.0 · Coil 3 ·
multiplatform-settings · Material 3. Navigation is a small stack-based setup in
commonMain (data objects/classes as route keys), no platform-specific nav.

Takeaways

  • For a content/list/detail app, shared-UI CMP pays off on Android. Write 17 screens once, not twice.
  • The native tax is small and predictable. It lives at ~10 expect/actual seams — anything that wraps a platform view or calls a platform API.
  • The pain is exactly where you'd guess: WebView, and the iOS toolchain.
  • expect/actual for fixed platform primitives; interfaces for anything you'd test or swap.
  • Be honest about iOS. Compiling and rendering in a simulator is not the same as shipping.

The app is a GitHub Trending / Hacker News / Product Hunt reader, if you want
context on the screens. Repo (MIT): https://github.com/HarlonWang/TrendingAI
and the WebView lib: https://github.com/HarlonWang/kmp-webview.

What's your experience taking CMP to production, especially on iOS? I'd love to
compare notes in the comments.