Webpack结合less,加载相对路径时报错,绝对路径则没问题

#1

这是我的webpack配置:

var path = require('path');   //这个是引入Node的path路径模块用来解析路径的
var webpack = require("webpack"); //引入webpack来进行
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var SpritesmithPlugin = require('webpack-spritesmith');
var CopyWebpackPlugin = require('copy-webpack-plugin');

var rootPath = path.join(__dirname, '..');
var srcPath = path.join(rootPath, 'src');
var distPath = path.join(rootPath, 'dist');

var node_modules = path.resolve(rootPath, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');

var baseOnlinePath = 'https://xxx.xxx.com/m/assets/';

var extractCss = new ExtractTextPlugin({
    filename: "css/[name].css",
    allChunks: true,
    disable: false
});

module.exports = function () {
    return {
        context: srcPath,
        entry: {
            'app': 'js/main.js',
            'vendors': ['react', 'react-dom'],
        },
        output: {
            path: distPath,
            filename: 'js/[name].js',
            publicPath: '/',
            sourceMapFilename: 'sourcemap/[name].map'
        },
        resolve: {
            modules: [srcPath, "node_modules", "sprites"],
            extensions: ['.js', '.jsx']
        },
        module: {
            rules: [
                {
                    enforce: "pre",
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: "eslint-loader", // eslint校验
                },
                {
                    test: /\.coffee$/,
                    loader: 'coffee-loader',
                    exclude: /node_modules/
                },
                {
                    test: /\.(js|jsx)$/,
                    loader: 'babel-loader', // es6转译
                    include: [srcPath],
                    exclude: /node_modules/
                },
                {
                    test: /\.css$/,
                    use: extractCss.extract({ // 提取css文件
                        fallback: 'style-loader',
                        use: [{
                            loader: 'css-loader',
                            options: {
                                modules: true, // 开启css-modules
                                minimize: false,
                                sourceMap: true, // Sourcemaps
                                camelCase: false // 用CamelCase方式导出类名
                            }
                        }, {
                            loader: 'postcss-loader',
                            options: {
                                plugins: function () {
                                    return [
                                        require('autoprefixer') // 自动前缀
                                    ]
                                }
                            }
                        }],
                        publicPath: '/dist'
                    })
                },
                {
                    test: /\.less$/,
                    use: extractCss.extract({ // 提取scss文件
                        fallback: 'style-loader',
                        use: [{
                            loader: 'css-loader',
                            options: {
                                modules: false, // 开启css-modules
                                minimize: false,
                                sourceMap: true, // Sourcemaps
                                camelCase: false // 用CamelCase方式导出类名
                            }
                        }, {
                            loader: 'postcss-loader',
                            options: {
                                plugins: function () {
                                    return [
                                        require('autoprefixer') // 自动前缀
                                    ]
                                }
                            }
                        }, {
                            loader: 'less-loader',
                            options: {
                                sourceMap: true // Sourcemaps
                            }
                        }],
                        publicPath: process.env.NODE_ENV === 'prod' ? baseOnlinePath : '/dist'
                    })
                },
                {
                    test: /\.png$/, // css-sprites资源加载
                    loader: 'file-loader',
                    include: path.join(rootPath, 'src/mil_imgs/sprites'),
                    options: {
                        name: 'mil_imgs/[name].[ext]'
                    }
                },
                {
                    test: /\.(jpe?g|png|gif|svg)$/i,
                    use: [
                        {
                            loader: 'file-loader',
                            options: {
                                name: 'mil_imgs/[name].[ext]'
                            },
                            options: {

                            },
                        }, {
                            loader: 'image-webpack-loader',
                            options: {
                                gifsicle: {
                                    interlaced: false,
                                },
                                optipng: {
                                    optimizationLevel: 7,
                                },
                                pngquant: {
                                    quality: "65-90",
                                    speed: 4
                                },
                                mozjpeg: {
                                    progressive: true,
                                    quality: 65
                                },
                                svgo: {
                                    plugins: [
                                        {
                                            removeViewBox: false
                                        },
                                        {
                                            removeEmptyAttrs: false
                                        }
                                    ]
                                }
                            }
                        }
                    ],
                    include: path.join(rootPath, 'src/mil_imgs/**/*'),
                    exclude: [/node_modules/, path.join('mil_imgs/sprites')]
                }
            ],
            noParse: [pathToReact]
        },
        plugins: [
            extractCss,
            new SpritesmithPlugin({ // css-sprites实现插件
                alias: {
                    'sprite.png': path.join(rootPath, 'src/mil_imgs/sprite.png'),
                    '_sprite.less': path.join(rootPath, 'src/less/_sprite.less')
                },
                src: {
                    cwd: path.join(rootPath, 'src/mil_imgs/sprites'),
                    glob: '*.png'
                },
                target: {
                    image: path.join(rootPath, 'src/mil_imgs/sprite.png'),
                    css: [
                        [path.join(rootPath, 'src/less/_sprite.less'), {
                            format: 'handlebars_based_template',
                        }]
                    ]
                },
                apiOptions: {
                    cssImageRef: baseOnlinePath + 'mil_imgs/banner1.png'
                },
                customTemplates: {
                    'handlebars_based_template': path.join(rootPath, 'node_modules/spritesheet-templates/lib/templates/less.template.handlebars'),
                }
            }),
            new CopyWebpackPlugin([
                {
                    context: srcPath,
                    from: 'lib/**/*',
                    to: 'js/lib/[name].min.[ext]'
                },
                {
                    context: srcPath,
                    from: 'mil_imgs/**/*',
                    to: 'mil_imgs/[name].[ext]',
                    ignore: ['mil_imgs/sprites/*'],
                }
            ]),
            new HtmlWebpackPlugin({
                template: 'index.html',
                inject: true
            }),
        ],
    };
}

然后在less中引用图片:

.product-card{
  padding: 20px;
  position: relative;
  background: url(../mil_imgs/card-bg.png) no-repeat;
  background-size: 100% 100%;
  background-position: center;
}

当使用的是这样的相对地址的时候,就报这个错:

ERROR in ./mil_imgs/card-bg.png
    Module parse failed: /Users/chw/fecode/installment-fe/src/mil_imgs/card-bg.png Unexpected character '�' (1:0)
    You may need an appropriate loader to handle this file type.
    (Source code omitted for this binary file)
     @ ../~/css-loader?{"modules":false,"minimize":false,"sourceMap":true,"camelCase":false}!../~/postcss-loader?{}!../~/less-loader/dist?{"sourceMap":true}!./less/product.less 6:457-491

如果我使用的是绝对地址,好像绝对地址就是不作处理的额,所以不会报错:

.product-card{
  padding: 20px;
  position: relative;
  background: url(/mil_imgs/card-bg.png) no-repeat;
  background-size: 100% 100%;
  background-position: center;
}

但这样的话,我就没法对图片的路径进行替换了。有没有大神可以帮忙看看我是哪里配置错了么?

#2

可能是这个? https://github.com/webpack-contrib/css-loader/issues/228#issuecomment-181907171

以前混用 CSS 和 LESS 的时候遇到过, 需要配置 importLoaders.

#3

@jiyinyiyong
加上了也不行啊,还是报的相同的错误。


...

{
                    test: /\.less$/,
                    use: extractCss.extract({ // 提取scss文件
                        fallback: 'style-loader',
                        use: [{
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                                modules: false, // 开启css-modules
                                minimize: false,
                                sourceMap: true, // Sourcemaps
                                camelCase: false // 用CamelCase方式导出类名
                            }
                        }, {
                            loader: 'postcss-loader',
                            options: {
                                plugins: function () {
                                    return [
                                        require('autoprefixer') // 自动前缀
                                    ]
                                }
                            }
                        }, {
                            loader: 'less-loader',
                            options: {
                                sourceMap: true // Sourcemaps
                            }
                        }],
                        publicPath: process.env.NODE_ENV === 'prod' ? baseOnlinePath : '/dist'
                    })
                },

...

#4

publicPath: ‘./dist’