9

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
      }
    })
  ]
});
Bruford
  • 471
  • 1
  • 3
  • 13

2 Answers2

17

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="">
Hectorromerodev
  • 405
  • 5
  • 9
5

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

Bruford
  • 471
  • 1
  • 3
  • 13
  • I'm having the same problem with me relative references in my templates. i.e in my login.html I've this "src="../assets/img/auth0.png"" which is not working on my electron app, as the assets folder is at the root level. Can you help me? As I don't understand your answer. Thanks! – MarBVI Sep 05 '17 at 13:09
  • @MarBVI I've updated answer, left out backticks so code wasn't display correctly! - woops – Bruford Sep 11 '17 at 17:33
  • I don't know, but I will put this post, may can help to your problem. [How to load image (and other assets) in Angular an project?](https://stackoverflow.com/questions/42793292/how-to-load-image-and-other-assets-in-angular-an-project) – Hectorromerodev Dec 04 '20 at 00:16
  • If you do not want to change the href in the index.html file, you may use the following while building your app `ng build --base-href ./ --configuration=production` – Raphaël Balet Jun 21 '21 at 17:31