Favicon Doesn't Appear in Search Engines

18 Views Asked by At

I believe there is some wrong or missing configuration in Webpack 5, notice that when injecting the goals and links, it gives me duplicate the "image/x-icon" and generates other "rel=icon" that I don't know if they are correct:

DOM IMAGE

WEBPACK 5 CODE:

const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlFaviconsWebpackPlugin = require("favicons-webpack-plugin");
const HtmlCSPWebpackPlugin = require("csp-html-webpack-plugin");
const HtmlScriptExtWebpackPlugin = require("script-ext-html-webpack-plugin");

const AutoPrefixer = require("autoprefixer");
const BrowserslistPlugin = require("browserslist");
const YAML = require("yamljs");

const GLOB = require("glob");
const LIGHTNING_CSS_PLUGIN = require("lightningcss");
const PATH = require("path");
const PACKAGE_JSON = require("./package.json");

const IS_DEV_MODE = process.env.WEBPACK_SERVE;

const SITE_INFORMATION = {
    VERSION: PACKAGE_JSON.version,
    AUTHOR: PACKAGE_JSON.author.name,
    DESCRIPTION: PACKAGE_JSON.description,
    KEYWORDS: `${PACKAGE_JSON.keywords}`,
    THEME_COLOR: "#212529",
    BACKGROUND_COLOR: "#212529",
    TITLE: {
        MAIN: "THIAGO SAUD DEVELOPER | Take your business to the next level!",
        PWA: { LARGE: "THIAGO SAUD DEVELOPER", SHORT: "TS DEVELOPER" },
    },
    URL: {
        MAIN: PACKAGE_JSON.author.url,
        BANNER: "https://raw.githubusercontent.com/thiagosauddev/thiagosauddev/main/images/banner.png",
    },
};

const getHTMLWebpackPlugin = filename => ({
    filename,
    template: PATH.resolve(__dirname, `src/pages/${filename}`),
    chunks: "all",
    minify: true,
    cache: true,
    meta: {
        charset: "UTF-8",
        viewport: "width=device-width, initial-scale=1.0",
        canonical: SITE_INFORMATION.URL.MAIN,
        author: SITE_INFORMATION.AUTHOR,
        description: SITE_INFORMATION.DESCRIPTION,
        keywords: SITE_INFORMATION.KEYWORDS,
        robots: "index, follow",
        googlebot: "index, follow",
        "og:locale": "en_US",
        "og:type": "website",
        "og:url": SITE_INFORMATION.URL.MAIN,
        "og:title": SITE_INFORMATION.TITLE.MAIN,
        "og:site_name": SITE_INFORMATION.TITLE.MAIN,
        "og:description": SITE_INFORMATION.DESCRIPTION,
        "og:image": SITE_INFORMATION.URL.BANNER,
        "twitter:card": "summary_large_image",
        "twitter:url": SITE_INFORMATION.URL,
        "twitter:title": SITE_INFORMATION.TITLE.MAIN,
        "twitter:description": SITE_INFORMATION.DESCRIPTION,
        "twitter:image": SITE_INFORMATION.URL.BANNER,
        "twitter:image:alt": SITE_INFORMATION.TITLE.MAIN,
        "theme-color": SITE_INFORMATION.THEME_COLOR,
        "msapplication-TileColor": SITE_INFORMATION.THEME_COLOR,
    },
});

module.exports = {
    mode: "development",
    entry: "./src/index.js",
    target: "web",
    stats: {
        loggingDebug: ["sass-loader"],
    },
    devServer: {
        static: PATH.resolve(__dirname, "dist"),
        port: 3000,
        open: false,
        hot: false,
        liveReload: true,
    },
    plugins: [
        new HtmlWebpackPlugin(getHTMLWebpackPlugin("index.html")),
        new HtmlWebpackPlugin(getHTMLWebpackPlugin("404.html")),
        new HtmlScriptExtWebpackPlugin({
            defaultAttribute: "defer",
            preload: {
                test: /\.js$/,
                chunks: "all",
            },
            prefetch: {
                test: /\.js$/,
                chunks: "all",
            },
        }),
        new HtmlFaviconsWebpackPlugin({
            inject: true,
            mode: "webapp",
            devMode: "webapp",
            publicPath: "static",
            outputPath: "static/assets",
            logo: PATH.resolve(__dirname, "src/assets/images/logotype.webp"),
            logoMaskable: PATH.resolve(__dirname, "src/assets/images/logotype-maskable.webp"),
            manifest: { id: "/" },
            favicons: {
                start_url: "/",
                orientation: "portrait",
                display: "standalone",
                manifestMaskable: true,
                version: SITE_INFORMATION.VERSION,
                appName: SITE_INFORMATION.TITLE.PWA.LARGE,
                appShortName: SITE_INFORMATION.TITLE.PWA.SHORT,
                appDescription: SITE_INFORMATION.DESCRIPTION,
                developerName: SITE_INFORMATION.AUTHOR,
                developerURL: SITE_INFORMATION.URL,
                theme_color: SITE_INFORMATION.THEME_COLOR,
                background: SITE_INFORMATION.BACKGROUND_COLOR,
            },
        }),
        new HtmlCSPWebpackPlugin(
            {
                "default-src": "'self'",
                "base-uri": "'self'",
                "connect-src": ["'self'", "*.google-analytics.com"],
                "font-src": "'self'",
                "frame-src": "'none'",
                "img-src": ["'self'", "*.google-analytics.com"],
                "manifest-src": "'self'",
                "media-src": "'none'",
                "object-src": "'none'",
                "style-src": "'self'",
                "script-src": ["'self'", "'unsafe-eval'", "*.google-analytics.com"],
            },
            {
                enabled: true,
                hashingMethod: "sha256",
                hashEnabled: {
                    "script-src": true,
                    "style-src": true,
                },
                nonceEnabled: {
                    "script-src": true,
                    "style-src": true,
                },
            }
        ),
        new MiniCssExtractPlugin({
            filename: "static/css/[name].[contenthash:8].css",
            chunkFilename: "static/css/[id].[contenthash:8].chunk.css",
        }),
        new PurgeCSSPlugin({
            paths: GLOB.sync(`${PATH.join(__dirname, "src")}/**/*`, { nodir: true }),
            only: ["bundle", "vendor"],
        }),
        new CopyPlugin({
            patterns: [
                {
                    from: PATH.resolve(__dirname, "src/robots.txt"),
                    to: PATH.resolve(__dirname, "dist"),
                    context: "*.txt",
                },
                {
                    from: PATH.resolve(__dirname, "src/assets/images/favicon.ico"),
                    to: PATH.resolve(__dirname, "dist"),
                    context: "*.ico",
                },
            ],
        }),
    ],
    resolve: {
        alias: {
            "@": PATH.resolve(__dirname, "src"),
            "@assets": PATH.resolve(__dirname, "src", "assets"),
            "@pages": PATH.resolve(__dirname, "src", "pages"),
            "@scripts": PATH.resolve(__dirname, "src", "scripts"),
            "@scss": PATH.resolve(__dirname, "src", "scss"),
        },
    },
    output: {
        clean: !IS_DEV_MODE,
        path: PATH.resolve(__dirname, "dist"),
        filename: "static/js/[name].[contenthash:8].js",
        chunkFilename: "static/js/[id].[chunkhash:8].chunk.js",
        assetModuleFilename: "static/assets/[name].[contenthash:8][ext]",
    },
    optimization: {
        moduleIds: "deterministic",
        runtimeChunk: "single",
        splitChunks: {
            chunks: "all",
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: "vendors",
                    chunks: "all",
                },
                styles: {
                    name: "styles",
                    test: /\.css$/,
                    chunks: "all",
                    enforce: true,
                },
            },
        },
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin({
                parallel: true,
                minify: CssMinimizerPlugin.lightningCssMinify,
                minimizerOptions: {
                    targets: LIGHTNING_CSS_PLUGIN.browserslistToTargets(new BrowserslistPlugin(">= 0.25%")),
                },
            }),
            new TerserPlugin({
                test: /\.js(\?.*)?$/i,
                parallel: true,
                terserOptions: {
                    ecma: 8,
                    mangle: { safari10: true },
                    compress: {
                        ecma: 5,
                        inline: 2,
                        toplevel: true,
                        comparisons: false,
                        dead_code: true,
                        unused: true,
                        join_vars: true,
                        warnings: !IS_DEV_MODE,
                        drop_console: !IS_DEV_MODE,
                        drop_debugger: !IS_DEV_MODE,
                    },
                },
            }),
            new ImageMinimizerPlugin({
                minimizer: {
                    implementation: ImageMinimizerPlugin.sharpMinify,
                    options: {
                        quality: 100,
                        encodeOptions: {
                            webp: {
                                lossless: true,
                            },
                        },
                    },
                },
            }),
        ],
    },
    module: {
        strictExportPresence: true,
        rules: [
            {
                test: /\.(ttf)$/i,
                type: "asset/resource",
            },
            {
                test: /\.(webp|ico)$/i,
                type: "asset/resource",
            },
            {
                test: /\.yaml$/i,
                type: "json",
                parser: {
                    parse: YAML.parse,
                },
            },
            {
                test: /\.html$/i,
                loader: "html-loader",
            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: "babel-loader",
                    options: {
                        cacheDirectory: true,
                        cacheCompression: true,
                        presets: ["@babel/preset-env"],
                        plugins: ["@babel/plugin-transform-runtime"],
                    },
                },
            },
            {
                test: /\.(sa|sc|c)ss$/i,
                use: [
                    { loader: MiniCssExtractPlugin.loader },
                    { loader: "css-loader" },
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: { plugins: () => [AutoPrefixer()] },
                        },
                    },
                    { loader: "resolve-url-loader" },
                    {
                        loader: "sass-loader",
                        options: {
                            sourceMap: true,
                        },
                    },
                ],
            },
        ],
    },
};

Is there actually a problem with my code above? Is the duplicate image/x-icon meta that Webpack generates the cause of the problem? How to fix this problem?

0

There are 0 best solutions below