许可证选择:四个问题、214 个直接依赖与 12 个 copyleft

选许可证不是选立场,是回答四个问题:谁要改、改完是否闭源、服务端算不算分发、被大公司拿走怕不怕。本文用一张四问表、214 个直接依赖与 12 个 copyleft 的清单,给出一个人能长期维护的选法,并比较四种许可证的取舍差异。

许可证不是道德声明,是一份你签了字、却永远不会在场解释的合同。

一、一次法务邮件与一张依赖清单

2026 年 5 月,一家做在线教育的公司给许砚发邮件,问 syncwell 能不能提供「不带 AGPL 义务」的版本。对方不是要找麻烦,他们的法务只是在走一次标准流程:把要集成进产品的开源组件列出来,逐个确认许可证。这封邮件让许砚第一次认真对待仓库根目录那个 1.1 KB 的 LICENSE 文件。

他后来复盘,这件事真正的触发点不是法务邮件,而是「对方比你先读完你自己的许可证」。一家公司愿意花时间确认义务,说明它真的想用;这种信号比 star 有用,也比下载量具体。

以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。

他做了一件本该在第一年就做的事:把依赖树导出,逐条读许可证。结果有 214 个直接依赖,其中 197 个是宽松许可(MIT、Apache-2.0、BSD、ISC),12 个是 copyleft(GPL、LGPL、MPL),5 个的许可证字段为空或写的是「见仓库」。比例是 92.1%、5.6% 与 2.3%。

大多数人不是选错许可证,是从来没看过依赖的许可证。 自己那一个文件写得再漂亮,只要有 12 个 copyleft 混进发布包,实际义务就由它们决定。

还有一个常被忽略的来源:复制粘贴。项目早期的几个工具函数是从一个 GPL 项目里改的,没有保留头注释;这类代码在依赖清单里查不到,只能靠提交历史回溯。他把 2024 年之前的 300 次提交扫了一遍。

这份清单还暴露了一个更基础的问题:214 个依赖里,有 38 个只在开发或测试时使用,不进最终分发。把它们单独标出来后,真正随产物分发的依赖是 176 个,copyleft 只剩 5 个。许可证合规的第一步不是选,而是先分清「分发」与「不分发」。

「分发」的判定也不总是清晰。把二进制发到 GitHub Releases 是分发;把源码放在仓库里让人 clone,通常也算分发;让用户在你的服务器上调用,多数许可证不算分发,AGPL 例外。三种形态对应三种义务,混着算就会多背或少背。

二、四个问题决定你该用哪一种

许可证的选择可以压缩成四个问题。它们不问「你支持开源吗」,只问「你的产物会被谁、以什么方式使用」。四个问题答完,答案通常只剩一个。

问题答「是」的后果对应倾向
会不会有人把它嵌进闭源产品?强 copyleft 会挡住这类采用MIT / Apache-2.0
你介不介意别人改完闭源?不介意选宽松;介意选 copyleftMIT / MPL / AGPL
服务端使用算不算分发?算,选 AGPL;不算,GPL 管不到AGPL-3.0
怕不怕云厂商直接拿去卖?怕,用 BSL 或 Open CoreBSL / 部分闭源

四个问题的顺序不能换。先答第一个,是因为它决定了你的采用面;再答第二个,是因为它决定了你要不要保留回馈义务;第三个问题只对「有服务端」的项目有意义;第四个问题只有在项目已经足够大、值得被云厂商盯上时才成立。

四个问题里,只有第一个会真正改变你的用户结构。选了强 copyleft,等于主动放弃一部分「想嵌进闭源产品」的采用;选了宽松许可,等于接受「别人改完可以不开源」。后三个问题都是在第一个答案的基础上做微调。

MIT 与 Apache-2.0 的差别常被低估。MIT 最短,几乎不设条件;Apache-2.0 多了专利授权、商标声明与 NOTICE 要求。如果你做的是一把会被企业集成的库,Apache-2.0 的专利条款能省掉法务一半的问题;如果你做的是一个希望被复制、被改造的小工具,MIT 的摩擦力最低。

一个常见的折中是「核心用 Apache-2.0,示例与模板用 CC0」。前者保证专利与归属,后者让复制粘贴没有心理负担;两类文件放在不同目录,各带一个 LICENSE,比整仓一个许可更清楚。

MPL-2.0 是文件级的 copyleft:改了哪个文件,就开源哪个文件,其他文件可以是闭源的。它对「想保留一点回馈、又不想吓跑商业用户」的项目最友好。AGPL-3.0 把「通过网络提供服务」也算作分发,这是它唯一但决定性的区别。

BSL 不是 OSI 认可的开源许可证,它限制生产用途、通常带一个几年后的转换期。它解决的是「云厂商拿去卖」的问题,代价是失去「开源」这个标签以及一部分社区信任。用它之前,先确认你真的到了需要它的规模。

还有一个现实约束:BSL 的项目通常收不到企业赞助。赞助方大多希望支持「真正的开源」,而不是「限制商用的源码可见项目」;这不是道德判断,是预算科目的区别。改协议之前,先想清楚你失去的是哪一类钱。

三、214 个依赖里的 12 个 copyleft

把 12 个 copyleft 按类型拆开,处理方式并不相同。数量最多的是 LGPL,它允许动态链接、不要求你的代码开源;最容易踩坑的是 GPL,它要求衍生作品整体以同许可发布。

许可证数量占比处理方式
GPL-3.041.9%仅测试工具,不随产物分发
LGPL-3.052.3%动态链接,提供替换方式
MPL-2.031.4%文件级隔离,未修改原文件
合计125.6%5 个进入分发,7 个只用于开发

四个 GPL-3.0 依赖里,有三个是测试框架的插件,一个是构建脚本里的压缩工具。它们只在 CI 里运行,不进入发布包,所以不构成分发。真正需要处理的是另外五个:LGPL 的动态链接要保证用户能替换库文件,MPL 的三个文件要保留原样、改动放在新文件里。

许可证不明的那 5 个更麻烦。它们不是「没有许可证」,而是「仓库里没有 LICENSE 文件」。在法律上,没有许可证意味着保留所有权利,即使代码公开可读也不能直接分发。处理方式只有三条:找到上游确认、换成有明确许可的替代品、或者从分发中移除。许砚最后换掉了 3 个,保留了 2 个只在本地开发时使用的。

换依赖的成本常被高估。那 3 个被换掉的包,替代品的 API 相似度在 80% 以上,改动集中在两个文件、约 140 行;真正花时间的是回归测试,不是替换本身。相比之下,为一个许可不明的包写法律意见的成本更高。

依赖合规不是一次性任务,是一条会随每次 npm install 变化的流水线。 214 这个数字在下个月就会变;如果不把许可证检查放进 CI,半年后你会面对一份没人读得懂的清单。

扫描工具的输出要收敛。默认报告会列出所有依赖的所有许可证,信息量太大;实际有用的是三行:新增的 copyleft、新增的不明许可、以及许可证发生变化的依赖。只盯这三行,一个人也能维护。

一个可执行的做法是:在 CI 里跑一次许可证扫描,把结果按「随产物分发」与「仅开发」两栏输出;对 copyleft 与不明许可单独报错,其余只记录。这样每次新增依赖都会在合并前暴露,而不是在客户法务发邮件时暴露。

四、Apache-2.0 的三件小事与一次复算

如果最终选 Apache-2.0,有三件小事必须做,它们不影响收入,但影响别人敢不敢用。

第一是 NOTICE 文件。Apache-2.0 要求分发时保留 NOTICE 里的归属声明;如果你的项目包含别人的 Apache-2.0 代码,要把它们的 NOTICE 合并进来。第二是商标。许可证给的是版权与专利授权,不包括商标;项目名与 logo 不能随代码一起被自由使用。第三是贡献者许可。如果不要求 CLA,至少要在 CONTRIBUTING.md 里写清「提交即表示同意以本项目许可证发布」。

商标这件事最容易被忽略,因为它不在许可证文本里。许可证给的是版权与专利授权,项目名、logo、域名都不在其中;fork 可以继续用代码,不能继续用名字。写一句「名称与 logo 不随许可证授权」,能省掉未来的一次投诉。

这三件事的成本都很低:NOTICE 一小时、商标声明半小时、贡献者声明两小时。它们的共同点是「现在不做,以后做的成本会随 star 增长」;4,200 个 star 时补一份 CLA,比 400 个 star 时难十倍。

这三件事对应三种常见事故:NOTICE 丢了被下游投诉、项目名被 fork 拿去商用、贡献者事后反悔要求撤回代码。三件都不难做,难的是在项目有 4,200 个 star 之前做。

如果项目已经有外部贡献,CLA 的补签会很麻烦。可行的折中是 DCO:不签协议,只在提交信息里加一行「Signed-off-by」,表示同意以项目许可证发布。它的保护弱于 CLA,但迁移成本低,适合个人项目。

复算:
直接依赖:214
宽松(MIT/Apache-2.0/BSD/ISC):197 → 197 ÷ 214 = 92.1%
copyleft:12 → 12 ÷ 214 = 5.6%
  其中 GPL-3.0 4(1.9%)、LGPL-3.0 5(2.3%)、MPL-2.0 3(1.4%)
许可不明:5 → 5 ÷ 214 = 2.3%
随产物分发:176(214 − 38 个仅开发/测试)
分发中的 copyleft:5 → 5 ÷ 176 = 2.8%
处理:4 个 GPL 仅测试 + 3 个不明替换 + 2 个不明仅本地 = 9 个不进入分发
复核:197 + 12 + 5 = 214;4 + 5 + 3 = 12;92.1% + 5.6% + 2.3% = 100.0%

复算里最容易被忽略的是 176 这个分母。用 214 算「分发中的 copyleft 占比」会得到 5.6%,用 176 算会得到 2.8%;前者是仓库的真实负担,后者是用户的真实风险。两个数都要留,回答不同的问题。

还有一个口径是「传递依赖」。214 个直接依赖背后还有 900 多个传递依赖;它们不写在 package.json 里,但会进入产物。用直接依赖的清单去回答安全问题,会漏掉一大半;用传递依赖去回答许可证问题,又会淹没在噪声里。

五、行动清单与复算验收

  • 导出完整依赖树,标出每个依赖的许可证标识符。
  • 把依赖分成「随产物分发」与「仅开发/测试」两栏,分别计数。
  • 单独列出 copyleft 与许可证不明的依赖,逐个写出处理方式。
  • 用四个问题各答一次,写下最终选定的许可证与理由。
  • 确认根目录有 LICENSE,内容与 SPDX 标识符一致。
  • 若有 Apache-2.0 代码,补齐 NOTICE 与贡献者声明。
  • 把许可证扫描加进 CI,对 copyleft 与不明许可设成失败。
  • 在 README 里写明商标不随许可证授权。

验收标准:任取一个发布包,都能列出其中每个依赖的许可证,并说清 copyleft 的那几个为什么可以这样分发。

前四条是「先看清」,后四条是「再固定」。如果只有一小时,先做第二条:不分「分发」与「不分发」,后面所有判断都会算错分母。

清单里最容易被跳过的是第七条。人工清单只能反映导出那天的状态,CI 检查才能反映下一次合并之后的状态;开源项目的依赖是活的,合规也必须是活的。

使用边界与实操验收

本文不是法律意见。 许可证的解释、衍生作品的判定、跨境司法的适用,都以正式文本与专业顾问为准。本文只处理「一个人怎么把许可证选清楚、把依赖看清」。

四个问题不是决策树。 它们给的是倾向,不是判决。同一个项目在不同阶段可以换许可证,但换的代价见第 9 篇:一次变更会带来 fork、star 波动与客户询问。

12 个 copyleft 是样本。 换成前端项目,这个数字通常更高;换成纯 Go 或 Rust 的 CLI,通常更低。比例不重要,清单本身才重要。

「不明许可」不等于「可以随便用」。 没有 LICENSE 的仓库默认保留所有权利,公开可读不等于可以分发。处理它的成本通常高于换一个替代品。

不要用许可证表达价值观。 许可证是一份给下游法务看的合同;用它表达「我反对某类公司」,通常既挡不住对方,也吓退了正常用户。

关键参考与核验范围

以上链接于 2026-10-26 实测可公开访问;未核验版本、功能范围与政策更新。核验日期:2026-10-26。

范围上只讨论个人开源项目的许可证选型与依赖合规,不讨论诉讼、专利布局、跨境许可与商业合同的具体条款。

系列导航

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「Indie」更多文章

  1. 开源项目验收:十项能力、四维评分与三种不该开源的项目
  2. 治理、fork 与退出:17 位贡献者、82% 的提交与一次改协议的代价
  3. 双许可与企业版:九家询价、两家成交与 4,800 美元