Search code examples
webpacksassfont-awesomeextract-text-plugin

webpack doesn't copy font files


I try to set up a webpack config for my vue2 application. It should also create the css from sass. So i get a look to laravel's mix plugin to create my own webpack config. It works fine, but when I include font awesome in my sass file (@import "~font-awesome/scss/font-awesome";), I get this error:

Module build failed: ModuleNotFoundError: Module not found: Error: Can't resolve '../fonts/fontawesome-webfont.eot?v=4.7.0' in '[PATH]\client\styles'

Webpack should automatically copy the FA font files to [PATH]\client\fonts\ like laravel-mix. I tried a lot of solutions, but no one worked. My webpack.config.js looks like:

const path = require('path'),
    webpack = require('webpack'),
    ExtractTextPlugin = require("extract-text-webpack-plugin"),
    FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin"),
    postCssOptions = [require('autoprefixer')];

module.exports = {
    entry: {
        'main': [
          './client/scripts/main.js',
          './client/styles/main.scss'
        ]
    },
    output: {
        path: path.resolve(__dirname, 'public'),
        publicPath: './',
        filename: 'js/[name].js'
    },
    resolve: {
        extensions: [ '*', '.js', '.vue' ],
        alias: {
            'vue$': 'vue/dist/vue.common.js',
            'vue-router$': 'vue-router/dist/vue-router.common.js'
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        js: 'babel-loader?presets[]=es2015',
                        scss: ExtractTextPlugin.extract({
                            use: 'css-loader!sass-loader',
                            fallback: 'vue-style-loader'
                        }),
                        sass: ExtractTextPlugin.extract({
                            use: 'css-loader!sass-loader?indentedSyntax',
                            fallback: 'vue-style-loader'
                        }),
                        css: ExtractTextPlugin.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader'
                        }),
                        postcss: postCssOptions
                    }
                }
            },

            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style-loader'
                })
            },

            {
                test: /\.s[ac]ss$/,
                loader: ExtractTextPlugin.extract({
                    use: 'css-loader!sass-loader',
                    fallback: 'style-loader'
                })
            },

            {
                test: /\.html$/,
                loaders: ['html-loader']
            },

            {
                test: /\.(png|jpe?g|gif)$/,
                loader: 'file-loader',
                options: {
                    name: 'images/[name].[ext]?[hash]'
                }
            },

            {
                test: /\.(woff2?|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: 'file-loader',
                options: {
                    name: 'fonts/[name].[ext]?[hash]'
                }
            }
        ]
    },
    devtool: '#source-map',
    plugins: [
        new ExtractTextPlugin({
            filename: "./css/[name].css",
            allChunks: true
        }),
        new FriendlyErrorsWebpackPlugin ({
            shouldClearConsole: true
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: isProduction,
            options: {
                postcss: postCssOptions,
                context: __dirname,
                output: { path: './' }
            }
        })
    ]
}

Solution

  • Now i solved it using resolve-url-loader to the loaders of the sass/scss files, so i have:

                {
                    test: /\.s[ac]ss$/,
                    loader: ExtractTextPlugin.extract({
                        use: 'css-loader!resolve-url-loader!sass-loader?sourceMap',
                        fallback: 'style-loader'
                    })
                },
    
                {
                    test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                    loader: 'file-loader',
                    options: {
                        name: 'fonts/[name].[ext]?[hash]',
                        publicPath: '/'
                    }
                }
    

    remember, to add ?sourceMap to the sass loader https://www.npmjs.com/package/resolve-url-loader