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>

相关推荐
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
guokanglun1 小时前
CSS样式实现3D效果
前端·css·3d
NiNg_1_2345 小时前
前端CSS3 渐变详解
前端·css·html
Au_ust6 小时前
css:权重计算
前端·css
前端Hardy7 小时前
HTML&CSS 打造的酷炫菜单选项卡
前端·javascript·css·html·css3
YUJIANYUE8 小时前
原生html+js输入框下拉多选带关闭模块完整案例
javascript·css·html
码手Lion8 小时前
CSS多列布局:打破传统布局的束缚
前端·css
Wx-bishekaifayuan8 小时前
springboot市社保局社保信息管理与分析系统-计算机设计毕业源码03479
java·css·spring boot·spring·spring cloud·servlet·guava
起风的秋天@8 小时前
CSS Modules在框架中的使用
前端·css
熊的猫9 小时前
ES6 中 Map 和 Set
前端·javascript·vue.js·chrome·webpack·node.js·es6