webpack 转换 less,开启 CSS Modules 后背景图片失效

开发背景

使用 create-react-app 创建 React 项目后,通过 react-app-rewired 开启了 less 转换的功能。

但通过抄袭 react-app-rewire-css-modules 模块开启 CSS Modules 发现在 *.module.less 里面的背景图片失效,需要修改图片路径为 ../yourdir/yourImage 的方式才能有效解决(进入上一层级目录,在进入当前文件夹目录)。

issues 上面也有一个类似的问题,CSS background img path error

解决方案

需要在转换 less 的后面加一个 loader,名字是 resolve-url-loader

如果是 sass 可以参考上面的 issues 修复问题。

react-app-rewired 方案,代码如下:

/**
 * less
 * 抄袭:https://github.com/codebandits/react-app-rewire-css-modules
 */
const path = require('path');
const cloneDeep = require('lodash.clonedeep');

const ruleChildren = loader =>
    loader.use ||
    loader.oneOf ||
    (Array.isArray(loader.loader) && loader.loader) ||
    [];

const findIndexAndRules = (rulesSource, ruleMatcher) => {
    let result = undefined;
    const rules = Array.isArray(rulesSource)
        ? rulesSource
        : ruleChildren(rulesSource);
    rules.some(
        (rule, index) =>
            (result = ruleMatcher(rule)
                ? { index, rules }
                : findIndexAndRules(ruleChildren(rule), ruleMatcher))
    );
    return result;
};

const findRule = (rulesSource, ruleMatcher) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    return rules[index];
};

const cssRuleMatcher = rule =>
    rule.test && String(rule.test) === String(/\.css$/);

const createLoaderMatcher = loader => rule =>
    rule.loader &&
    rule.loader.indexOf(`${path.sep}${loader}${path.sep}`) !== -1;
const cssLoaderMatcher = createLoaderMatcher('css-loader');
const postcssLoaderMatcher = createLoaderMatcher('postcss-loader');
const fileLoaderMatcher = createLoaderMatcher('file-loader');

const addAfterRule = (rulesSource, ruleMatcher, value) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    rules.splice(index + 1, 0, value);
};

const addBeforeRule = (rulesSource, ruleMatcher, value) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    rules.splice(index, 0, value);
};

function createRewireLess({
    localIdentName = `[local]___[hash:base64:5]`,
    lessLoaderOptions = {}
}) {
    return function(config, env) {
        const cssRule = findRule(config.module.rules, cssRuleMatcher);
        const sassRule = cloneDeep(cssRule);
        const cssModulesRule = cloneDeep(cssRule);

        cssRule.exclude = /\.module\.css$/;

        const cssModulesRuleCssLoader = findRule(
            cssModulesRule,
            cssLoaderMatcher
        );
        cssModulesRuleCssLoader.options = Object.assign(
            { modules: true, localIdentName },
            cssModulesRuleCssLoader.options
        );
        addBeforeRule(config.module.rules, fileLoaderMatcher, cssModulesRule);

        sassRule.test = /\.less$/;
        sassRule.exclude = /\.module\.less$/;
        addAfterRule(sassRule, postcssLoaderMatcher, {
            loader: require.resolve('less-loader'),
            options: lessLoaderOptions
        });

        addBeforeRule(config.module.rules, fileLoaderMatcher, sassRule);

        const sassModulesRule = cloneDeep(cssModulesRule);
        sassModulesRule.test = /\.module\.less$/;
        // sassModulesRule.exclude = path.resolve(__dirname, 'node_modules');
        // fix image url
        addAfterRule(sassModulesRule, postcssLoaderMatcher, {
            loader: require.resolve('resolve-url-loader')
        });
        addAfterRule(sassModulesRule, postcssLoaderMatcher, {
            loader: require.resolve('less-loader'),
            options: lessLoaderOptions
        });
        addBeforeRule(config.module.rules, fileLoaderMatcher, sassModulesRule);

        return config;
    };
}

const rewireLess = createRewireLess({});

rewireLess.withLoaderOptions = createRewireLess;

module.exports = rewireLess;    

如果是 webpack 的配置,如下:

let module = {
    importLoaders: 3,
    modules: true,
    localIdentName: '[name]_[local]_[hash:base64:5]'
};
let loaders = [
    {
        loader: 'css-loader',
        options: module
    },
    {
        loader: 'postcss-loader',
        options: {
            plugins: [require('autoprefixer')('last 100 versions')]
        }
    },
    {
        loader: 'resolve-url-loader'
    },
    {
        loader: 'less-loader',
        options: {
            javascriptEnabled: true,
            modifyVars: { '@primary-color': '#1DA57A' }
        }
    }
];
原文阅读: webpack 转换 less,开启 CSS Modules 后背景图片失效
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Webpack 是一款非常流行的前端打包工具,它可以将 JavaScriptCSS、图片等多种资源文件进行打包,并通过一系列的插件和配置来进行定制化。当我们在开发过程中使用 CSS设置背景图片时,可能会遇到一些问题,比如路径引用不正确、文件无法被正确加载等。 为了解决Webpack打包CSS背景图片路径引用问题,我们可以采取以下几种方式: 1. 直接使用相对路径 我们可以使用相对路径来引用背景图片。比如,如果我们的 CSS 文件和图片文件在同一个目录下,那么可以直接使用相对路径来引用。例如: background-image: url(./bg.png); 这里的 "./" 表示当前目录,后面跟上文件名即可。 2. 配置 publicPath 在打包的时候,Webpack默认会将所有的图片等静态资源放到 output.path 指定的输出目录下,并根据 output.publicPath 配置的路径来进行访问。如果我们在使用背景图片的时候,出现了路径错误的问题,可能就是因为 publicPath 配置不正确造成的。 我们需要在配置文件中设置一个 publicPath,这个路径就是我们最终在浏览器中访问静态资源的路径。比如,我们可以将 publicPath 设置为"/static/",那么在 CSS 中引用背景图片的时候,可以这样写: background-image: url(/static/bg.png); 3. 使用 url-loader 和 file-loader 我们还可以使用 url-loader 和 file-loader 这两个 Loader 处理背景图片的路径问题。url-loader 可以将小于 limit 配置的图片转化为 Data URL,大于 limit 的图片会使用 file-loader 进行处理,最终输出成一个单独的图片文件。使用方式如下: { test: /\.(png|jpg|gif|svg)$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: '[name].[hash:7].[ext]', outputPath: 'images/' } } ] } 在以上代码中,我们配置了使用 url-loader 处理图片文件,并指定了 limit 为 8192,即小于 8KB 的图片会被转化为 Data URL;大于 8KB 的图片则使用 file-loader 进行处理,并输出至指定目录下。通过这种方式,我们可以避免在 CSS 中编写复杂的路径,也可以减少请求次数,提高页面性能。 通过以上几种方式,我们就可以轻松处理Webpack打包CSS背景图片路径引用的问题。基于不同的项目需求和实际情况,我们可以选择其中适合自己项目的方式来进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值