1

when we update our code for angular 12, we have an issue with webpack-dev-server (prod works ok) with the images src on HTML. e.g: please see example for the image src here

<div class="hbox logo-wrapper">
        <i class="fas fa-bars mx-3 cursor-pointer" (click)="onMenuClick($event)"></i>
        <img src="../assets/images/white-logo.svg"
             class="cursor-pointer"
             (click)="onLogoClick()">
        <span class="mx-3">|</span>
        <i class="fas fa-home cursor-pointer"
           (click)="onHomeButtonClick()"
           ngbTooltip="Portal Home"></i>
  </div>

this code belongs to some component in our angular project. we are not using the angular CLI but running our webpack build command :

node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js

currently, when running the local build - the application runs ok but the image is not loaded, I mean webpack cant find it at http://localhost:4200/assets/images/white-logo.svg - return 404.

enter image description here

everything works great with angular 11.2, since the change to 12, we have this issue, I think we are missing something or some definition needs to be changed.

this is our webpack config (for dev).

const path = require('path');
const packageJsonVersion = require('./package.json').version;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const rxPaths = require('rxjs/_esm5/path-mapping');
const buildGuid = Math.floor((1 + Math.random()) * 0x10000000000).toString(16).substring(1);
const { SourceMapDevToolPlugin, DefinePlugin } = require('webpack');
const { BaseHrefWebpackPlugin } = require('base-href-webpack-plugin');
const { AngularWebpackPlugin} = require('@ngtools/webpack');
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); // Uncomment it below for build monitoring

const entryPoints = ["inline", "polyfills", "sw-register", "styles", "vendor", "main"];
const env = process.env.NODE_ENV || 'development';
const userName = process.env.USER || process.env.USERNAME;
const projectRoot = process.cwd();
const copyWebpackPluginIgnoreList = ["**/.gitkeep", "**/.DS_Store", "**/Thumbs.db"];

module.exports = {
    performance: {
        hints: false,
        maxAssetSize: 100000
    },
    "mode": "development",
    "devtool": false,
    "resolve": {
        "extensions": [
            ".ts",
            ".js",
            ".es6"
        ],
        "symlinks": true,
        "modules": [
            "./src",
            "./node_modules"
        ],
        "alias": rxPaths(),
        "mainFields": [
            "browser",
            "module",
            "main"
        ],
        "fallback": {
            "stream": require.resolve("stream-browserify")
        }
    },
    "resolveLoader": {
        "modules": [
            "./node_modules",
            "./node_modules/@angular/cli/node_modules"
        ],
        "alias": rxPaths()
    },
    "entry": {
        "main": [
            "./src/main.ts"
        ],
        "polyfills": [
            "./src/polyfills.ts"
        ]
    },
    "output": {
        "path": path.join(process.cwd(), "dist"),
        "filename": "[name].[chunkhash:20].bundle.js",
        "chunkFilename": "[id].chunk.js",
        "crossOriginLoading": false
    },
    "module": {
        "rules": [
            {
                test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/,
                parser: { system: true },  // enable SystemJS
            },
            {
                "test": /\.html$/,
                "loader": "html-loader",
                options: {
                    esModule: false,
                    sources: {
                        list: [
                            // All default supported tags and attributes
                            '...',
                            {
                                tag: 'link',
                                attribute: 'href',
                                type: 'src',
                                filter: (tag, attribute, attributes, resourcePath) => {
                                    if (/index\.html$/.test(resourcePath)) {
                                        return false;
                                    }
                                    return true;
                                }
                            }
                        ],
                    },
                },
            },
            {
                "test": /\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani|eot|svg|cur|webm)$/,
                "loader": "file-loader",
                "options": {
                    "name": "assets/[name].[hash:20].[ext]",
                    "limit": 10000
                }
            },
            {
                "include": [
                    path.join(process.cwd(), "src/assets")
                ],
                test: /\.scss$/,
                use: [
                    { loader: 'style-loader', options: { esModule: false } },
                    { loader: 'css-loader', options: { sourceMap: true, esModule: false } },
                    { loader: "resolve-url-loader" },
                    { loader: 'sass-loader', options: { sourceMap: true } }
                ],
            },
            {
                "include": [
                    path.join(process.cwd(), "src/app")
                ],
                test: /\.scss$/,
                use: [
                    'to-string-loader',
                    { loader: 'css-loader', options: { sourceMap: true, esModule: false } },
                    { loader: "resolve-url-loader" },
                    { loader: 'sass-loader', options: { sourceMap: true } }
                ]
            },
            {
                "test": /\.ts$/,
                "loader": "@ngtools/webpack"
            }
        ]
    },
    "plugins": [
        new CopyWebpackPlugin({
            patterns: [
                {
                    context: "public",
                    to: "",
                    from: "assets/**/*",
                    globOptions: {
                        dot: true,
                        ignore: copyWebpackPluginIgnoreList
                    },
                    info: { minimized: true }
                }
            ]
        }),
        new ProgressPlugin(),
        new CircularDependencyPlugin({
            "exclude": /node_modules/,
            "failOnError": false,
            "onDetected": false,
            "cwd": projectRoot
        }),
        new HtmlWebpackPlugin({
            "template": "./src/index.html",
            "filename": "./index.html",
            "hash": false,
            "inject": true,
            "compile": true,
            "favicon": false,
            "minify": false,
            "cache": true,
            "showErrors": true,
            "excludeChunks": [],
            "title": "Webpack App",
            "xhtml": true,
            "chunksSortMode": function sort(left, right) {
                let leftIndex = entryPoints.indexOf(left);
                let rightIndex = entryPoints.indexOf(right);
                if (leftIndex > rightIndex) {
                    return 1;
                } else if (leftIndex < rightIndex) {
                    return -1;
                } else {
                    return 0;
                }
            }
        }),
        new BaseHrefWebpackPlugin({}),
        new SourceMapDevToolPlugin({
            "filename": "[file].map[query]",
            "moduleFilenameTemplate": "[resource-path]",
            "fallbackModuleFilenameTemplate": "[resource-path]?[hash]",
            "sourceRoot": "webpack:///"
        }),
        new AngularWebpackPlugin({
            "fileReplacements": {
                "environments/environment.ts": "environments/environment.ts"
            },
            "tsconfig": "src/tsconfig.app.json",
            "compilerOptions": {}
        }),
        new DefinePlugin({
            TEST_ENVIRONMENT: env === 'test',
            ENVIRONMENT: JSON.stringify(env),
            MACHINENAME: JSON.stringify(userName),
            BUILD_GUID: JSON.stringify(buildGuid),
            PORTAL_VERSION: JSON.stringify(packageJsonVersion)
        }),
        new CleanWebpackPlugin(),
        // new BundleAnalyzerPlugin(),
    ],
    optimization: {
        moduleIds: 'named',
        emitOnErrors: false
    },
    node: {
        "global": true
    },
    devServer: {
        port: 4200,
        host: "0.0.0.0",
        hot: false,
        historyApiFallback: true,
        proxy: {
            "*": "http://localhost:3000"
        },
        static: [
            {
                watch: false
            }
        ],
        firewall: false
    }
};

would appreciate if someone could suggest to us what could possibly go wrong here.

relevant packages versions:

"webpack-dev-server": "4.0.0-beta.2"
"webpack": "5.24.0",
"webpack-cli": "4.7.2",
"css-loader": "6.2.0"
"style-loader": "3.2.1"
"html-webpack-plugin": "^5.1.0"
"@ngtools/webpack": "12.2.0"

and all other angular packages with version 12.2.0

thanks

spinker
  • 298
  • 4
  • 20
  • remove the ../ your image path in angular your absolute path should be assets/ or /assets/. this is just a path issue - angular gets a little sketchy with import paths of images. I've fought with this many times. try the simple before getting too much into the much of angular and web pack. – chris burd Aug 06 '21 at 11:56
  • i tried both options you offer : `src="assets/images/white-logo.svg"` and `src="/assets/images/white-logo.svg"` and still the same problem – spinker Aug 06 '21 at 13:05
  • Did you find the solution? – Diego Sep 30 '21 at 10:05
  • hi @Diego yes i did this config in the new AngularWebpackPlugin : `"jitMode": true, "directTemplateLoading": false` and then it worked for me – spinker Sep 30 '21 at 17:05

0 Answers0