Alex
Alex

Reputation: 1029

Can't load static image with Angular2 and webpack

Usually I'm backend developer but started learn frontend stuff. I made example app from Angular tutorial and trying to build my own small app now.

I stuck with simple problem - when I'm trying to load static image (ex. logo) it returns me 404 error code. Looks like I missed something in configuration and I have no idea what it can be.


Code for load image:

<img src="images/logo.png" alt="Logo" width="48" height="48"/>

Structure:

web
- app
-- assets
-- images
-- js
-- model
-- stylesheets
-- *.ts
-- *.html
-- *.css
-- main.ts
-- polyfills.ts
-- rxjs-extensions.ts
-- vendor.ts
- config
- dist
- index.html
- packages.json
- tsconfig.json
- typings.json
- webpack.config.js

package.json

{
  "name": "angular2-webpack",
  "version": "1.0.0",
  "description": "A webpack starter for Angular",
  "scripts": {
    "start": "webpack-dev-server --display-error-details --inline --progress --port 8080",
    "test": "karma start",
    "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",
    "postinstall": "typings install"
  },
  "license": "MIT",
  "dependencies": {
    "@angular/common": "2.0.1",
    "@angular/compiler": "2.0.1",
    "@angular/core": "2.0.1",
    "@angular/forms": "2.0.1",
    "@angular/http": "2.0.1",
    "@angular/platform-browser": "2.0.1",
    "@angular/platform-browser-dynamic": "2.0.1",
    "@angular/router": "3.0.0",
    "core-js": "^2.4.1",
    "rxjs": "5.0.0-beta.12",
    "zone.js": "^0.6.23",
    "assets-webpack-plugin": "^3.4.0"
  },
  "devDependencies": {
    "angular2-template-loader": "^0.4.0",
    "awesome-typescript-loader": "^2.2.4",
    "css-loader": "^0.23.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.8.5",
    "html-loader": "^0.4.3",
    "html-webpack-plugin": "^2.15.0",
    "jasmine-core": "^2.4.1",
    "karma": "^1.2.0",
    "karma-jasmine": "^1.0.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^1.8.0",
    "null-loader": "^0.1.1",
    "phantomjs-prebuilt": "^2.1.7",
    "raw-loader": "^0.5.1",
    "rimraf": "^2.5.2",
    "style-loader": "^0.13.1",
    "typescript": "^2.0.2",
    "typings": "^1.3.2",
    "webpack": "^1.13.0",
    "webpack-dev-server": "^1.14.1",
    "webpack-merge": "^0.14.0",
    "copy-webpack-plugin": "^3.0.1"
  }
}

config/webpack.common.js

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

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

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

    module: {
        loaders: [
            {
                test: /\.(png|jpg|jpeg|gif|svg|ico)$/,
                loader: 'file'
            },
            {
                test: /\.ts$/,
                loaders: ['awesome-typescript-loader', 'angular2-template-loader']
            },
            {
                test: /\.html$/,
                loader: 'html'
            },
            {
                test: /\.css$/,
                exclude: helpers.root('app'),
                loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
            },
            {
                test: /\.css$/,
                include: helpers.root('app'),
                loader: 'raw'
            }
        ]
    },

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

        new HtmlWebpackPlugin({
            template: 'index.html',
            inject: 'body'
        }),
    ]
};

webpack.dev.js

var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');

const webpack = require('webpack');

const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');

module.exports = webpackMerge(commonConfig, {
    devtool: 'cheap-module-eval-source-map',

    debug: true,

    output: {
        path: helpers.root('app'),
        publicPath: '/',
        filename: '[name].js',
        chunkFilename: '[id].chunk.js'
    },

    plugins: [
        new ExtractTextPlugin('[name].css')
    ],

    devServer: {
        historyApiFallback: true,
        stats: 'minimal'
    }
});

index.html

<html>
<head>
    <base href="/">
    <title>Angular QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
<catalog-root>Loading...</catalog-root>

</body>
</html>

Upvotes: 3

Views: 7014

Answers (3)

Ashkan R. Nejad
Ashkan R. Nejad

Reputation: 164

Try keeping you images in "assets" folder in the "src" folser of your angular app. then try to open in using assets/myImage.jpg in the HTML and /src/assets/myImage.jpg in the CSS

Upvotes: 0

Edmar Miyake
Edmar Miyake

Reputation: 12390

Add a / before images. All the paths will be relative to root, since your SPA is index.html located in root, I assume.

If not, add your base url in <head>

<base href="<%= webpackConfig.metadata.baseUrl %>">

Also, check if your are copying your assets correctly in your webpack:

const CopyWebpackPlugin = require('copy-webpack-plugin');

plugins[
  ...,
  new CopyWebpackPlugin([{
    from: 'app/images',
    to: './images'
  }]);
];

Upvotes: 3

snorkpete
snorkpete

Reputation: 14574

Try using a relative path. So eg if in main.ts:

<img src="./images/logo.png" alt="Logo" width="48" height="48"/>

Upvotes: 1

Related Questions