Webpack + Vue loader for css image url

1.6k views Asked by At

I am having trouble loading an image url with webpack. It works well in development mode. But at the time to build for production, it can no longer find the image with error:

Failed to load resource: net::ERR_FILE_NOT_FOUND file:///static/flags/4x3/gb.svg

Using Electron with vue-loader. The flags are in the static directory static/ I am using this boilerplate as the base https://github.com/bradstewart/electron-boilerplate-vue

Folder structure:

app/
    components/
    assets/
        less/
        flags/
        fonts/
    App.vue
    main.js
    background.js
build/
dist/
static/
    flags/
        1x1/
            ad.svg
            ae.svg
            ...
        4x3/
            ad.svg
            ae.svg
            ...

webpack.base.conf.js

var fs = require('fs')
var path = require('path')
var webpack = require('webpack')
var config = require('../config')
var projectRoot = path.resolve(__dirname, '../')

module.exports = {
    output: {
        path: config.build.outputRoot,
        filename: '[name].js'
    },

    target: 'node',
    node: {
        __filename: false,
        __dirname: false
    },
    resolve: {
        extensions: ['', '.js', '.vue', '.json'],
        fallback: [path.join(__dirname, '../node_modules')],
        alias: {
            app: path.resolve(__dirname, '../app'),
            '@': path.resolve(__dirname, '../app'),
            'vue': 'vue/dist/vue.common.js'
        }
    },

    module: {
        preLoaders: [
            {
                test: /\.vue$/,
                loader: 'eslint',
                include: projectRoot,
                exclude: /node_modules/
            },
            {
                test: /\.js$/,
                loader: 'eslint',
                include: projectRoot,
                exclude: /vue-devtools|node_modules/
            }
        ],
        loaders: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        less: 'style-loader!css-loader!less-loader'
                    }
                }
            },            
            {
                test: /\.js$/,
                loader: 'babel',
                include: projectRoot,
                exclude: /vue-devtools|node_modules/
            },
            {
                test: /\.json$/,
                loader: 'json'
            },
            {
                test: /\.html$/,
                loader: 'vue-html'
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url',
                query: {
                    limit: 10000,
                    name: path.join(config.build.assetsSubDirectory, '[name].[ext]')
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader: 'url',
                query: {
                    limit: 10000,
                    name: path.join(config.build.assetsSubDirectory, 'fonts/[name].[ext]')
                }
            }
        ]
    },
    plugins: [
        new webpack.ExternalsPlugin('commonjs2', [
            'desktop-capturer',
            'electron',
            'ipc',
            'ipc-renderer',
            'native-image',
            'remote',
            'web-frame',
            'clipboard',
            'crash-reporter',
            'screen',
            'shell'
        ]),
    ],
    vue: {
        loaders: {
            scss: 'style-loader!css-loader!sass-loader',
            less: 'style-loader!css-loader!less-loader'
        }
    },
    eslint: {
        formatter: require('eslint-friendly-formatter')
    },
    externals: ['ajv', 'acorn']
}

webpack.prod.conf.js

var path = require('path')
var webpack = require('webpack')
var merge = require('webpack-merge')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var config = require('../config')
var baseWebpackConfig = require('./webpack.base.conf')

module.exports = merge(baseWebpackConfig, {
    entry: {
        app: './app/main.js',
        secondary: './app/secondary.js',
        background: './app/background.js'
    },
    devtool: config.build.productionSourceMap ? '#source-map' : false,
    output: {
        filename: '[name].js',
        chunkFilename: '[id].js'
    },
    vue: { },
    plugins: [
        new CopyWebpackPlugin([
            { from: './app/package.json', to: '.' },
            { from: './static', to: 'static' }
        ]),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        new ExtractTextPlugin(path.join(config.build.assetsSubDirectory, '[name].css')),
        new HtmlWebpackPlugin({
            filename: 'main.html',
            template: './app/main.html',
            excludeChunks: ['background', 'secondary'],
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
            }
        }),
        new HtmlWebpackPlugin({
            filename: 'secondary.html',
            template: './app/secondary.html',
            excludeChunks: ['background', 'app'],
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
            }
        })
    ]
})

style.less

@flag-icon-css-path: '/static/flags';
@flag-icon-rect-path: '/4x3';
@flag-icon-square-path: '/1x1';

.flag-icon(@country) {
    .flag-icon-@{country} {
        background-image: ~"url('@{flag-icon-css-path}@{flag-icon-rect-path}/@{country}.svg')";

        &.flag-icon-squared {
            background-image: ~"url('@{flag-icon-css-path}@{flag-icon-square-path}/@{country}.svg')";
        }
    }
}

.flag-icon(ad);
.flag-icon(ae);
.flag-icon(af);
/*
....
*/
0

There are 0 answers