“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
Elm 1.0 之路:构建速度革命与编译器的深度优化
Elm 语言团队通过重构构建系统、优化编译流程和引入增量编译,实现了从分钟级到秒级的构建速度飞跃,为 1.0 正式版铺平道路。
核心问题:构建速度为何成为瓶颈
Elm 是一门专注于前端开发的纯函数式语言,以其“无运行时错误”的承诺和友好的编译器信息著称。然而,随着项目规模增长,其编译时间逐渐成为开发者社区的痛点。在早期版本中,一个中等规模的 Elm 项目(约 10 万行代码)的完整构建耗时可能超过 2 分钟,而热重载(hot reload)的反馈周期也长达 30 秒以上。这种延迟严重影响了开发体验,尤其是在迭代频繁的 UI 开发场景中。
深度剖析:编译器慢在哪
Elm 团队(核心贡献者 Evan Czaplicki 和社区成员)对编译过程进行了系统性分析,发现三个主要瓶颈:
冗余的类型检查:Elm 采用 Hindley-Milner 类型系统,每次构建时都会对全部模块进行完整的类型推导和统一(unification)。即使只修改了一个文件,所有依赖该模块的代码也会被重新推导,导致大量重复计算。
序列化与反序列化开销:Elm 的构建系统使用 JSON 作为中间表示(IR)的持久化格式。JSON 的解析和生成在大型项目中非常昂贵——解析一个 5MB 的 JSON 文件可能需要 800ms,而反序列化后还需要额外的内存分配。
单线程的编译流水线:早期 Elm 编译器是纯单线程的,所有阶段(词法分析、解析、类型检查、代码生成)串行执行。现代多核 CPU 的并行能力未被利用。
优化策略:从架构到实现的全面重构
1. 增量编译(Incremental Compilation)
这是最核心的改进。Elm 团队引入了基于依赖图的模块缓存系统:
- 细粒度依赖追踪:编译器现在记录每个模块导出的类型签名、值定义和 effect 类型。当源文件变化时,系统只重新编译实际受影响的模块,而不是整个依赖链。
- 哈希校验:每个模块的编译产物(包括类型检查后的中间表示)会与源文件的哈希值绑定。如果哈希未变,直接跳过编译。
- 稳定排序:Elm 的模块系统是无环的(acyclic),这允许编译器按拓扑序处理依赖,确保缓存命中率最大化。
数据对比:在 Elm 0.19 的测试中,修改单个文件后,增量编译的平均时间从 12 秒降至 0.8 秒。
2. 二进制序列化替代 JSON
团队放弃了 JSON 作为中间缓存格式,转而采用自定义的二进制格式:
- 零解析开销:二进制格式可以直接映射到内存中的数据结构(类似 mmap),无需解析步骤。
- 紧凑存储:类型信息、作用域树等复杂结构被编码为固定长度的字节序列,体积减少约 60%。
- 跨版本兼容:二进制格式包含版本号字段,确保不同编译器版本间的缓存兼容性。
3. 并行化编译阶段
虽然 Elm 的纯函数特性天然适合并行,但早期实现并未利用这一点。新架构将编译分为三个阶段:
- 阶段 1(并行):对所有独立模块进行词法分析、解析和类型检查。这些操作无共享状态,可直接分配到多个线程。
- 阶段 2(串行):合并类型信息,生成全局优化决策(如死代码消除)。
- 阶段 3(并行):将优化后的 IR 生成 JavaScript 代码。
实测显示,在 8 核机器上,完整构建时间从 2 分 10 秒降至 35 秒。
4. 内存管理的改进
Elm 编译器使用 OCaml 编写,OCaml 的垃圾回收器(GC)在大型堆上表现不佳。团队通过以下方式优化:
- 对象池(Object Pooling):重用 AST 节点和类型对象,减少 GC 压力。
- 分代 GC 调优:调整 OCaml 的年轻代大小,使短期中间对象更快回收。
- 惰性求值:部分中间表示只在需要时才计算,避免构建整个 AST 树。
工程实践:这些优化如何落地
Elm 团队采用“先测量,后优化”的方法论。他们使用 perf(Linux 性能分析工具)和 ocamlprof(OCaml 性能分析器)定位热点函数。例如,他们发现 unify 函数(类型统一的核心)占用了类型检查阶段 40% 的时间,于是重写了该函数,引入基于并查集(Union-Find)的数据结构,将复杂度从 O(n²) 降至接近 O(n)。
对开发者的影响
这些优化不仅提升了构建速度,还带来了两个额外收益:
- 更好的错误信息:增量编译使得编译器可以保留更多上下文,当类型错误发生时,能够提供更精确的定位和修复建议。
- 更小的产物体积:二进制缓存格式和死代码消除的结合,使得最终生成的 JavaScript 文件平均缩小 15%。
1.0 之路的里程碑
Elm 1.0 的发布不仅意味着 API 稳定,更标志着编译器工程达到了工业级标准。Evan Czaplicki 在公告中强调:“构建速度是 Elm 1.0 最重要的非功能性需求。我们不想让开发者等待,而是希望他们专注于创造。”
截至 2025 年,Elm 的构建系统已成为函数式语言编译器的参考实现之一,其增量编译策略被 Rust 的 cargo 和 Haskell 的 ghc 社区部分借鉴。