Unable to get image to be shown in product release in Angular 5 using WebPack

I have an image that appears on the main page of my Angular application during development, but when I make a production version, the image does not display. I looked at other discussions ( this one looked promising, but didn't solve my problem), but still hasn't developed a solution. Any ideas what I'm doing wrong?

My image tag looks like this:

<img alt="Rocket" src="../../images/rocket.gif" />

In the production process, he derives this:

<img alt="Rocket" src="dist/0f686f4440348c6e453c282baa10b674.gif">

I really looked in my dist folder and the file exists, but it seems to be corrupted. There is another file that exists there, 5743b3dcb9db968dd0e484850845aa54.gif, which contains my image. Not sure if this will give a hint.

My webpack.config.js file looks like this:

const path = require("path");
const webpack = require("webpack");
const merge = require("webpack-merge");
const AngularCompilerPlugin = require("@ngtools/webpack").AngularCompilerPlugin;
const CheckerPlugin = require("awesome-typescript-loader").CheckerPlugin;

module.exports = (env) => {
    // Configuration in common to both client-side and server-side bundles
    const isDevBuild = !(env && env.prod);
    //const isDevBuild = false;
    const sharedConfig = {
        stats: { modules: false },
        context: __dirname,
        resolve: {
            extensions: [".ts", ".js"],
            "alias": {
                "jquery-ui":"jquery-ui-dist/jquery-ui",
                "scripts": path.resolve(__dirname, "./ClientApp/scripts"),
                "node_modules": path.resolve(__dirname,"./node_modules")
            }
        },
        output: {
            filename: "[name].js",
            publicPath: "dist/" // Webpack dev middleware, if enabled, handles requests for this URL prefix
        },
        module: {
            rules: [
                { test: /\.ts$/, include: /ClientApp/, use: ["awesome-typescript-loader?silent=true", "angular2-template-loader", "angular-router-loader"] },
                { test: /\.html$/, use: "html-loader?minimize=false" },
                { test: /\.scss$/, include: /ClientApp/, use: ["raw-loader", "sass-loader"] },
                { test: /\.css$/, use: ["to-string-loader", isDevBuild ? "css-loader" : "css-loader?minimize"] },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: "url-loader?limit=25000" }
            ]
        },
        plugins: [
            new CheckerPlugin(),
            new webpack.ProvidePlugin({
                jQuery: "jquery",
                $: "jquery",
                jquery: "jquery",
                "window.jQuery": "jquery'",
                "window.$": "jquery"
            })]
    };

    // Configuration for client-side bundle suitable for running in browsers
    const clientBundleOutputDir = "./wwwroot/dist";
    const clientBundleConfig = merge(sharedConfig, {
        entry: { "main-client": "./ClientApp/boot.browser.ts" },
        output: { path: path.join(__dirname, clientBundleOutputDir) },
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require("./wwwroot/dist/vendor-manifest.json")
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: "[file].map", // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(clientBundleOutputDir, "[resourcePath]") // Point sourcemap entries to the original file locations on disk
            })
        ] : [
                // Plugins that apply in production builds only
                new webpack.optimize.UglifyJsPlugin(),
                //new AotPlugin({
                new AngularCompilerPlugin({
                    tsConfigPath: "./tsconfig.json",
                    entryModule: path.join(__dirname, "ClientApp/app/app.module.browser#AppModule"),
                    exclude: ["./**/*.server.ts"]
                })
            ])
    });

    // Configuration for server-side (prerendering) bundle suitable for running in Node
    const serverBundleConfig = merge(sharedConfig, {
        resolve: { mainFields: ["main"] },
        entry: { "main-server": "./ClientApp/boot.server.ts" },
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require("./ClientApp/dist/vendor-manifest.json"),
                sourceType: "commonjs2",
                name: "./vendor"
            })
        ].concat(isDevBuild ? [] : [
            // Plugins that apply in production builds only
            //new AotPlugin({
            new AngularCompilerPlugin({
                tsConfigPath: "./tsconfig.json",
                entryModule: path.join(__dirname, "ClientApp/app/app.module.server#AppModule"),
                exclude: ["./**/*.browser.ts"]
            })
        ]),
        output: {
            libraryTarget: "commonjs",
            path: path.join(__dirname, "./ClientApp/dist")
        },
        target: "node",
        devtool: "inline-source-map"
    });

    return [clientBundleConfig, serverBundleConfig];
};

and my webpack.config.vendor.js file looks like this:

const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const merge = require("webpack-merge");
const treeShakableModules = [
    "@angular/animations",
    "@angular/cdk",
    "@angular/common",
    "@angular/compiler",
    "@angular/core",
    "@angular/forms",
    "@angular/http",
    "@angular/material",
    "@angular/platform-browser",
    "@angular/platform-browser-dynamic",
    "@angular/router",
    "@asymmetrik/ngx-leaflet",
    "@progress/kendo-angular-charts",
    "@progress/kendo-angular-inputs",
    "@progress/kendo-angular-intl",
    "@progress/kendo-angular-l10n",
    "@progress/kendo-drawing",
    "@progress/kendo-file-saver",
    "zone.js"
];
const nonTreeShakableModules = [
    "@progress/kendo-theme-default/dist/all.css",
    "ag-grid-angular",
    "ag-grid",
    "ag-grid-enterprise/dist/ag-grid-enterprise.js",
    "ag-grid/dist/styles/ag-grid.css",
    "ag-grid/src/styles/ag-theme-material.scss",
    "bootstrap",
    "bootstrap/dist/css/bootstrap.css",
    "es6-promise",
    "es6-shim",
    "event-source-polyfill",
    "exceljs/dist/exceljs.min.js",
    "file-saver",
    "font-awesome/css/font-awesome.css",
    "hammerjs",
    "jquery",
    "jquery-ui-dist/jquery-ui",
    "leaflet",
    "leaflet/dist/leaflet.css",
    "lodash",
    "moment",
    "ngx-bootstrap",
    "tether",
    "sheetjs",
    "xlsx",
    "./ClientApp/theme/material/js/material.js",
    "./ClientApp/theme/material/js/ripples.js",
    "./ClientApp/theme/material/css/bootstrap-material-design.css",
    "./ClientApp/theme/material/css/ripples.css"
];
const allModules = treeShakableModules.concat(nonTreeShakableModules);

module.exports = (env) => {
    const extractCSS = new ExtractTextPlugin("vendor.css");
    const isDevBuild = !(env && env.prod);
    //const isDevBuild = false;
    const sharedConfig = {
        stats: { modules: false },
        resolve: {
            extensions: [".js"]
        },
        module: {
            rules: [
                { test: /\.(png|gif|jpg|jpeg|woff|woff2|eot|ttf|svg)(\?|$)/, use: "url-loader?limit=100000" },
                { test: /\.scss$/, use: ["raw-loader", "sass-loader"] }
            ]
        },
        output: {
            publicPath: "dist/",
            filename: "[name].js",
            library: "[name]_[hash]"
        },
        plugins: [
            new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", jquery: "jquery", "window.jQuery": "jquery", "_": "lodash" }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
            new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, "./ClientApp")), // Workaround for https://github.com/angular/angular/issues/11580
            new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)esm5/, path.join(__dirname, "./ClientApp")), 
            new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, "./ClientApp")), // Workaround for https://github.com/angular/angular/issues/14898
            new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100
        ]
    };

    const clientBundleConfig = merge(sharedConfig, {
        entry: {
            // To keep development builds fast, include all vendor dependencies in the vendor bundle.
            // But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle.
            vendor: isDevBuild ? allModules : nonTreeShakableModules
        },
        output: { path: path.join(__dirname, "wwwroot", "dist") },
        module: {
            rules: [
                { test: /\.css(\?|$)/, use: extractCSS.extract({ use: isDevBuild ? "css-loader" : "css-loader?minimize" }) }
            ]
        },
        plugins: [
            extractCSS,
            new webpack.DllPlugin({
                path: path.join(__dirname, "wwwroot", "dist", "[name]-manifest.json"),
                name: "[name]_[hash]"
            })
        ].concat(isDevBuild ? [] : [
            new webpack.optimize.UglifyJsPlugin()
        ])
    });

    const serverBundleConfig = merge(sharedConfig, {
        target: "node",
        resolve: { mainFields: ["main"] },
        entry: { vendor: allModules.concat(["aspnet-prerendering"]) },
        output: {
            path: path.join(__dirname, "ClientApp", "dist"),
            libraryTarget: "commonjs2"
        },
        module: {
            rules: [{ test: /\.css(\?|$)/, use: ["to-string-loader", isDevBuild ? "css-loader" : "css-loader?minimize"] }]
        },
        plugins: [
            new webpack.DllPlugin({
                path: path.join(__dirname, "ClientApp", "dist", "[name]-manifest.json"),
                name: "[name]_[hash]"
            })
        ]
    });

    return [clientBundleConfig, serverBundleConfig];
}
+6
source share
1 answer

I solved this problem. It turns out I need to add a link to the image in the insert section without a tree in the webpack.config.vendor.js file.

I added the following line, fixed the link on the html component page, and it all worked in a published application! Fine!

"./ClientApp/images/rocket.gif"
+5
source

All Articles