实现一个更先进的 css module 开发工具
截止目前,css module 仍被大多数开发者所使用,几乎零上手成本的使用方式收到大多数开发者的青睐。至今已经有与之匹配的生态和工具,本次所推荐的工具,能提供给 css module 开发者们更丝滑,更优雅的开发体验(免费)。
简介
工具形式为 vscode 插件,可在插件市场搜索 css-module-typed 安装使用
动机
vscode插件市场已经有了很多css module相关的插件,但是用起来总有一种差强人意的感觉,并不能完全满足我们的使用需求,例如:
- 需要生成生成d.ts文件,对项目侵入性极大;
- 不支持goToDefinition,鼠标hover 类名的时候只能看见类型,但是并不能跳转到对应的样式代码位置;
- CSS Modules created by clinyong 插件虽然支持goToDefinition,但是也只支持了部分,例如: &.class {} 这种写法就不再被支持;
功能
基于上述动机,我们在新的插件中实现了以下功能:
- 代码自动补全
- Go to definition
- less/scss 缩写后的类名识别
- 不需要生成 d.ts 文件,保持磁盘干净整洁
- 自动标记不存在的 class name
demo 演示
功能演示:
类名不存在时,提示更符合开发的心智模型:
安装
方式1:vscode 插件市场搜索 css-module-typed,install 后,重启即可
方式2:访问 marketplace.visualstudio.com/items?itemN… ,点击 install 即可
原理
增强 typescript 语言服务
由于 typescript 语言服务并不能识别 css module 文件(后缀为 .css/.scss/.sass/.less )。
因此我们实现 typescript 语言服务器插件,从 css module 文件识别为 ts 文件
// 欺骗 typescript 语言服务器
languageServiceHost.getScriptKind = (fileName) => {
if (!info.languageServiceHost.getScriptKind) {
return ts.ScriptKind.Unknown;
}
if (isCSS(fileName)) {
return ts.ScriptKind.TS;
}
return info.languageServiceHost.getScriptKind(fileName);
};
同时当 typescript 语言服务器请求读取 css module 类型时,编译 css module 文件为 d.ts 格式的内容并返回。
// 提供编译后的 d.ts 内容
languageServiceHost.getScriptSnapshot = (fileName) => {
if (isCSS(fileName)) {
const snapshot = getDtsSnapshot(
ts,
processor,
fileName,
options,
logger,
compilerOptions,
directory,
);
return snapshot;
}
return info.languageServiceHost.getScriptSnapshot(fileName);
};
核心库改造
实际上,上述【增强 typescript 语言服务】实现在社区已经有对应实现 typescript-plugin-css-module ,但插件仍有许多未解决的问题。因此,我们针对核心库 typescript-plugin-css-module 进行了部分改造,包括:
- 解决大型项目的性能瓶颈
- 支持标记错误类名为"废弃"
- vscode 插件支持
- 更精确的 goToDefinition
更详细的原理可以看这里:vscode 如何支持 css-module 文件跳转到类名?
vscode 插件支持
幸运的是,vscode 允许插件提供 typescript 插件 ,在 package.json - contributes 中定义插件库即可
{
"contributes": {
"typescriptServerPlugins": [
{
"name": "typescript-styled-plugin"
}
]
}
}
typescript 插件的自定义配置将由 vscode 插件进行传递,由于一些时序问题,插件放弃了使用官方提供的 configurePlugin 方式注入 typescript 配置,而是在 vscode 插件被激活时,写入临时文件配置,让 typescrip 插件能更早的拿到用户自定义配置
总结
相比于使用 typescript-plugin-css-module,使用 vscode 插件的形式给项目的 css module 文件添加类型声明可以真正降低代码的侵入性,并且不需要再为每个项目都做一遍插件的安装和配置,有效地降低了工具的使用成本。
相比于社区类似的插件 Css Modules ,除了增强了【代码自动补全】和【goToDefinition】之外,还提供了【错误 className 标记】和【less/scss 缩写支持】,从 typescript 语言层面出发,满足更多的开发场景,给予更友好的开发体验。