From 4733e00b9b1dc2ff8b02c04809939ea5ec768381 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Thu, 16 Feb 2023 21:10:34 +0800 Subject: [PATCH] =?UTF-8?q?:truck:=20refactor:=20=E5=B0=86=20styled=20?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E6=9B=BF=E6=8D=A2=E5=9B=9E=20@emotion/styled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking Changes: 不再计划默认支持组件选择器 --- docs/guide/strategy.md | 35 ++++++++++++------- package.json | 2 +- .../ThemeProvider/TokenContainer.tsx | 2 +- src/core/engine.ts | 2 ++ src/functions/createStyles/index.ts | 2 +- src/functions/createStyles/response.ts | 2 +- src/hooks/useAntdStylish.ts | 2 +- src/hooks/useTheme.ts | 2 +- src/pedestal.ts | 8 ----- 9 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 src/core/engine.ts delete mode 100644 src/pedestal.ts diff --git a/docs/guide/strategy.md b/docs/guide/strategy.md index 679128fd..25821ccb 100644 --- a/docs/guide/strategy.md +++ b/docs/guide/strategy.md @@ -32,15 +32,11 @@ antd-style 在构建之初,我们有两个基本假设: ## 当前 antd-style 选择的样式引擎 -基于目前的社区方案发展情况,我们选择了 `styled-component` 作为 `styled` 语法的样式引擎,选择了 `emotion` 作为 `css` 语法的样式引擎。决策原因如下: +基于目前的社区方案发展情况,我们选择了 `@emotion/styled` 作为 `styled` 语法的样式引擎,选择了 `emotion` 作为 `css` 语法的样式引擎。决策原因如下: -### styled: 为什么选择 styled-component +### styled: 为什么选择 @emotion/styled -styled 的语法候选池中有两个库: `styled-component` 和 `emotion`。一开始时我们使用的是 emotion 的方案,但在实际应用落地验证时,我们发现 emotion 的 styled 默认不支持组件作为选择器的写法,需要配置 babel 插件才可达成,而我们一旦 re-export 了 styled 对象,babel 插件的配置将会变得很复杂,大部分开发者可能都无法正确配置。 - -因此在 styled 写法上最终选择了 styled-component,为此我们将需多付出 Gzip 后 10 KB+ 大小的体积(对比 emotion/styled )。 - -对比如下: +styled 的语法候选池中有两个库: `styled-component` 和 `emotion`。 它们的能力对比如下: | 特性 | Styled Components | Emotion | | --------------------- | ----------------- | ---------------------------------------------------------------- | @@ -58,11 +54,27 @@ styled 的语法候选池中有两个库: `styled-component` 和 `emotion`。 | Dynamic styles | ✅ | ✅ | | Component as Selector | ✅ | 需要 [Babel 插件](https://emotion.sh/docs/@emotion/babel-plugin) | +一开始时我们使用的是 emotion 的方案,但在实际应用落地验证时,我们发现 emotion 的 styled 默认不支持组件作为选择器的写法,需要配置 babel 插件才能实现。 + +而我们最初的实现 re-export 了 `styled` 对象,这会使得 babel 插件的配置变得很复杂,大部分开发者可能都无法正确配置。 + +所以我们又尝试默认集成 `styled-components`, 但此时发现,如果要为了默认兼容组件选择器的写法来集成 styled-components,为此将需多付出压缩后 10 KB+ 大小的体积(对比 `@emotion/styled` )。 + +| 集成 `styled-components` 的版本([3.0.0-alpha.42](https://bundlephobia.com/package/antd-style@3.0.0-alpha.42)) | 集成 `@emotion/styled` 的版本([3.0.0-alpha.41](https://bundlephobia.com/package/antd-style@3.0.0-alpha.41)) | +| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| ![](https://mdn.alipayobjects.com/huamei_rqvucu/afts/img/A*uuRsQKLILmIAAAAAAAAAAAAADoN6AQ/fmt.webp) | ![](https://mdn.alipayobjects.com/huamei_rqvucu/afts/img/A*uuRsQKLILmIAAAAAAAAAAAAADoN6AQ/fmt.webp) | + +因此而在我们实际业务落地测试中发现,95% 的样式书写场景都不会用到组件选择器的语法。只有在需要动画、复合选择器等场景才会用到, 而在这种场景下 `createStyles` 的写法将会更加自然易用。 + +在我们看来,组件选择器的语法本质上是因为 styled-components 不支持创建 className 才不得已提供的补救措施。而为了这 5% 的使用场景再去额外增大 10kb+ 的体积,完全不划算。同时在最终定稿的实现方案中,也明确产出了 styled-components 的语法替换能力方案。详见:[createInstance-兼容 styled-components](/api/create-instance#兼容-styled-主题方案)。 + +因此综合实践案例,结合包体积、使用场景,我们在多次摇摆下最终选择了 `@emotion/styled` 作为 `styled` 语法的样式引擎。 + ### css: 为什么选择 emotion css 的语法候选池中也是上述两个库: `styled-component` 和 `emotion`。 -在决策 css 方案时,基本上没有太多额外判断,我们直接才采用了 emotion。原因是 styled-component 所提供的 `css` 方法无法直接转为 className 因此在转为 className 方面 styled-component 的能力是缺失的。而 `css` props 我们已经在上一节中解释过,它不是我们期望的 api。因此 `css` 采用了 emotion 作为样式引擎。 +在决策 css 方案时,基本上没有太多额外判断,我们直接才采用了 emotion。原因是 styled-component 所提供的 `css` 方法无法直接转为 className 因此在转为 className 方面 styled-components 的能力是缺失的。而 `css` props 我们已经在上一节中解释过,它不是我们期望的 api。因此 `css` 采用了 emotion 作为样式引擎。 | 特性 | Styled Components | Emotion | | -------------- | ------------------- | ------------------- | @@ -75,9 +87,6 @@ css 的语法候选池中也是上述两个库: `styled-component` 和 `emotio | Object styles | ✅ | ✅ | | Dynamic styles | ✅ | ✅ | -## 体积优化 - -由于 antd-style 同时采用了 styled-component 和 emotion,它的体积势必会比单一库更大。 +## 体积优化建议 -![](https://mdn.alipayobjects.com/huamei_rqvucu/afts/img/A*uuRsQKLILmIAAAAAAAAAAAAADoN6AQ/fmt.webp) -因此在实际使用中,我们建议采用 `styled` 或 `css` 中的一种写法,而不是两种写法混着写。如果不使用相应的方法,打包器能自动 TreeShaking 掉没有用到的方法。实测体积可以降到个位数 kb。 +在实际使用中,我们建议采用 `styled` 或 `css` 中的一种写法,而不是两种写法混着写。如果不使用相应的方法,打包器能自动 TreeShaking 掉没有用到的方法。实测体积可以降到个位数 kb。 diff --git a/package.json b/package.json index 8b19c75b..b43a0ed8 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "@emotion/react": "^11", "@emotion/serialize": "^1", "@emotion/styled": "^11", - "styled-components": "beta", "use-merge-value": "^1" }, "devDependencies": { @@ -120,6 +119,7 @@ "react-use-measure": "^2", "semantic-release": "^19", "semantic-release-config-gitmoji": "^1", + "styled-components": "beta", "stylelint": "^14", "three": "^0.148", "ts-jest": "^29", diff --git a/src/containers/ThemeProvider/TokenContainer.tsx b/src/containers/ThemeProvider/TokenContainer.tsx index 08c19da0..d450fdfc 100644 --- a/src/containers/ThemeProvider/TokenContainer.tsx +++ b/src/containers/ThemeProvider/TokenContainer.tsx @@ -1,7 +1,7 @@ import { ReactElement, useMemo } from 'react'; +import { PedestalProvider, reactCss } from '@/core/engine'; import { useAntdTheme, useThemeMode } from '@/hooks'; -import { PedestalProvider, reactCss } from '@/pedestal'; import { Theme } from '@/types'; import type { ThemeProviderProps } from './type'; diff --git a/src/core/engine.ts b/src/core/engine.ts new file mode 100644 index 00000000..542d6550 --- /dev/null +++ b/src/core/engine.ts @@ -0,0 +1,2 @@ +export { css as reactCss, ThemeProvider as PedestalProvider, useTheme } from '@emotion/react'; +export { default as styled } from '@emotion/styled'; diff --git a/src/functions/createStyles/index.ts b/src/functions/createStyles/index.ts index 9dfa948a..4c1d5ff5 100644 --- a/src/functions/createStyles/index.ts +++ b/src/functions/createStyles/index.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react'; +import { reactCss } from '@/core/engine'; import { useEmotion, useTheme } from '@/hooks'; -import { reactCss } from '@/pedestal'; import type { BaseReturnType, ClassNamesUtil, diff --git a/src/functions/createStyles/response.ts b/src/functions/createStyles/response.ts index 40195914..df1cc8c1 100644 --- a/src/functions/createStyles/response.ts +++ b/src/functions/createStyles/response.ts @@ -1,5 +1,5 @@ +import { reactCss } from '@/core/engine'; import { useAntdToken } from '@/hooks'; -import { reactCss } from '@/pedestal'; import type { Breakpoint, BreakpointMapParams, diff --git a/src/hooks/useAntdStylish.ts b/src/hooks/useAntdStylish.ts index 68a66282..87a9b294 100644 --- a/src/hooks/useAntdStylish.ts +++ b/src/hooks/useAntdStylish.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { reactCss } from '@/pedestal'; +import { reactCss } from '@/core/engine'; import { createAntdStylish } from '@/stylish/button'; import { AntdStylish } from '@/types'; diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index 4fb31d2e..5479929d 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,4 +1,4 @@ -import { useTheme as _useTheme } from '@/pedestal'; +import { useTheme as _useTheme } from '@/core/engine'; import { Theme } from '@/types'; import { useMemo } from 'react'; diff --git a/src/pedestal.ts b/src/pedestal.ts deleted file mode 100644 index fae4a486..00000000 --- a/src/pedestal.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { css as reactCss } from '@emotion/react'; -// styled 配套的 -export { ThemeProvider as PedestalProvider, useTheme, withTheme } from 'styled-components'; - -// styled 方法 -import type { CreateStyled } from '@/types'; -import _styled from 'styled-components'; -export const styled = _styled as unknown as CreateStyled;