Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image assets not found in packaged electron app - angular4 and webpack

I'm writing an electron app using Angular and Webpack and I have an issue where my one and only reference to an image is getting skewed in the build somehow. I suspect it's a webpack config error somehow tied in to what electron does to run the app - given the actual resultant URL points to the correct directory according to where the .js and .png files sit when output to dist.

The image is reference in login.component.html

The the src directory looks like this:

src
├── app/
│   └── login/
│        ├── login.component.html
│        ├── login.component.ts
│        └── login.component.css
└── assets/
    └── images/
        └── someimage.png

the dist dir:

 dist 
   ├── assets/
   │    └── images/
   │        └── someimage.png
   ├── index.html
   ├── index.js
   ├── app.css
   └── app.js

Here's my common config

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: {
        'polyfills': './src/polyfills.ts',
        'vendor': './src/vendor.ts',
        'app': './src/app.ts',
    },

    resolve: {
        extensions: ['.ts', '.js']
    },

    target: "electron-renderer",

    module: {
        rules: [
            {
                test: /\.ts$/,
                loaders: [
                    {
                        loader: 'awesome-typescript-loader',
                        options: { configFileName: helpers.root('src', 'tsconfig.json') }
                    }, 'angular2-template-loader'
                ]
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loader: 'file-loader?name=assets/[name].[hash].[ext]'
            },
            {
                test: /\.scss$/,
                exclude: helpers.root('src','app'),
                use: [{
                    loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' })
                },
                {
                    loader: 'css-loader',
                    options: {
                        sourceMaps: true
                    }
                }, 
                {
                    loader: "resolve-url-loader"
                },
                {
                    loader: "sass-loader", 
                    options: {
                        sourceMaps: true
                    }
                }]
            },
            {
                test: /\.scss$/,
                include: helpers.root('src','app'),
                use: [
                    {
                        loader: 'raw-loader'
                    },
                    {
                        loader: "sass-loader"
                    }
                ]
            }
        ]
    },

    plugins: [
        // Workaround for angular/angular#11580
        new webpack.ContextReplacementPlugin(
            // The (\\|\/) piece accounts for path separators in *nix and Windows
            /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
            helpers.root('./src'), // location of your src
            {} // a map of your routes
        ),

        new webpack.optimize.CommonsChunkPlugin({
            name: ['app', 'vendor', 'polyfills']
        }),

        new HtmlWebpackPlugin({
            template: 'src/index.html'
        }),

        new CopyWebpackPlugin([
            {from: helpers.root('./src/index.js'),to: helpers.root('./dist/index.js')},
            {from: helpers.root('./package.json'),to: helpers.root('./dist/package.json')}
        ])
    ]
};

and my prod to merge with the above

const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const commonConfig = require('./webpack.common.js');
const helpers = require('./helpers');
const ElectronConnectWebpackPlugin = require('electron-connect-webpack-plugin');
const path = require('path');

const ENV = process.env.NODE_ENV = process.env.ENV = 'production';

module.exports = webpackMerge(commonConfig, {
  output: {
    path: helpers.root('dist'),
    filename: '[name].js',
    chunkFilename: '[id].[hash].chunk.js'
  },

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),

    new ExtractTextPlugin('[name].[hash].css'),
    new webpack.DefinePlugin({
      'process.env': {
        'ENV': JSON.stringify(ENV)
      }
    }),
    new webpack.LoaderOptionsPlugin({
      htmlLoader: {
        minimize: false // workaround for ng2
      }
    })
  ]
});
like image 439
Bruford Avatar asked Jul 18 '17 22:07

Bruford


2 Answers

You're using the wrong path to the images.

In the Angular project, you don't have to add the relative path from your file to image file.

Angular resolves this problem for you, and in a component, you have to only add a path to the assets folder, instead of ../../assets.

✅ This code will work:

<img src="assets/img.jpg" alt="">

⛔ and this code will not work:

<img src="../../assets/img.jpg" alt="">
like image 73
hectorromerodev Avatar answered Nov 13 '22 22:11

hectorromerodev


As it turns out, the index.html was missing a <base href="./"> - added this and the URLs resolved correctly

like image 5
Bruford Avatar answered Nov 13 '22 20:11

Bruford