Home > Enterprise >  @fluentui/icons not showing in page
@fluentui/icons not showing in page

Time:11-24

recently I cleaned up the webpack configuration in a project in order to make it more maintainable, I did so by splitting the configuration in two files:

// webpack.config.js
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const { merge } = require("webpack-merge");
const parts = require("./webpack.parts");

const commonConfig = merge([
  {
    target: "web",
    stats: {
      optimizationBailout: true,
    },
    entry: {
      index: {
        import: parts.rootResolverFn("src/index/main.js"),
        dependOn: "vendors",
      },
      vendors: ["react", "react-dom", "prop-types"],
    },
    output: {
      filename: "[name].[contenthash].js",
      path: parts.rootResolverFn("dist/public"),
      publicPath: "/",
      clean: true,
    },
    resolve: parts.resolve(),
  },
  parts.plugins(),
  parts.loadJs(),
  parts.loadAssets(),
  parts.loadCss(),
  parts.bundleAnalyzer(),
]);

const developmentConfig = merge([
  {
    output: {
      filename: "[name].bundle.js",
      pathinfo: false,
    },
    devtool: "eval-source-map",
    devServer: parts.devServer(),
    plugins: [new ReactRefreshWebpackPlugin()],
  },
]);

const productionConfig = merge([
  {
    optimization: {
      splitChunks: { chunks: "all" },
      runtimeChunk: { name: "runtime" },
      usedExports: true,
      sideEffects: true,
      minimizer: [
        `...`,
        new CssMinimizerPlugin({
          minimizerOptions: {
            preset: [
              "default",
              {
                discardComments: { removeAll: true },
              },
            ],
          },
        }),
      ],
    },
  },
]);

module.exports = (env, { mode }) => {
  switch (mode) {
    case "production":
      return merge(commonConfig, productionConfig);
    case "development":
      return merge(commonConfig, developmentConfig);
    default:
      throw new Error(`Trying to use unknown mode: ${mode}`);
  }
};

And the other file:

// webpack.parts.js
const path = require("path");
const { spawnSync } = require("child_process");
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const pkg = require("./package.json");

const root = path.join(__dirname, "./");

const pathResolver = (base) => (toResolve) => path.resolve(base, toResolve);
const rootResolver = pathResolver(root);

const isProd = process.env.NODE_ENV === "production";

let commitHash;
if (!isProd) {
  try {
    const { stdout } = spawnSync("git", ["rev-parse", "--short", "HEAD"]);
    console.log(`Current commit is: ${String(stdout)}`);
    commitHash = String(stdout);
  } catch (e) {
    console.warn("Could not retrieve hash for this development environment, is this a valid git repository?");
  }
}

const copyPluginPatterns = [
  {
    from: rootResolver("src/assets"),
    to: rootResolver("dist/public/assets"),
  },
  {
    from: rootResolver("node_modules/mxgraph/javascript"),
    to: rootResolver("dist/public/mxgraph"),
  },
  {
    from: rootResolver("src/config.js"),
    to: rootResolver("dist/public/"),
  },
];

exports.rootResolverFn = (path) => rootResolver(path);

exports.devServer = () => ({
  port: 8282,
  hot: true,
  historyApiFallback: true,
  open: true,
  client: {
    overlay: true,
  },
});

exports.resolve = () => ({
  alias: {
    api: rootResolver("src"),
    components: rootResolver("src/components"),
    shared: rootResolver("src/shared"),
  },
  extensions: ["*", ".js", ".jsx", ".json", ".mjs", ".es"],
  modules: [path.resolve(root), path.resolve(root, "src"), path.resolve(root, "node_modules")],
  symlinks: false,
});

exports.loadAssets = () => ({
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/,
        type: "asset/resource",
      },
      {
        test: /\.(svg)$/,
        type: "asset/inline",
      },
    ],
  },
});

exports.loadJs = () => ({
  module: {
    rules: [
      {
        test: /\.m?(js|jsx)$/,
        exclude: /(node_modules)/,
        use: {
          loader: "babel-loader",
          options: {
            plugins: [!isProd && require.resolve("react-refresh/babel")].filter(Boolean),
          },
        },
      },
    ],
  },
});

exports.loadCss = () => ({
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              sourceMap: true,
              url: false,
            },
          },
          "fast-sass-loader",
          "postcss-loader",
        ],
      },
    ],
  },
});

exports.plugins = () => {
  return {
    plugins: [
      new MiniCssExtractPlugin({
        ignoreOrder: true,
        filename: "[name].[contenthash].css",
      }),
      new CopyPlugin({
        patterns: copyPluginPatterns,
      }),
      new webpack.DefinePlugin({
        ENV: JSON.stringify(process.env.NODE_ENV || "development"),
        VERSION: JSON.stringify(pkg.version),
        TEST_MODE: JSON.stringify(process.env.TEST_MODE),
        COMMIT_SHA: process.env.COMMIT_SHA || commitHash,
      }),
      new HtmlWebpackPlugin({
        title: "MyApp",
        meta: {
          charset: "utf-8",
          viewport: "width=device-width, initial-scale=1",
        },
        template: rootResolver("src/index/index.html"),
        hash: true,
        chunks: ["index", "vendors"],
        minify: {
          collapseWhitespace: false,
        },
      }),
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment$/,
      }),
    ],
  };
};

exports.bundleAnalyzer = (options = {}) => ({
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerHost: "localhost",
      analyzerPort: "2112",
      ...options,
    }),
  ],
});

After applying these changes the icons from @fluentui/font-icons-mdl2 stopped showing correctly as in the following picture:

broken fluentui icons

I'm using the recommended approach in the webpack bundle analyzer output

The curious thing for me is that by inspecting the Network tab in DevTools I can see the calls to retrieve the fonts and they're successful

dev tools output

However, as you could see a couple of images above the glyphs are not show correctly.

Has someone experienced similar issues with @fluentui/font-icons-mdl2 and webpack recently? Thanks in advance.

CodePudding user response:

Well, I was able to figure out the problem, the problematic lines were:

splitChunks: { chunks: "all" },
runtimeChunk: { name: "runtime" },

After removing those lines the icons started to show up again as expected. I'll close this but I have the task to figure out exactly why that happened, that being said, webpack is a terrific tool but you should really take your time and read the documentation very carefully. Cheers

  • Related