「使用 webpack 5 从0到1搭建React+TypeScript 项目环境」2. 集成 css、less 与 sass

2022-10-24 18:31:19 浏览数 (1)

「使用 webpack 5 从0到1搭建React TypeScript 项目环境」2. 集成 css、less 与 sass

上篇文章带大家使用 webpack 5集成 ReactTypeScript,同时为了提高我们的代码质量,我们会在构建中添加「类型检查」「代码规范校验」。这次我们在上篇的基础上介绍如何集成 csslesssass

1. 配置 css

1.1 开发环境

为了在 JavaScript 模块中import 一个 CSS 文件,你需要安装 style-loadercss-loader,并在 module 配置 中添加这些 loader

我们需要安装css-loaderstyle-loader

代码语言:javascript复制
yarn add css-loader style-loader -D

修改配置文件:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.css$/i,
      use: ["style-loader", "css-loader"],
    },
  ],
},

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

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

接下来再通过yarn start开启即可看到我们引入外部.css文件生效。

1.2 生产环境

在生产环境下,我们需要进行压缩CSS,以便在生产环境中节省加载时间,同时还可以将CSS文件抽离成一个单独的文件。实现这个功能,需要 mini-css-extract-plugin 这个插件来帮忙。安装插件:

代码语言:javascript复制
yarn add mini-css-extract-plugin -D

本插件会将 CSS 提取到单独的文件中,为每个包含 CSSJS文件创建一个 CSS文件,并且支持 CSSSourceMaps 的按需加载。

本插件基于 webpack 5 的新特性构建,并且需要webpack 5才能正常工作。

之后将loaderplugin 添加到你的 webpack 配置文件中。

webpack.config.pred.js中做如下添加如下配置:

代码语言:javascript复制
const miniCssExtractPlugin = require('mini-css-extract-plugin');
// ...
module.exports = {
  // ....
  module: {
    rules: [
      // ...
      {
        test: /.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ]
  },
  plugins: [
    // ...
    new MiniCssExtractPlugin({
      filename: 'styles/[name].[contenthash].css'
    }),
  ],
  mode: 'production',

}

接下来再通过yarn build打包即可看到我们的输出目录多了一个「styles」文件夹,里面是我们抽离出来的CSS文件,但我们却看到CSS文件并没有被压缩,为了压缩输出的CSS文件,我们需要css-minimizer-webpack-plugin这个插件来帮忙。安装插件:

代码语言:javascript复制
yarn add css-minimizer-webpack-plugin -D

webpack.config.pred.js中做如下添加如下配置:

代码语言:javascript复制
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// ...
module.exports = {
  // ....
  // 优化配置 
  optimization: { 
    minimizer: [
      new CssMinimizerPlugin(), 
    ], 
  },
}

接下来再通过yarn build打包即可看到我们的输出「styles」文件里面的CSS文件已经被压缩了。

2. 使用 CSS modules

当开发人员命名的类有冲突时,后面的样式会覆盖前面的样式。

那么该如何解决呢?当然你可以选择命名的时候避免冲突,还有一种方法便是使用 CSS modules,这里便不再详细介绍它了,只讲如何配置环境。

首先,我们需要先改变引用的方式:

src/index.module.css

代码语言:javascript复制
.h1 {
  background-color: red;
}

scr/index.tsx

代码语言:javascript复制
import React from "react";
import ReactDOM from "react-dom";
import index from './index.module.css'

const App = () => (
  <h1 className={index.h1}>Hello World!</h1>
)

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

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

这个变量是一个对象,包含了对应样式文件的所有CSS类名称, 然后在组件中引用对应的类名变量。我们还需要将index.css重命名为index.module.css

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

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

代码语言:javascript复制
declare module "*.module.css";

之后重启应用,再次查看界面效果,就可以看见正常了:

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

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

webpack.config.dev.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.css$/i,
      use: ["style-loader", {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }],
    },
  ],
},

webpack.config.prod.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.css$/i,
      use: [MiniCssExtractPlugin.loader, {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }],
    },
  ],
},

修改typings.d.ts 的配置:

代码语言:javascript复制
declare module "*.css";

这样,我们就可以以如下方式进行使用了:

代码语言:javascript复制
import React from "react";
import ReactDOM from "react-dom";
import index from './index.css'

const App = () => (
  <h1 className={index.h1}>Hello World!</h1>
)

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

3. 配置 Less

如果你想在项目中使用less,那么我们就需要less-loader这个工具。

首先,我们先安装一下:

代码语言:javascript复制
yarn add less less-loader -D

webpack.config.dev.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.less$/i,
      use: ["style-loader", {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }, 'less-loader'],
    },
  ],
},

webpack.config.prod.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.less$/i,
      use: [MiniCssExtractPlugin.loader, {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }, 'less-loader'],
    },
  ],
},

同时,为了配合 CSS modules,我们需要在typings.d.ts 中加入以下内容,否则 Typescript无法识别 Less 类型:

代码语言:javascript复制
declare module "*.less";

如此,我们就可以在项目中使用Less了。

4. 配置 Sass

接下来我们看看如何配置 Sass,其实与 Less 的设置方式是类似的。

如果你想在项目中使用Sass,那么我们就需要sass-loader这个工具。

首先,我们先安装一下:

代码语言:javascript复制
yarn add sass sass-loader -D

webpack.config.dev.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.s[ac]ss$/i,
      use: ["style-loader", {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }, 'sass-loader'],
    },
  ],
},

webpack.config.prod.js中我们做如下修改:

代码语言:javascript复制
module: {
  rules: [
    ...,
    {
      test: /.s[ac]ss$/i,
      use: [MiniCssExtractPlugin.loader, {
        loader: "css-loader",
        options: {
          modules: true,
        },
      }, 'sass-loader'],
    },
  ],
},

同时,为了配合 CSS modules,我们需要在typings.d.ts 中加入以下内容,否则 Typescript无法识别 sassscss 类型:

代码语言:javascript复制
declare module "*.sass";
declare module "*.scss";

如此,我们就可以在项目中使用Sass了。

这样以来,我们的项目环境就集成 csslesssass,同时还支持css module

0 人点赞