Create React App 中配置 CSS (css normalize、scss、styled-components) 的正确姿势

3,398 阅读4分钟

上篇文章我们了解了如何 从零搭一个 React 脚手架,学习了 webpack 4.0 的基本配置。

这几天我尝试在 Create React App(下面简称 cra) 中配置 CSS,其中配置 sass 还是挺有意思的。因为官方推荐的方法不适用于国内用户,找到了一种快速配置的方法。 今天给大家分享下。

太长不看版

  • 我们想在 Create React App 创建的应用中配置 scss,官方推荐引入 node-sass。

  • 但是国内下载 node-sass 经常失败,而且 node-sass 需要本地编译,速度很慢。

  • 于是我们使用 dart-sass 代替 node-sass,但是 Create React App 只支持 node-sass。

  • 经过一顿搜索,我们发现 npm 6.9 支持 package alia 功能,可以给 npm 包一个别名。

  • 所以我们在本地下载 dart-sass, 并给一个别名:node-sass,这样项目就不会报错啦。

代码:

yarn add node-sass@npm:dart-sass

正文

第一步,初始化 cra。

初始化

cra 默认是不支持 TypeScript 的,需要按照 官网 ,加上 --template typescript 参数。

yarn global add create-react-app

# 项目名称为 react-demo
create-react-app react-demo --template typescript 

安装完成后,进入 react-demo,启动项目。

cd react-demo
yarn start

目录说明

.
├── README.md
├── package.json
├── public             // 静态文件
│   ├── favicon.ico    // 图表
│   ├── index.html     // 首页
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt     // 用于屏蔽百度
├── src                // 源代码
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx        // 主组件
│   ├── index.css
│   ├── index.tsx      // 入口文件
│   ├── logo.svg
│   ├── react-app-env.d.ts // TS 类型声明
│   ├── serviceWorker.ts
│   └── setupTests.ts  // 测试文件
├── tsconfig.json      // TS 配置文件
└── yarn.lock

接下来开始进行 css 相关配置,cra 提供了 css normalize。 (官网:Adding a CSS Reset

css normalize

字面意思,让 css 变的普通。

这个属性会将默认样式重写,让页面在不同浏览器上的默认样式基本相同。 (默默吐槽,默认样式都会被覆盖,个人感觉这个东西没什么用)

使用方法很简单,index.css 上添加 @import-normalize; 就可以啦。

@import-normalize; /* 引入 normalize.css */
/* 其他样式 */

支持 scss

官方网站对引入 scss 有详细介绍。

node-sass

yarn add node-sass

但我们不用这种方法。

大家去搜索一下就知道了,node-sass 经常下载失败。

不使用 node-sass 的原因

  1. 容易下载失败 我们安装 node-sass 时在 node scripts/install 阶段会从 github.com 上下载一个 .node 文件。 因为 GitHub Releases 里的文件都托管在 s3.amazonaws.com 上面, 而这个网址在国内总是网络不稳定,所以我们总是下载失败。

  2. node-sass 需要本地编译 node-sass 下载完成后,不能直接使用,需要本地编译一下。本地编译速度很慢,而且很消耗 CPU。

使用 dart-sass 代替 node-sass

一顿搜索后,有大佬建议使用 dart-sass 代替 node-sass。

dart-sass 兼容 node-sass 的 API,而且安装过程无需下载二进制文件。

直接安装

直接安装 dart-sass

yarn add dart-sass

安装之后,我们新建一个 .scss 文件,并引入项目。

这时候 cra 会报错:请下载 node-sass

以 node-sass 命名 dart-sass

不能直接安装 dart-sass,再次搜索 cra 中安装 dart-sass 的解决方案。

最后,在 cra 的 issue 找到了答案。

If you're not using yarn, npm 6.9 added package-aliasing, so npm install node-sass@npm:dart-sass will install dart-sass and play nicely with the default create-react-app config.

npm 从 6.9 版本开始支持包别名(package-aliasing)功能,语法是 npm install node-sass@npm:dart-sass

所以,我们在本地下载 dart-sass, 并给一个别名:node-sass。这样就不会报错啦。

yarn add node-sass@npm:dart-sass

styled-components

虽然上面介绍了 scss的配置,但是我最喜欢的还是 styled-components,比 sass 更香。

安装

yarn add styled-components
yarn add --dev @types/styled-components

原理

模板字符串 有一个隐藏的功能,这个功能一直没有人用。

直到 styled-components 的出现。

带标签的模板字符串,用法:

// myTag 是一个函数,具体看下面👇
myTag`that ${ person } is a ${ age }`;

一个 🌰 :

var person = 'Mike';
var age = 28;

var output = myTag`that ${ person } is a ${ age }`;

console.log(output);
// that Mike is a youngster

// strings ["that ", " is a ", ""]
function myTag(strings, personExp, ageExp) {
  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "
	
// 在这个示例中,结尾应该还有一个 string
// var str2 = strings [2];
// 但是为空(''),所以我们忽略 str2

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  return str0 + personExp + str1 + ageStr;
}

用法

具体用法不是这篇文章的重点,这里简单举个例子。

感兴趣的同学可以去官网查看。

const Button = styled.a`
  /* 创建一个 a 标签,名称为 Button */
  /* 这块写 css */
    border: 1px solid red;
  /* 如果 primary  */
  ${props => props.primary && css`
    background: white;
    color: black;
  `}
`

render(
  <div>
    <Button primary>
      button1 其实是 a 标签,边框为红
    </Button>
    <Button>
      button2 没有边框
    </Button>
  </div>
)

总结

今天介绍了 Create React App 中如何使用 css normalize、sass、styled-components,和一些简单原理。

  • css normalize
    • 这个属性会将默认样式重写,让页面在不同浏览器上的默认样式基本相同。
    • 使用方法: @import-normalize;
  • scss
    • 使用 dart-sass 代替 node-sass
    • yarn add node-sass@npm:dart-sass
  • styled-components
    • 原理:模板字符串的隐藏的功能。
      • myTagthat ${ person } is a ${ age };
      • myTag 是一个函数
    • 用法
      const Button = styled.a`
        /* 创建一个 a 标签,名称为 Button */
        /* 这块写 css */
          border: 1px solid red;
        /* 如果 primary  */
        ${props => props.primary && css`
          background: white;
          color: black;
        `}
      `