Home > Back-end >  How to exclude link tags (or more specifically .css files extracted by the mini-css-extract-plugin)
How to exclude link tags (or more specifically .css files extracted by the mini-css-extract-plugin)

Time:10-27

Due to how the (legacy) project is currently set up, I cannot benefit from the caching capabilities of webpack in the standard way, but instead have to generate the scripts in empty files (like main.html5 example) and include those in the project's head or body.

That works just fine with the config I currently have but I find myself lacking the capability to reference the main.[hash].js and main.[hash].css extracted by mini-css-extract-plugin in seperate ejs files so that i could include each generated html5 in different locations of my html5 template (link tag in head and script in body).

webpack.common.js :

module.exports = {
  entry: {
    main: path.resolve(__dirname, "./react/src/Index.js"),
    styles: path.resolve(__dirname, "./react/src/Styles.js"),
    vendor: path.resolve(__dirname, "./react/src/Vendor.js"),
  },
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[name].[contenthash].js",
    assetModuleFilename: "images/[hash][ext][query]",
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "./react/main.ejs"),
      filename: "main.html5",
      inject: false,
      publicPath: "/dist/",
      chunks: ["main"], // would be great to only reference .js here, then create another instance for .css
    }),
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
    }),
  ],

main.ejs only has :

<%= htmlWebpackPlugin.tags.headTags %>

Generated main.html5 file :

<script defer="" src="/dist/main.534ca9564003f8d93251.js"></script><link href="/dist/main.0864e3dfa0f6edc21e68.css" rel="stylesheet">

Then i include main.html5 into my project's template like so:

<body>
// ---- html code goes here
        <?php include_once 'dist/main.html5'; ?> 
</body>

The problem is that this loads both tags at the end of the body tag whereas i would like to include the css in the head tags.So Ideally, I would have 2 html5 files generated. One containing script tag and the other the link tag. I have read the documentation for webpack but fail to see any possible solution that would work for my case. If i could exclude tags from the ejs file that could be a solution but i fail to find anything about that in the HtmlWebpackPlugin Documentation.

CodePudding user response:

So, I found out about html-webpack-exclude-assets-plugin which is doing exactly what i want but unfortunately it is not working and has not been updated for about 5 years. Thankfully, there is an alternative with html-webpack-skip-assets-plugin. Here is how I use it :

webpack.common.js :

const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackSkipAssetsPlugin =
  require("html-webpack-skip-assets-plugin").HtmlWebpackSkipAssetsPlugin;

    module.exports = {
      entry: {
        main: path.resolve(__dirname, "./react/src/Index.js"),
      },
      output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "[name].[contenthash].js",
        assetModuleFilename: "images/[hash][ext][query]",
      },
  optimization: {
    minimizer: [`...`, new CssMinimizerPlugin()],
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    },
  },
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "./react/vendor.ejs"),
          filename: "vendor.html5",
          inject: false,
          publicPath: "/dist/",
          chunks: ["vendor"],
          excludeAssets: [
            /\/dist\/styles.*.css/,
            (asset) => asset.attributes && asset.attributes["x-skip"],
          ],
        }),
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "./react/styles.ejs"),
          filename: "styles.html5",
          inject: false,
          publicPath: "/dist/",
          chunks: ["main"],
          // excludeAssets: [/\.css$/i]
          excludeAssets: [
            /\/dist\/main.*.js/,
            (asset) => asset.attributes && asset.attributes["x-skip"],
          ],
        }),
        new MiniCssExtractPlugin({
          filename: "[name].[contenthash].css",
        }),    
        new HtmlWebpackSkipAssetsPlugin(),

      ],
module: {
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    use: ["babel-loader"],
  },
  {
    test: /\.css$/i,
    exclude: /node_modules/,
    use: [MiniCssExtractPlugin.loader, "css-loader"],
  },
  {
    test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
    type: "asset/resource", //* less performance heavy than asset/inline
  },
  {
    test: /\.(woff(2)?|eot|ttf|otf|svg)$/i,
    type: "asset/inline", //* only for small assets. if webpack complains about asset size limit, change to asset/ressource type or asset. Had these as inline before (woff(2)?|eot|ttf|otf|svg),
  },
],
  },

There you go, we can now generate the css link tag in an html file of its own and include it wherever needed in our project's .html5 template.

  • Related