jantimon/html-webpack-plugin

File does not render correctly / cannot get variable from options

mateusz-grek opened this issue ยท 3 comments

Current behaviour ๐Ÿ’ฃ

I currently have the following file structure: emodelle.html located in the de folder takes the element from de/components/02_footer_section/index.html and injects its contents into itself.

de/emodelle.html
de/components/02_footer_section/index.html
de/emodelle.html

   DATA FROM FOOTER:
  <%= require('html-loader!./components/02_footer_section/index.html').default %>

   DATA STRAIGHT FROM EMODELLE:
  <%= htmlWebpackPlugin.options.newVariable %>

</main>

de/components/02_footer_section/index.html

    <%= htmlWebpackPlugin.options.newVariable %>
</div>

This dynamic variable newVariable comes from webpack.config.js

const htmlPluginEntries = templateFiles.map((template) => new HTMLWebpackPlugin({
  inject: true,
  hash: false,
  filename: template.output,
  template: path.resolve(environment.paths.source, template.input),
  favicon: path.resolve(environment.paths.source, 'images', 'favicon.ico'),
  newVariable: 'New Variable test'
}));

Webpack.config.js

/**
 * Webpack main configuration file
 */

const path = require('path');
const fs = require('fs');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const SitemapPlugin = require('sitemap-webpack-plugin').default;
const Glob = require('glob');

let filesToIncludeArr = [];
let filesToIncludeArrSitemap = [];
const filesToInclude = Glob.sync('src/**/*.html').map(function(file) {

  
    filesToIncludeArr.push(file.replace('src/', ''));
    filesToIncludeArrSitemap.push(file.replace('src/', '').replace('.html', '').replace('index', ''));
  
  
  // filesToIncludeArr[entryKey] = file;
})
console.log(filesToIncludeArr);

// Example of simple string paths
const paths = filesToIncludeArrSitemap;

const environment = require('./configuration/environment');

const templateFiles = filesToIncludeArr
  .filter((file) => ['.html', '.ejs'].includes(path.extname(file).toLowerCase())).map((filename) => ({
    input: filename,
    output: filename.replace(/\.ejs$/, '.html'),
}));

const htmlPluginEntries = templateFiles.map((template) => new HTMLWebpackPlugin({
  inject: true,
  hash: false,
  filename: template.output,
  template: path.resolve(environment.paths.source, template.input),
  favicon: path.resolve(environment.paths.source, 'images', 'favicon.ico'),
  newVariable: 'New Variable test'
}));


module.exports = {
  entry: {
    app: path.resolve(environment.paths.source, 'js', 'app.js'),
  },
  output: {
    filename: 'js/[name].js',
    path: environment.paths.output,
  },
  module: {
    rules: [
      {
        test: /\.((c|sa|sc)ss)$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.(png|gif|jpe?g|svg|webp)$/i,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: environment.limits.images,
          },
        },
        generator: {
          filename: 'images/design/[name].[hash:6][ext]',
        },
      },
      {
        test: /\.(eot|ttf|woff|woff2)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: environment.limits.images,
          },
        },
        generator: {
          filename: 'images/design/[name].[hash:6][ext]',
        },
      },
      
    ],
  },
  optimization: {
    minimizer: [
      '...',
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            // Lossless optimization with custom option
            // Feel free to experiment with options for better result for you
            plugins: [
              ['gifsicle', { interlaced: true }],
              ['jpegtran', { progressive: true }],
              ['optipng', { optimizationLevel: 5 }],
              // Svgo configuration here https://github.com/svg/svgo#configuration
              [
                'svgo',
                {
                  plugins: [
                    {
                      name: 'removeViewBox',
                      active: false,
                    },
                  ],
                },
              ],
            ],
          },
        },
      }),
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
    new CleanWebpackPlugin({
      verbose: true,
      cleanOnceBeforeBuildPatterns: ['**/*', '!stats.json'],
    }),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: path.resolve(environment.paths.source, 'images', 'content'),
          to: path.resolve(environment.paths.output, 'images', 'content'),
          toType: 'dir',
          globOptions: {
            ignore: ['*.DS_Store', 'Thumbs.db'],
          },
        },
        { from: "src/.htaccess"},
        { from: "src/robots.txt"},
        {
          from: path.resolve(environment.paths.source, 'videos'),
          to: path.resolve(environment.paths.output, 'videos'),
          toType: 'dir',
          globOptions: {
            ignore: ['*.DS_Store', 'Thumbs.db'],
          },
        },
      ],
    }),
    new SitemapPlugin({
      base: 'https://citroenist-mag.ch/',
      paths,
      options: {
        filename: 'sitemap.xml'
      }
    })
    
  ].concat(htmlPluginEntries),
  target: 'web',
};

Expected behaviour โ˜€๏ธ

When using the npm run dev command, the newVariable variable appears correctly from emodelle.html, but not from footer, but when I go directly to the footer file in the browser, I see the rendered variable.

It seems that when compiling, webpack only renders emodelle and takes its variables, while from footer it does not render anything, it only shows pure html as a string in emodelle.html

GOAL TO ACHIEVE

I would like to be able to add dynamic variables to the file de/components/02_footer_section/index.html which will then be rendered when compiling to emodelle.html

Reproduction Example ๐Ÿ‘พ

Environment ๐Ÿ–ฅ

Node.js v21.5.0
linux 6.5.0-15-generic

npm version: 10.2.4

npm ls webpack 
@weareathlon/frontend-webpack-boilerplate@5.16.0 /home/mateusz/Developer/xxx/xxx
โ”œโ”€โ”ฌ babel-loader@9.1.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ clean-webpack-plugin@4.0.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ copy-webpack-plugin@11.0.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ css-loader@6.7.3
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ css-minimizer-webpack-plugin@4.2.2
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ html-loader@4.2.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ html-webpack-plugin@5.5.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ image-minimizer-webpack-plugin@3.8.1
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ mini-css-extract-plugin@2.7.2
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ postcss-loader@7.0.2
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ sass-loader@13.2.0
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ terser-webpack-plugin@5.3.6
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ webpack-cli@5.0.1
โ”‚ โ”œโ”€โ”ฌ @webpack-cli/configtest@2.0.1
โ”‚ โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”‚ โ”œโ”€โ”ฌ @webpack-cli/info@2.0.1
โ”‚ โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”‚ โ”œโ”€โ”ฌ @webpack-cli/serve@2.0.1
โ”‚ โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”œโ”€โ”ฌ webpack-dev-server@4.11.1
โ”‚ โ”œโ”€โ”ฌ webpack-dev-middleware@5.3.3
โ”‚ โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ”‚ โ””โ”€โ”€ webpack@5.75.0 deduped
โ””โ”€โ”€ webpack@5.75.0

npm ls html-webpack-plugin 

@weareathlon/frontend-webpack-boilerplate@5.16.0 /home/mateusz/Developer/xxx/xxx
โ””โ”€โ”€ html-webpack-plugin@5.5.0

Please create reproducible test repo using github, thank you

Please see reproducible test repo as requested https://github.com/mateusz-grek/html-webpack-plugin-issue

Because html-loader doesn't support variables, it is a future of html-webpack-plugin, you need to pass variables into <%= require('html-loader!./components/02_footer_section/index.html').default %>

There is an old issue - webpack-contrib/html-loader#291, I recommend to use template engine for such purposes, we are still not sure it is a right solution to allow using require inside HTML files, that is why it is not finished and don't work in some cases