@emotion/eslint-plugin 演进全解析:从 10.0.14 到 11.12.0 的规则迭代与 Emotion 迁移实践
【免费下载链接】emotion👩🎤 CSS-in-JS library designed for high performance style composition项目地址: https://gitcode.com/gh_mirrors/em/emotion
本篇技术指南以@emotion/eslint-plugin的 CHANGELOG 为主线,系统梳理该 ESLint 插件从 10.0.14 到 11.12.0 的关键演进:ESLint 版本兼容策略、TypeScript 源码迁移、@jsxImportSource自动注入、空cssprop 崩溃修复,以及围绕 Emotion 10/11 迁移的规则体系。读者读完本文,将掌握该插件的全部规则能力与配置方法,并能结合源码理解每条规则的实际判定逻辑。
一、插件定位:为 Emotion 而生的 ESLint 规则集
@emotion/eslint-plugin是 Emotion 官方维护的 ESLint 插件(仓库位于packages/eslint-plugin/),其核心职责有两类:
- 强制最佳实践:保证
cssprop 依赖的jsx已正确导入、限制样式书写风格(字符串或对象二选一); - 提供 codemod 能力:帮助用户从 Emotion 10 平滑迁移到 Emotion 11,甚至自动改写旧版包名导入。
在 README.md 中明确给出了安装与启用方式:
npm i eslint --save-dev npm install @emotion/eslint-plugin --save-dev注意:如果 ESLint 是全局安装(
-g),则@emotion/eslint-plugin也必须全局安装,否则 ESLint 无法加载插件。
启用时只需在.eslintrc的plugins段填入@emotion(可省略/eslint-plugin后缀),随后在rules段按需开启规则:
{ "plugins": ["@emotion"], "rules": { "@emotion/jsx-import": "error" } }从src/utils.ts的源码可以看到,所有规则都通过@typescript-eslint/utils提供的ESLintUtils.RuleCreator创建,规则元信息中的文档链接会自动指向仓库内docs/rules/${ruleName}.md,保证每条规则都有配套文档可查。
二、版本演进时间线:从 CHANGELOG 看迭代脉络
CHANGELOG 记录了从 10.0.14 到 11.12.0 的全部关键变更,按时间线拆解如下。
11.12.0:TypeScript 迁移与空 css prop 修复(最新版本)
这是 CHANGELOG 中最新的一个版本,包含一个 Minor 和两个 Patch 变更:
- 源码迁移到 TypeScript(PR #2568):插件源码由 JavaScript 迁移至 TypeScript,此后类型声明文件(
.d.ts)由 TypeScript 编译器自动生成,取代了此前手写的类型声明。这一点可以在当前仓库结构中得到印证——packages/eslint-plugin/src/下的全部规则文件均为.ts后缀。 - 空
cssprop 崩溃修复:<div css />这种空属性的写法,此前会导致@emotion/syntax-preference规则崩溃,现在会正常抛出一个错误而非崩溃。 @emotion/jsx-import规则崩溃修复:同样的空cssprop 场景,在jsx-import规则中也曾触发崩溃,本版本一并修复。
结合 syntax-preference.ts 源码可以看到,两条规则都针对JSXAttribute中的css属性做了空值判断:当node.value不存在时,报告emptyCssProp消息(Empty \css` prop is not valid.`),从而避免访问不存在的节点属性导致崩溃。
11.11.0:Node ESM 导入修复
该版本修复了插件在 Node ESM 环境下无法正常import的问题(PR #3029)。这与包导出的模块格式有关,在纯 CommonJS 环境下运行正常、切换到 ESM 加载时则可能失败,属于纯工程层面的兼容性修复。
11.10.0:exports 字段限制导入范围
该版本(PR #2819)在package.json清单中新增了exports字段。exports字段会限制包内可被外部导入的文件范围,但 Emotion 团队表示会尽量放行所有此前被视为公共 API 的文件路径,避免破坏既有使用方的导入。
11.7.0:ESLint 8 进入 peer 依赖
该版本(PR #2562)将 ESLint 8 加入 peerDependencies 范围,同时继续支持 ESLint 6 与 ESLint 7。从 package.json 可以看到这一策略一直延续至今——插件对多个 ESLint 主版本保持向后兼容,方便不同工程平滑接入。
11.5.0:自动注入 jsxImportSource pragma
该版本(PR #2353)实现了@jsxImportSourcepragma 的自动添加。这是为 React 17+ 自动 JSX runtime(runtime: 'automatic')设计的能力,具体逻辑见 jsx-import.ts:
const JSX_IMPORT_SOURCE_REGEX = /\*?\s*@jsxImportSource\s+([^\s]+)/当检测到cssprop 但文件中不存在/** @jsxImportSource @emotion/react */注释时,规则会自动在文件头部插入:
/** @jsxImportSource @emotion/react */修复逻辑通过fixer.insertTextBefore(sourceCode.ast.body[0], ...)实现;若已存在但指向了错误的 import source,则会用fixer.replaceText直接替换为正确值。规则还支持通过配置选项指定importSource(默认'@emotion/react'),schema 中要求runtime必须等于'automatic'才会启用该分支。
11.2.0:syntax-preference 覆盖 css 函数
该版本(PR #2246)增强了syntax-preference规则:支持对css函数调用进行检查,并校验css与styled调用的参数样式类型。从源码看,isObjectStyle与isStringStyle两个判定函数覆盖了四种写法:
// 对象风格(isObjectStyle) css({ color: 'red' }) styled.h1({ color: 'red' }) // 简写 styled('h1')({ color: 'red' }) // 完整写法 // 字符串风格(isStringStyle) css`color: red;` styled.h1`color: red;` styled('h1')`color: red;`当配置为"object"偏好时,规则还会递归检查ArrayExpression中每个元素、TemplateLiteral、字符串Literal,以及 JSX 中css属性的表达式容器;对于字符串风格的模板字面量,报告preferWrappingWithCSS(Prefer wrapping your string styles with \css` call.)——即提示用css` 标签包装。
11.0.0:重大重构 —— 改名、新规则与迁移体系
11.0.0 是本插件历史上最重要的一次大版本,包含一个 Major 变更与三个 Minor 变更:
插件改名(PR #1675):
eslint-plugin-emotion正式更名为@emotion/eslint-plugin。迁移动作很明确:- 配置中的
"plugins": ["emotion"]改为"plugins": ["@emotion"]; - 规则前缀由
emotion/改为@emotion/。
- 配置中的
新增
@emotion/pkg-renaming规则:专为 Emotion 11 迁移设计的 codemod 规则,详见下文。cssprop 场景尊重syntax-preference(PR #1659):此前syntax-preference只检查styled/css调用,现在 JSX 中的cssprop 写法(对象 vs 字符串)也纳入风格统一检查。ESLint 7 加入 peer 依赖范围(PR #2034):在继续支持 ESLint 6 的基础上扩展兼容矩阵。
随后发布的11.0.0-rc.0与11.0.0-next.10只是发布候选与预发布版本,内容与 11.0.0 一致。
10.x 时代:稳定与修补
- 10.0.27:补充 LICENSE 文件(PR #1698)。
- 10.0.14:更新构建工具,并增强
jsx-import规则的自动修复能力——当文件中已存在import ... from '@emotion/core'时,自动修复会在现有 import 语句中追加jsx具名导入,而不是新增一行 import。
三、规则体系深度解析
当前仓库共包含 6 条规则,全部源码位于packages/eslint-plugin/src/rules/,文档位于packages/eslint-plugin/docs/rules/。
3.1 jsx-import:保证 css prop 可用的前置条件
cssprop 在 React 环境中依赖jsx被正确设置为 pragma。该规则(详见 jsx-import.md)的判定与修复分两条路径:
经典 pragma 模式:检查是否存在import { jsx } from '@emotion/react'(或@emotion/core)以及/** @jsx jsx */注释。不满足时报错:
// 错误示例 let element = <div css={{ color: 'green' }} />// 正确示例 /** @jsx jsx */ import { jsx } from '@emotion/react' let element = <div css={{ color: 'green' }} />自动修复时会根据现状智能补全:已有 jsx 导入就只补 pragma 注释,已有 pragma 就在既有@emotion/react导入中追加jsx,两者皆无则同时插入注释与导入。另外该规则还识别context.settings.react.pragma配置(settings: { react: { pragma: 'jsx' } })。
自动 runtime 模式:对应 11.5.0 新增能力,配置方式如下:
{ "rules": { "@emotion/jsx-import": ["error", { "runtime": "automatic", "importSource": "@emotion/react" }] } }该模式下规则不再要求显式导入,而是检查@jsxImportSource注释是否存在且指向正确,缺失时自动插入。此外,规则还会将css={...}内的裸模板字面量修复为css标签调用,例如把<div css={`color:hotpink;`} />改写为css标签包裹的形式。
何时不使用:如果你已通过 Babel 插件等方式自动添加导入与 pragma,可关闭此规则。
3.2 syntax-preference:统一样式书写风格
该规则(详见 syntax-preference.md)在string与object两种风格间强制二选一,schema 定义见 syntax-preference.ts:
{ "rules": { "@emotion/syntax-preference": ["error", "string"] } }配置为"string"时,以下对象写法会被报错(提示Styles should be written using strings.):
const H1 = styled.h1({ color: red }) const H1 = styled('h1')({ color: red })配置为"object"时,以下字符串写法会被报错:
const H1 = styled.h1`color: red;` const H1 = styled('h1')`color: red;`何时不使用:如果你的团队不想把样式限定为单一语法,可以不启用。
3.3 pkg-renaming:Emotion 11 迁移的包名 codemod
这是 11.0.0 为 Emotion 11 迁移新增的规则(README 中将其定位为 "Emotion 11 codemod")。它在 pkg-renaming.ts 中内置了一张包名映射表:
| 旧包名 | 新包名 |
|---|---|
@emotion/core | @emotion/react |
emotion | @emotion/css |
emotion/macro | @emotion/css/macro |
@emotion/styled-base | @emotion/styled/base |
jest-emotion | @emotion/jest |
babel-plugin-emotion | @emotion/babel-plugin |
eslint-plugin-emotion | @emotion/eslint-plugin |
create-emotion-server | @emotion/server/create-instance |
create-emotion | @emotion/css/create-instance |
emotion-server | @emotion/server |
命中映射的 import 声明会被报告renamePackage消息,并可自动修复为import ... from '新包名'。此外它还处理两类特殊场景:
- 默认导出迁移:
import css from '@emotion/css'(或/macro)这类默认导入在 Emotion 11 中已改为具名导出,规则会将其重写为import { css } from '@emotion/react'(保留局部别名); - emotion-theming 并入:
emotion-theming的导出已并入@emotion/react,规则会将导入源替换为'@emotion/react'。
启用方式:
{ "rules": { "@emotion/pkg-renaming": "error" } }3.4 其余三条迁移辅助规则
README 将以下三条规则归类为 "Emotion 10 codemods",并建议迁移后继续保留它们——例如让使用cssprop 时自动补全jsx导入等:
{ "rules": { "@emotion/jsx-import": "error", "@emotion/no-vanilla": "error", "@emotion/import-from-emotion": "error", "@emotion/styled-import": "error" } }styled-import(见 styled-import.md):检测import styled from 'react-emotion'这类错误来源,提示改为从@emotion/styled导入;import-from-emotion(见 import-from-emotion.md):在 Emotion 10+ 中,react-emotion不再转发emotion的导出,从react-emotion导入css等符号会被报错,建议改用emotion;no-vanilla(见 no-vanilla.md):在 React 场景下不推荐使用 vanilla 形态的@emotion/css,该规则对相关导入报错;如果你不使用 React 而用 vanilla emotion,应关闭此规则。
注意:README 特别提醒,这些规则假设你正在使用 React;如果不在 React 中使用,应继续使用
emotion包,并相应调整规则策略。
四、从 CHANGELOG 反推迁移实操
综合 CHANGELOG 与源码,可以整理出一条完整的 Emotion 10 → 11 迁移链:
- 改名先行:按 11.0.0 的要求,将
plugins与规则前缀从emotion改为@emotion; - 开启 pkg-renaming codemod:用
"@emotion/pkg-renaming": "error"自动改写全部旧包名导入(@emotion/core→@emotion/react、emotion→@emotion/css等); - 开启 Emotion 10 codemods:
jsx-import、styled-import、import-from-emotion帮助清理react-emotion等历史导入,no-vanilla约束 React 场景下的 vanilla 用法(可按需永久关闭); - 对齐现代 JSX runtime:启用
@emotion/jsx-import的 automatic 模式后,规则自动维护@jsxImportSourcepragma,无需手写; - 统一风格:用
syntax-preference在全仓库范围内锁定字符串或对象风格。
五、版本兼容速查
| 版本 | 关键变更 | 意义 |
|---|---|---|
| 11.12.0 | TypeScript 源码迁移;空cssprop 崩溃修复 | 类型声明自动生成;规则健壮性提升 |
| 11.11.0 | 修复 Node ESM 导入 | 工程兼容性 |
| 11.10.0 | package.json 增加exports字段 | 限制公开 API 范围 |
| 11.7.0 | ESLint 8 加入 peer 依赖 | 兼容 ESLint 6/7/8 |
| 11.5.0 | 自动注入@jsxImportSourcepragma | 支持 React 17+ 自动 runtime |
| 11.2.0 | syntax-preference支持css函数与参数检查 | 风格检查覆盖面扩大 |
| 11.0.0 | 更名@emotion/eslint-plugin;新增pkg-renaming;ESLint 7 支持 | Emotion 11 迁移体系成型 |
| 10.0.27 | 补充 LICENSE | 合规 |
| 10.0.14 | jsx-import自动修复并入已有 import | 自动修复体验优化 |
六、结语
从 10.0.14 的单一规则修补,到 11.0.0 的改名与迁移体系,再到 11.12.0 的 TypeScript 化与空cssprop 修复,@emotion/eslint-plugin的 CHANGELOG 本身就是一份 Emotion 生态演进的缩影。对于正在使用或计划迁移 Emotion 的团队,开启这套规则不仅能借助自动修复节省大量手工改动,还能在编码阶段持续守住样式导入与书写风格的规范。后续若需深入了解每条规则的边界行为,可直接阅读仓库内 docs/rules 下的规则文档与src/rules/下的源码实现。
【免费下载链接】emotion👩🎤 CSS-in-JS library designed for high performance style composition项目地址: https://gitcode.com/gh_mirrors/em/emotion
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考