最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 「React Build」之三集成 CSS/Less/Sass/Antd

    正文概述 掘金(大古同学)   2021-04-06   788

    在上一篇文章中,我们使用 TypeScript/ESLint/Webpack 搭建了一个 React 应用。这篇文章中,我们继续在上一篇文章的基础上加入 CSS/Less/Sass/Antd

    在代码中引入 CSS

    创建一个src/pages/CssDemo/index.tsx组件并添加一个 CSS 类名

    import React from "react";
    
    const Index: React.FC = () => {
      return (
        <div className="container">
          <div>CSSDemo</div>
        </div>
      );
    };
    
    export default Index;
    

    然后我们在组件的同级目录创建一个 index.css文件并加入以下内容

    .container > div {
      font-size: 20px;
      color: blue;
    
      width: 200px;
      height: 200px;
      border: 1px solid gray;
    }
    

    通过npm start 启动应用

    当然!样式肯定是不会生效的。因为组件根本不知道container是在哪里被定义的。 so!我们需要在组件中导入样式文件模块

    import "./index.css";
    

    Webpack 会提示错误:"Module parse failed: Unexpected token".错误 ❎ 的原因是我们使用了一个 Webpack 无法解析的文件模块

    「React Build」之三集成 CSS/Less/Sass/Antd

    为开发环境配置 CSS

    我们需要让 Webpack 知道如何解析 CSS 文件,因此我们需要在webpack.dev.js中加入两个解析器

    const config= {
      ...
      module: {
        rules: [
          ...,
          {
            test: /\.css$/i,
            use: ["style-loader", "css-loader"],
          },
        ],
      },
      ...
    };
    

    这样配置后,当 Webpack 再遇到.css文件时,它将使用css-loaderstyle-loader进行处理(use 数组中的加载器从后向前执行)。

    • css-loader 在 import 语句(在我们的示例中为app.css)中读取引用的 CSS 文件并解析成 JavaScript 代码。
    • style-loader 将 JavaScript 代码中的 CSS 以 style 标签的形式插入到 html 文件中。

    为了使新的 Webpack 配置正常工作,我们需要安装css-loaderstyle-loader

    yarn add css-loader style-loader --dev
    

    接下来重新启动应用并观察界面,当然!样式生效了!

    「React Build」之三集成 CSS/Less/Sass/Antd

    为生产环境配置 CSS

    在生产环境中,需要把 CSS 样式抽离成单独的文件(避免浏览器缓存). 我们可以使用mini-css-extract-plugin代替style-loader来做到这一点。

    webpack 官方文档有说:

    接下来,我们安装mini-css-extract-plugin及其 TypeScript 类型库

    yarn add mini-css-extract-plugin @types/mini-css-extract-plugin --dev
    

    然后,我们需要把此 loader 加入到生产环境配置文件中,在webpack.prod.js中修改如下内容

    ...
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    
    const config= {
      ...,
      module: {
        rules: [
          ...,
          {
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader"],
          },
        ],
      },
      ...,
      plugins: [
        ...,
        new MiniCssExtractPlugin({
          filename: "[name].[contenthash].css",
        }),
      ],
      ...
    };
    

    mini-css-extract-plugin会将 CSS 样式从 JS 代码中抽离出来并创建.css 文件

    如果我们的应用使用了 code split

    • 那么可以使用[name]标志来让 Webpack 命名新的 CSS 文件。
    • 当内容更改时,使用[contenthash]标志更改已打包的新的文件名称,这也可以避免浏览器缓存。

    来,我们打一个包看看

    yarn run build
    

    我们可以看到在 build目录下已经生成了 CSS 文件

    「React Build」之三集成 CSS/Less/Sass/Antd

    然后我们查看 HTML 文件,发现 CSS 文件也被自动引入了

    「React Build」之三集成 CSS/Less/Sass/Antd

    为多个组件添加样式

    接下来我们在cssDemo/index.tsx组件中添加两个子组件,并且导入两个样式文件

    import "./heading.css";
    import "./content.css";
    
    const App = () => (
      <>
        <Heading />
        <Content />
      </>
    );
    const Heading = () => <h1 className="heading">My React and TypeScript App</h1>;
    
    const Content = () => <div className="content">With CSS!</div>;
    

    两个 CSS 文件内容如下所示

    /* heading.css */
    .heading {
      color: red;
    }
    
    /* content.css */
    .content {
      color: green;
    }
    

    然后通过yanr start启动应用查看界面效果,我们发现样式文件被转换了,变成了两个 style 标签引入到了 HTML 文件中

    「React Build」之三集成 CSS/Less/Sass/Antd

    接下来执行yarn run build打包项目,并查看打包后的文件,我们看到 CSS 生成了单独的文件

    「React Build」之三集成 CSS/Less/Sass/Antd

    是不是很有趣!?

    使用 CSS modules

    到这里,有经验的同学应该会发现一个问题: 开发人员必须仔细命名 CSS 类,才能避免样式名称冲突。 例如,如果我们将两个 CSS 类都称为“text”,那么标题和内容的颜色是什么呢?

    「React Build」之三集成 CSS/Less/Sass/Antd

    第二个 CSS 类的优先级高于第一个 CSS 类,导致两段文本均为绿色。

    如何解决呢?

    CSS modules 可以通过将 CSS 名称限定到特定组件中来解决样式类名冲突问题

    接下来我们CV如下代码实现CSS modules

    import heading from "./heading.module.css";
    import content from "./content.module.css";
    ...
    const Heading = () => (
      <h1 className={heading.heading}>My React and TypeScript App</h1>
    );
    const Content = () => <div className={content.content}>With CSS!</div>;
    

    import 语句跟原来的略有不同。 我们通过引用.module.css后缀的文件,并从中导入为一个变量

    这个变量是一个对象,包含了对应样式文件的所有 CSS 类名称, 然后在组件中引用对应的类名变量

    我们还需要将content.css重命名为content.module.css,将heading.css重命名为heading.module.css

    但是!TypeScript 编译出现错误 ❎“无法找到模块'.module.css'或对应的类型声明”错误,因为 TS 无法解析CSS modules

    「React Build」之三集成 CSS/Less/Sass/Antd

    为了解决这个错误,我们需要创建一个src/typings.d.ts类型声明文件并加入以下内容

    declare module "*.module.css";
    

    之后重启应用,再次查看界面效果,可以发现样式按预期的正常显示了

    「React Build」之三集成 CSS/Less/Sass/Antd

    我们看到 CSS 类名称被赋予了一个看起来很随机的名称。 因为这样可以确保不同组件中的样式名称不会冲突。

    如果我们还记得在组件中引用类名称的方式,那看起就有些奇怪了:

    className={fileName.cssClassName}
    

    为什么代码中导入的样式类名与生成后的类名不一样?因为上面的代码其实在通知 Webpack 为类名称赋予全局唯一的名称。

    接下来,我们再看看npm run build后的样式文件,我们发现生产环境的样式文件类名也是全局唯一的

    「React Build」之三集成 CSS/Less/Sass/Antd

    CSS modules 的引用方式优化

    每次都需要通过 *.module.css的方式实现 CSS modules 不免有些麻烦。其实,我们可以通过修改 Webpack 配置简化 CSS modules 的写法

    修改webpack.dev.js 的配置, CSS modules 官方文档

    ...
          {
            test: /\.css$/i,
            use: ["style-loader", {
              loader: "css-loader",
              options: {
                modules: true,
              },
            },
            ],
          },
    ...
    

    修改webpack.pro.js 的配置

    ...
          {
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, {
              loader: "css-loader",
              options: {
                modules: true,
              },
            },],
          },
    ...
    

    修改typings.d.ts 的配置

    declare module "*.css";
    

    我们还需要将content.module.css重命名为content.css,将heading.module.css重命名为heading.css

    修改 App 组件中导入的样式名称

    import contentStyle from "./content.css";
    import headingStyle from "./heading.css";
    

    最后重新启动应用查看界面效果,可以发现与之前的效果一致

    写法更简洁了是吧??

    在项目中配置 Less

    真实工作中,我们一般需要一些 CSS 预编译器以提高我们的工作效率,先说如何配置 Less webpack 参考文档

    修改webpack.dev.js 配置

          {
            test: /\.less$/i,
            use: [
              {
                loader: "style-loader",
              },
              {
                loader: "css-loader",
                options: {
                  modules: true,
                },
              },
              {
                loader: "less-loader",
              },
            ],
          },
    

    修改webpack.pro.js 配置

          {
            test: /\.less$/i,
            use: [MiniCssExtractPlugin.loader, {
              loader: "css-loader",
              options: {
                modules: true,
                importLoaders: 1,
              },
            },
            {
              loader: "less-loader",
            },
            ],
          },
    

    为了使新的 Webpack 配置正常工作,我们需要安装less-loaderless

    yarn add less less-loader --dev
    

    注意:还需要在typings.d.ts 中加入以下内容,否则 Typescript 无法识别 Less 类型

    declare module "*.less";
    

    为组件添加 Less

    接下来我们在 src/lessDemo/index.tsx 组件中导入 less 文件

    import React from "react";
    
    import style from "./index.less";
    
    const Index: React.FC = () => {
      return (
        <div className={style.container}>
          <div>LessDemo</div>
        </div>
      );
    };
    
    export default Index;
    

    Less 文件内容如下所示

    @color: purple;
    
    .container {
      div {
        font-size: 20px;
        color: @color;
        width: 200px;
        height: 200px;
        border: 1px solid gray;
      }
    }
    

    然后通过yanr start启动应用查看界面效果,我们发现样式文件被转换了,变成了两个 style 标签引入到了 HTML 文件中

    「React Build」之三集成 CSS/Less/Sass/Antd

    接下来执行yarn run build打包项目,并查看打包后的文件,我们看到 Less 和其他的 CSS 一起 生成了单独的文件

    「React Build」之三集成 CSS/Less/Sass/Antd

    是不是很有趣!?

    在项目中配置 Sass

    接下来我们看看如何配置 Sass,其实与 Less 的设置方式是类似的 . [webpack 参考文档][14]

    修改webpack.dev.js 配置

          {
            test: /\.s[ac]ss$/i,
            use: [
              //从包含CSS的JS代码中 创建 `style` 节点
              {
                loader: "style-loader",
              },
              // 将 CSS 转换为 CommonJS 格式的JS代码
              {
                loader: "css-loader",
                options: {
                  modules: true,
                },
              },
              // 将 Sass 转换为 CSS
              {
                loader: "sass-loader",
              },
            ],
          },
    

    修改webpack.pro.js 为如下配置

          {
            test: /\.s[ac]ss$/i,
            use: [MiniCssExtractPlugin.loader, {
              loader: "css-loader",
              options: {
                modules: true,
                importLoaders: 1,
              },
            },
            {
              loader: "sass-loader",
            },
            ],
          },
    

    为了使新的 Webpack 配置正常工作,我们需要安装sass-loadersass

    yarn add sass sass-loader --dev
    

    注意:还需要在typings.d.ts 中加入以下内容,否则 Typescript 无法识别 sass/scss 类型

    declare module "*.sass";
    declare module "*.scss";
    

    为组件添加 Sass

    接下来我们为 src/sassDemo/index.tsx 组件入 Sass 样式文件

    import React from "react";
    
    import style from "./index.scss";
    
    const Index: React.FC = () => {
      return (
        <div className={style.container}>
          <div>SASSDemo</div>
        </div>
      );
    };
    
    export default Index;
    

    Ssss 文件内容如下所示

    $color: red;
    
    .container {
      div {
        font-size: 20px;
        color: $color;
        width: 200px;
        height: 200px;
        border: 1px solid gray;
      }
    }
    

    然后通过yanr start启动应用查看界面效果,跟预期一样...

    为项目添加 UI 库-Antd

    在真实开发中,我们一般使用 UI 库来提高我们的界面开发效率。国内最火的 React UI 库非 Antd莫属。接下来我们开始配置吧

    首先安装 Antd 依赖

    yarn add antd
    

    修改 sr/pages/antdDemo/index.tsx组件-引入一个 Button 组件

    import React from "react";
    import { Button } from "antd";
    
    const Index: React.FC = () => {
      return (
        <div>
          <Button type="primary">Antd 按钮</Button>
        </div>
      );
    };
    
    export default Index;
    

    通过yarn start启动项目并观察界面效果,我们发现按钮被成功引用了,但是却没有显示正确的样式

    「React Build」之三集成 CSS/Less/Sass/Antd

    接下我们给 Antd 加上样式

    import React from "react";
    import { Button } from "antd";
    
    import "./index.less";
    
    const Index: React.FC = () => {
      return (
        <div>
          <Button type="primary">Antd 按钮</Button>
        </div>
      );
    };
    
    export default Index;
    

    index.less的内容如下

    @import "~antd/dist/antd.less";
    

    这里可以发现,Antd 的样式是基于 Less 实现的

    保存代码后却发现 Webpack 编译报错"Module build failed"

    「React Build」之三集成 CSS/Less/Sass/Antd

    我们根据报错中的 issue 地址去找解决方案,有方案说Less加上javascriptEnabled即可

    来我们加一下看看

          {
            test: /\.less$/i,
            use: ["style-loader", {
              loader: "css-loader",
              options: {
                modules: true,
              },
            },
              {
                loader: "less-loader",
                options: {
                  lessOptions: {
                    javascriptEnabled: true
                  },
                },
              },
            ],
          },
    

    设置完成后重启项目并观察界面效果,但是我们发现 Antd 还是没有样式,那么我们继续查找 issue

    真实原因:

    正确的 Webpack 配置如下

    const config = {
       ........
      module: {
        rules: [
           ........
          {
            test: /\.less$/i,
            use: ["style-loader", {
              loader: "css-loader",
              options: {
                modules: true,
              },
            },
              {
                loader: "less-loader",
              },
            ],
            exclude: path.resolve(__dirname, "../src/app.less"),
          },
          {
            test: /\.less$/i,
            use: ["style-loader", {
              loader: "css-loader",
            },
              {
                loader: "less-loader",
                options: {
                  lessOptions: {
                    javascriptEnabled: true
                  },
                },
              },
            ],
            include: path.resolve(__dirname, "../src/app.less"),
          },
        ]
      },
      ........
    
    

    修改src/app.less的内容

    @import "~antd/dist/antd.less";
    
    /* 全局样式,没有CSS modules
    
    作用:
    1. 覆盖Antd样式
    2. 定义全局公共样式
    */
    
    .myText {
      color: red;
    }
    

    修改src/index.tsx内容

    import React from "react";
    import ReactDOM from "react-dom";
    
    import './app.less'
    import AntdDemo from "./pages/antdDemo";
    ........
    
    const App = () => (
      <>
      ....
        <AntdDemo />
      ....
      </>
    );
    
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById("root")
    );
    
    

    重新启动项目,发现样式正常显示了,?

    「React Build」之三集成 CSS/Less/Sass/Antd


    难道这就结束了吗??‍♂️ 不,离搭建一个完整的 React 应用有些距离。那么在下一篇文章中,我会告诉你如何在项目中集成图片/字体资源


    起源地下载网 » 「React Build」之三集成 CSS/Less/Sass/Antd

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元