“写笔记”支持四种格式——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)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
Webpack v5.108.4 发布,模块打包器
Webpack 又发新版本了,这次是 v5.108.4。虽然是个 patch 版本,但仔细翻了下 changelog,发现这次改动的点还挺有意思的,尤其如果你在用 experiments.css 或者自定义 resolve 插件的话,值得仔细看看。
我自己平时用 Webpack 做项目打包,很少会追着每个小版本更新,但这次有几个修复涉及到了 CSS 模块解析和路径处理,属于那种“不知道的时候看起来一切正常,知道了之后才发现之前踩过坑”的类型。所以我觉得有必要把这几个改动掰开揉碎讲清楚。
这次改了啥?一个概括
先列个清单,方便你快速了解:
- 修复
experiments.css在 resolve 钩子中的context参数传递问题
当 CSS 文件里通过@import或url()引用其他文件时,resolve插件拿到的context有时候是错的,导致解析路径不对。 - 修复
resolve.byDependency配置中byDependency类型定义缺失
TypeScript 用户会报类型错误,这个版本补上了类型声明。 - 修复
harmony-import-local在循环依赖场景下的处理
循环引用 + ES Module 本地导入时可能出现模块初始化顺序问题,这个修复让 Webpack 能更安全地处理这种情况。
下面我一个一个展开说。
1. experiments.css 的 resolve context 修复
背景:为什么这个参数这么重要?
Webpack 的 resolve 阶段,本质上就是“根据一个路径字符串,找到真正的文件”。比如你在 JS 里写 import './style.css',Webpack 会调用 resolve 逻辑,把 ./style.css 解析成磁盘上的绝对路径。
这个过程中,有一个参数叫 context,它表示“当前解析的起始目录”。比如:
- 如果
./style.css是在/src/pages/home.js里被引用的,那么context应该是/src/pages/。 - 如果
./style.css是在/src/styles/main.css里通过@import './components/button.css'引用的,那么context应该是/src/styles/。
你可能会觉得:“这有啥好纠结的,谁引用谁就是 context 呗。” 但问题在于,当 experiments.css 开启后,Webpack 内部处理 CSS 的方式和 JS 不一样——CSS 文件里的 @import 和 url() 是由 CSS 解析器处理的,它会把引用信息传给 resolve 钩子,但之前版本里,这个传递过程丢失了正确的 context。
具体 bug 表现
假设你有这样的结构:
/src/
styles/
main.css /* @import './components/button.css' */
components/
button.css
pages/
home.css /* @import '../styles/main.css' */
在 webpack.config.js 里,你写了一个自定义 resolve 插件,想根据 context 做点事情,比如:
class MyResolvePlugin {
apply(resolver) {
resolver.getHook('resolve').tapAsync('MyResolvePlugin', (request, resolveContext, callback) => {
console.log('context:', request.context);
callback();
});
}
}
在 v5.108.3 及之前,当 Webpack 解析 home.css 中的 @import '../styles/main.css' 时,request.context 可能是正确的(因为 JS 模块解析那一套逻辑还算成熟)。但继续解析 main.css 中的 @import './components/button.css' 时,request.context 可能就变成了 /src/pages/ 而不是 /src/styles/——因为 Webpack 内部在传递 context 时,没有正确更新为 CSS 文件所在的目录。
这就导致你的 resolve 插件拿到的 context 是错的,进而解析出错误的路径,甚至找不到文件。
这次怎么修的?
Webpack 团队在解析 CSS 的 @import 和 url() 时,显式地将当前 CSS 文件所在的目录设置为 resolve 的 context。具体的代码改动在 lib/css/CssParser.js 和 lib/css/CssModulesPlugin.js 里,核心就是:
// 修复前:直接复用上层 context
resolveContext = parentContext;
// 修复后:使用当前 CSS 文件所在目录作为 context
resolveContext = path.dirname(cssFileAbsolutePath);
这个改动看起来很小,但如果你写过自定义 resolve 插件,或者用过 enhanced-resolve 的 alias、modules 配置,你就知道 context 一错,整个解析链就乱了。
对你有什么影响?
- 如果你没用
experiments.css(还是用css-loader+style-loader那种传统方式),这次修复对你无影响。 - 如果你在用
experiments.css,并且没有自定义 resolve 插件,那大概率也不会触发这个 bug,因为内置解析器在大多数场景下能正常工作。 - 但如果你写了自定义 resolve 插件,并且依赖
request.context来做路径映射(比如动态替换某些模块路径),那这个修复很可能解决你之前遇到的“某些 CSS 引用解析不对”的问题。
2. resolve.byDependency 类型定义修复
背景:TypeScript 用户的痛点
Webpack 5 引入了一个很实用的配置项:resolve.byDependency。它允许你根据模块的依赖类型(dependency type)来使用不同的解析规则。比如:
// webpack.config.js
module.exports = {
resolve: {
byDependency: {
// 对于 ES Module 导入,使用这些解析规则
esm: {
extensions: ['.mjs', '.js', '.json'],
},
// 对于 CommonJS 导入,使用不同的解析规则
commonjs: {
extensions: ['.js', '.json'],
},
// 对于 CSS 中的 @import,使用这些规则
'css-import': {
extensions: ['.css'],
},
},
},
};
这个功能在大型 monorepo 里特别有用,因为你可以让 JS 模块和 CSS 模块走不同的解析路径,避免冲突。
bug 在哪?
在 v5.108.3 及之前,Webpack 的 TypeScript 类型定义里,resolve.byDependency 的类型被定义为:
byDependency?: Record<string, ResolveOptions>;
但 ResolveOptions 本身是一个复杂的类型,包含了 alias、extensions、modules 等字段。问题是,当你在 byDependency 里配置某个依赖类型时,Webpack 内部只允许你覆盖部分字段(比如 extensions),而不是全部。但类型定义并没有反映这个限制,导致开发者可能写了一些实际上不会被使用的配置,TypeScript 也不报错。
更严重的是,有些开发者发现 TypeScript 报错说 byDependency 不存在,因为类型定义里根本没有这个字段(在某些版本中确实漏掉了)。
这次怎么修的?
Webpack 团队在 lib/WebpackOptionsDefaulter.js 和对应的 .d.ts 文件中补全了 byDependency 的类型声明,并且修正了子类型的结构,让 TypeScript 能够正确提示可用的字段。
具体改动可以参考这个 commit:
fix: add byDependency type to ResolveOptions(实际 commit hash 可以查 changelog)
对你有什么影响?
- 如果你用的是 JavaScript(没有 TypeScript),这个修复对你无感。
- 如果你用 TypeScript 写 Webpack 配置,并且用到了
resolve.byDependency,那升级后 TypeScript 不会再报类型错误,而且编辑器提示会更准确。 - 如果你还没用过
byDependency,可以试试看,尤其当你需要区分 CSS 和 JS 的解析规则时,这个配置比写多个oneOf要干净得多。
3. harmony-import-local 循环依赖修复
背景:ES Module 循环依赖有多坑?
ES Module 的循环依赖是一个经典问题。Webpack 内部用 harmony-import-local 这个内部标识来处理“本地导入的 ES 模块”。所谓“本地导入”,指的是像 import { foo } from './bar' 这种相对路径或绝对路径导入,而不是从 node_modules 导入。
当两个模块互相引用时:
// a.js
import { b } from './b';
export const a = 'a';
// b.js
import { a } from './a';
export const b = 'b';
Webpack 需要保证模块的初始化顺序正确。在 ES Module 里,import 声明会被提升到模块顶部,但实际执行时,模块的初始化是惰性的:当你 import { b } from './b' 时,Webpack 会先执行 b.js 的顶层代码,如果 b.js 又反过来 import { a } from './a',而此时 a.js 还没执行完,那么 a 的值就是 undefined(因为 export const a = 'a' 还没执行)。
Webpack 通过“占位符”和“运行时检查”来处理这种情况:它会先创建一个未初始化的模块记录,等依赖模块执行完后,再填充实际值。但如果循环依赖链条特别复杂,或者涉及到 harmony-import-local 的特殊处理,就可能出现“模块已经初始化,但导出值还没赋值”的情况。
具体 bug 表现
这个 bug 比较隐蔽,通常出现在以下场景:
- 你有三个或更多模块形成循环依赖。
- 其中某个模块使用了
export { something } from './other'这种重导出语法。 - 重导出的模块恰好是本地模块(
harmony-import-local)。
比如:
// a.js
export { value } from './c';
// b.js
import { value } from './a';
export const b = value + ' from b';
// c.js
import { b } from './b';
export const value = 'c';
在这个例子中,a.js 重导出 c.js 的 value,b.js 导入 a.js 的 value,c.js 又导入 b.js 的 b。这是一个典型的三角循环依赖。
在 v5.108.3 及之前,Webpack 在处理 a.js 的 export { value } from './c' 时,会先解析 c.js,而 c.js 又需要 b.js,b.js 又需要 a.js…… 最终导致 value 在 b.js 里被解析为 undefined,或者直接抛出 Cannot access before initialization 错误。
这次怎么修的?
Webpack 团队在 lib/dependencies/HarmonyImportLocalDependency.js 里修改了依赖处理逻辑,当检测到循环依赖时,不再立即尝试解析所有导出,而是先返回一个“占位符”,等所有模块都完成初始化后,再统一进行值的绑定。这样确保了在循环依赖中,每个模块的导出都能正确获取到最终值。
核心代码改动类似:
// 修复前:立即解析导出
const exports = moduleGraph.getExports(dependency);
// 修复后:先检查是否处于循环依赖中,如果是则延迟绑定
if (isCyclic(module, dependency)) {
dependency.setLazyBinding(true);
}
对你有什么影响?
- 如果你项目里没有循环依赖,或者循环依赖只涉及
node_modules里的包(比如 lodash 内部),那这个修复对你无影响。 - 如果你项目里有多个本地模块形成循环依赖,并且你遇到过“变量为 undefined”的诡异 bug,那升级后很可能就修好了。
- 建议检查一下你的
import语句,尽量避免循环依赖,虽然 Webpack 能处理,但循环依赖终究是设计上的坏味道。
升级建议
这次升级是 patch 版本,理论上完全向后兼容。如果你已经在用 Webpack 5,可以直接:
npm install webpack@5.108.4 --save-dev
# 或者
yarn add webpack@5.108.4 --dev
升级后建议做两件事:
- 跑一遍你的测试用例,尤其是涉及 CSS 解析和循环依赖的模块。
- 如果你之前因为
byDependency类型报错而写了// @ts-ignore,现在可以去掉看看。
另外,如果你还没启用 experiments.css,可以趁这个机会试试。Webpack 5 原生 CSS 支持已经比较成熟了,不再需要 css-loader 和 style-loader,配置简化不少:
// webpack.config.js
module.exports = {
experiments: {
css: true,
},
};
但注意,experiments.css 目前还不支持 CSS 模块(*.module.css),如果你需要 CSS Modules,还是得用 css-loader。
总结
v5.108.4 虽然是个小版本,但三个修复都挺实在的:
- resolve context 修复:让
experiments.css在自定义 resolve 插件下表现正确。 - 类型定义修复:TypeScript 用户不再被烦人的类型错误困扰。
- 循环依赖修复:让 ES Module 循环依赖场景下变量初始化更可靠。
如果你遇到过我上面描述的那些问题,升级就对了。如果没有,也可以升,毕竟 patch 版本的风险极低,而且说不定哪天你就踩到这些坑了。
最后,Webpack 的 changelog 写得挺详细的,如果你想看每个 commit 的具体改动,可以翻翻 GitHub 上的发布记录:
https://github.com/webpack/webpack/releases/tag/v5.108.4
好了,这次就聊到这儿。如果你升级后遇到了什么奇怪的问题,欢迎留言交流。