webpack配置css-loader让scss文件支持模块化引入

1. webpack部分:

重点: modules: true, // 为false引入就是空对象, 无法使用

复制代码
const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths.js')
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin')
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    module: {
        rules: [
            // 直接引入图片 url
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: 'file-loader'
            },
            {
                test: /\.css$/,
                // loader 的执行顺序是:从后往前
                loader: ['style-loader', {
                    loader: "css-loader",
                    options: {
                        sourceMap: true,
                        modules: true
                    },
                }, 'postcss-loader'] // 加了 postcss
            },
            {
                test: /\.scss$/,
                // 增加 'less-loader' ,注意顺序
                loader: ['style-loader',  {
                    loader: "css-loader",
                    options: {
                        sourceMap: true,
                        modules: true,
                    }
                }, {
                    loader: "sass-loader",
                }]
            }
        ]
    },
    // 输出source-map, 方便直接调试es6源码
    devtool: 'source-map',
    plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'development'
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        }),
        // 热更新
        new HotModuleReplacementPlugin(),
        new DllReferencePlugin({
            // 描述react动态链接库的文件内容(告知webpack索引的位置)
            manifest: require(path.join(distPath, 'react.manifest.json')),
        }),
    ],
    devServer: {
        hot: true,
        port: 8111,
        progress: true,  // 显示打包的进度条
        contentBase: distPath,  // 根目录
        open: false,  // true:自动打开浏览器
        compress: true,  // 启动 gzip 压缩
        // 设置代理
        proxy: {
            '/api': 'http://localhost:8000',
            '/api2': {
                target: 'http://localhost:8111',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    }
})

2. 组件使用:

import styles from 'xx/path';

然后在标签的className使用styles.xxx或者styles['xxx'], 有中划线或者下划线的需要使用style['xxx-xxx']

复制代码
import React, { useState } from "react";
import connect from './connect';
import { mapStateTotProps } from "./mapStateToProps";
import { mapDispatchToProps } from "./mapDispatchToProps";
import styles from './TodoInput.scss'

// 子组件
const TodoInput = (props) => {
  console.log(styles, 'styles')
  const [text, setText] = useState("");
  const {
    addTodo,
    showAll,
    showFinished,
    showNotFinish,
  } = props;

  const handleChangeText = (e: React.ChangeEvent) => {
    setText((e.target as HTMLInputElement).value);
  };

  const handleAddTodo = () => {
    if (!text) return;
    addTodo({
      id: new Date().getTime(),
      text: text,
      isFinished: false,
    });
    setText("");
  };

  return (
    <div className={styles["todo-input"]}>
      <input
        type="text"
        placeholder="请输入代办事项"
        onChange={handleChangeText}
        value={text}
      />
      <button className={styles.btn} onClick={handleAddTodo}>+添加</button>
      <button className={styles.btn} onClick={showAll}>show all</button>
      <button className={styles.btn} onClick={showFinished}>show finished</button>
      <button className={styles.btn} onClick={showNotFinish}>show not finish</button>
    </div>
  );
};

export default connect(mapStateTotProps, mapDispatchToProps)(TodoInput);

注意事项:

  1. 作为模块化引入使用相当于vue的style标签加scope的效果, 因为会对class类解析生成唯一性字符串, 而标签是不会解析的, 如果class类的名称不想被改变使用:global{...}

scss文件:

复制代码
// :global写在里面, 因为外面的类的关系, 不会被全局样式影响
.todo-input {
    :global {
        .aaa {
            color: red;
        }
    }
}


// 写在最外层作用域, class名称是aaa的, 全局都会被影响
:global {
        .aaa {
            color: red;
        }
    }

组件使用:

import styles from './TodoInput.scss'

<input

type="text"

placeholder="请输入代办事项"

onChange={handleChangeText}

value={text}

className="aaa"

/>

  1. 也支持import 'xxx.scss'语法, 不过就没有styles对象了, scss里面的类名叫什么写什么

组件使用:

import './TodoInput.scss'

<input

type="text"

placeholder="请输入代办事项"

onChange={handleChangeText}

value={text}

className="aaa"

/>

<button className="btn" onClick={handleAddTodo}>+添加</button>

相关推荐
@一枝梅3 小时前
vue3 vite.config.js 引入bem.scss文件报错
javascript·rust·vue·scss
要加油哦~4 小时前
css | class中 ‘.‘ 和 ‘:‘ 的使用 | 如,何时用 &.is-selected{ ... } 何时用 &:hover{...}?
前端·css
JiangJiang6 小时前
🔥 面试官:Webpack 为什么能热更新?你真讲得清吗?
前端·面试·webpack
空&白8 小时前
css元素的after制作斜向的删除线
前端·css
奇舞精选9 小时前
你可能不知道但非常实用的 HTML5 元素
css
Jolyne_10 小时前
grid 实现完美的水平铺满、间隔一致的自适应布局
前端·css
西洼工作室10 小时前
【解决导航栏字体图标渲染导致文本闪烁问题】采用腾讯视频的解决方案
前端·css·css3
站在风口的猪110811 小时前
《前端面试题:CSS的display属性》
前端·css·html·css3·html5
FogLetter11 小时前
从Flex布局到Transition艺术:打造让用户尖叫的前端体验
前端·css
前端康师傅11 小时前
CSS中的继承问题
前端·css