Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output file does not contain markup. its more like a webpack js file that outputs markup #90

Open
scott-primacy opened this issue Apr 18, 2024 · 5 comments
Labels
question Further information is requested

Comments

@scott-primacy
Copy link

scott-primacy commented Apr 18, 2024

My html output contains webpack js, instead of html markup

webpack config:

     new HtmlBundlerPlugin({
        entry: {
           article: "/src/views/article.html"
        },
     })

article.html:

<%~ include('/src/views/partials/_markup-top.html',{pageTitle: 'article', bodyClass: 'tier'}) %>
<main>main stuff for articles here.... </main>
<%~ include('/src/views/partials/_markup-bottom.html') %>

I would expect the html output to be something like:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />  
		<link rel="preconnect" href="https://fonts.gstatic.com"> 
		<title>article</title>
		<meta name="description" content="test" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />  
		<link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700" rel="stylesheet">
	</head>
	<body class="tier">
		<!-- Skip Nav -->
		<div id="skip-nav">
			<a href="#main">Skip Navigation</a>
		</div>
		<!-- Main Container -->
		<main class="main-container" id="content">
			<!-- markup -->
		</main>		  
	</body>
</html>

Actual output:

/******/ (function() { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/views/article.html":
/*!********************************!*\
  !*** ./src/views/article.html ***!
  \********************************/
/***/ (function(module) {

module.exports='<!DOCTYPE html>\n<html lang="en">\n\n<head>\n    <meta charset="UTF-8" />\n    <link 
...

it's like it's treating this like a js file.

Environment:
Mac OS
node v16.13.2

webpack.config:

// Plugins
const path = require("path");
const glob = require("glob");
const TerserPlugin = require("terser-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const FileManagerPlugin = require("filemanager-webpack-plugin");
// const FileManagerPlugin = require("filemanager-plugin").WebpackFilemanager;
const HtmlBundlerPlugin = require("html-bundler-webpack-plugin");

const isHot = path.basename(require.main.filename) === "webpack-dev-server.js";

// Handle nested html partials
const INCLUDE_PATTERN = /<include src="(.+)"\s*\/?>(?:<\/include>)?/gi;

class CurrentTimePlugin {
   constructor() {
      // You can add any options you might want to pass to the plugin here
   }

   apply(compiler) {
      compiler.hooks.done.tap("CurrentTimePlugin", (stats) => {
         setTimeout(() => {
            const currentTime = new Date().toLocaleString();
            console.log("\n\n" + "=========================================================");
            console.log("\t" + `Webpack compiled at: ${currentTime}`);
            console.log("=========================================================");
         }, 100);
      });
   }
}

const processNestedHtml = (content, loaderContext, dir = null) =>
   !INCLUDE_PATTERN.test(content)
      ? content
      : content.replace(INCLUDE_PATTERN, (m, src) => {
           const filePath = path.resolve(dir || loaderContext.context, src);
           loaderContext.dependency(filePath);
           return processNestedHtml(loaderContext.fs.readFileSync(filePath, "utf8"), loaderContext, path.dirname(filePath));
        });

module.exports = {
   entry: {
      app: [path.join(__dirname, "../src/js/app.js")]
   },
   devServer: {
      static: {
         directory: path.resolve(__dirname, "../dist"),
         serveIndex: true,
         watch: true
      }
   },
   output: {
      path: path.resolve(__dirname, "../dist"),
      filename: "js/[name].js"
   },
   optimization: {
      minimize: false,
      minimizer: [
         new TerserPlugin({
            parallel: true
         }),
         new CssMinimizerPlugin()
      ]
   },
   resolve: {
      extensions: [".js", ".css", ".scss"],
      modules: ["node_modules"],
      alias: {
         request$: "xhr",
         fonts: path.resolve(__dirname, "../src/fonts"),
         components: path.resolve(__dirname, "../src/components"),
         modules: path.resolve(__dirname, "../src/modules"),
         styles: path.resolve(__dirname, "../src/styles")
      }
   },
   module: {
      rules: [
         {
            // babel-loader
            test: /\.js$/,
            exclude: /node_modules/,
            rules: [
               {
                  use: [
                     {
                        loader: "babel-loader",
                        options: {
                           cacheDirectory: true,
                           babelrc: false,
                           rootMode: "upward"
                        }
                     }
                  ]
               }
            ]
         },
         {
            // json loader
            test: /\.json$/,
            loader: "json-loader"
         },
         {
            // style loaders
            test: /\.(css|sass|scss)$/,
            use: [
               MiniCssExtractPlugin.loader,
               {
                  loader: "css-loader",
                  options: {
                     sourceMap: true,
                     importLoaders: 2,
                     esModule: false
                  }
               },
               {
                  loader: "postcss-loader",
                  options: {
                     sourceMap: true
                  }
               },
               {
                  loader: "resolve-url-loader"
               },
               {
                  loader: "sass-loader",
                  options: {
                     sourceMap: true
                  }
               }
            ]
         },
         {
            // Loads fonts
            test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
            loader: "url-loader",
            options: {
               limit: true,
               esModule: false
            }
         },
         {
            // Load images
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
            type: "asset/resource",
            generator: {
               filename: "assets/[name][ext]"
            }
         },
         {
            // Allow partials in html pages.
            test: /\.(html)$/,
            // exclude: /node_modules/,
            include: [path.resolve(__dirname, "../src/views/partials"), path.resolve(__dirname, "../src/components/icon-font/")],
            use: {
               loader: "html-loader",
               options: {
                  preprocessor: processNestedHtml
               }
            }
         }
      ]
   },
   stats: {
      children: true
   },
   plugins: [
      new FileManagerPlugin({
         events: {
            onEnd: [
               {delete: ["./dist/images"]},
               {delete: [path.join(__dirname, "../wp/wp-content/themes/2019-redesign/assets/*")]},
               {
                  copy: [
                     {
                        source: path.join(__dirname, "../src/images"),
                        destination: path.join(__dirname, "../dist/images")
                     }
                  ]
               },
               {
                  copy: [
                     {
                        source: path.join(__dirname, "../dist/images"),
                        destination: path.join(__dirname, "../wp/wp-content/themes/2019-redesign/assets/images")
                     }
                  ]
               },
               {
                  copy: [
                     {
                        source: path.join(__dirname, "../dist/js"),
                        destination: path.join(__dirname, "../wp/wp-content/themes/2019-redesign/assets/js")
                     }
                  ]
               },
               {
                  copy: [
                     {
                        source: path.join(__dirname, "../dist/css"),
                        destination: path.join(__dirname, "../wp/wp-content/themes/2019-redesign/assets/css")
                     }
                  ]
               }
            ]
         }
      }),

      // MiniCssExtractPlugin
      new MiniCssExtractPlugin({
         filename: isHot ? "[name].css" : "css/[name].css",
         chunkFilename: "[id].css"
      }),
      new ESLintPlugin(),

      new CurrentTimePlugin(),

      new HtmlBundlerPlugin({
         entry: {
            article: "/src/views/article.html"
         },
      })
   ]
};
@webdiscus
Copy link
Owner

@scott-primacy

please read the manual Install and Quick Start.

  1. delete the loader - MiniCssExtractPlugin.loader
  2. delete the plugin - MiniCssExtractPlugin
  3. delete the loader - html-loader

Please create a small repository with reproducible issue, then I can help you.

@webdiscus webdiscus added the question Further information is requested label Apr 18, 2024
@webdiscus
Copy link
Owner

webdiscus commented Apr 19, 2024

@scott-primacy

the correct webpack config:

const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

class CurrentTimePlugin {
  constructor() {
    // You can add any options you might want to pass to the plugin here
  }

  apply(compiler) {
    compiler.hooks.done.tap('CurrentTimePlugin', (stats) => {
      setTimeout(() => {
        const currentTime = new Date().toLocaleString();
        console.log('\n\n' + '=========================================================');
        console.log('\t' + `Webpack compiled at: ${currentTime}`);
        console.log('=========================================================');
      }, 100);
    });
  }
}

module.exports = {
  // NOTE: add the source JS file directly in the template using <script src="scripts/app.js"> tag, NOT here
  // entry: {
  //   app: [path.join(__dirname, '../src/js/app.js')],
  // },
  devServer: {
    static: {
      directory: path.resolve(__dirname, '../dist'),
      serveIndex: true,
      watch: true,
    },
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    //filename: 'js/[name].js', // <= MOVE into `js.filename` bundler plugin option
  },
  optimization: {
    minimize: false,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
      new CssMinimizerPlugin(),
    ],
  },
  resolve: {
    //extensions: ['.js', '.css', '.scss'], // DON'T mix JS and SCSS extensions
    extensions: ['.js'],
    modules: ['node_modules'],
    alias: {
      request$: 'xhr',
      fonts: path.resolve(__dirname, '../src/fonts'),
      components: path.resolve(__dirname, '../src/components'),
      modules: path.resolve(__dirname, '../src/modules'),
      styles: path.resolve(__dirname, '../src/styles'),
      scripts: path.resolve(__dirname, '../src/js'), // <= use alias to define JS in the template
      images: path.join(__dirname, '../wp/wp-content/themes/2019-redesign/assets/images'), // <= use alias to define source image files
    },
  },
  module: {
    rules: [
      {
        // babel-loader
        test: /\.js$/,
        exclude: /node_modules/,
        rules: [
          {
            use: [
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true,
                  babelrc: false,
                  rootMode: 'upward',
                },
              },
            ],
          },
        ],
      },
      {
        // json loader
        test: /\.json$/,
        loader: 'json-loader',
      },
      {
        // style loaders
        test: /\.(css|sass|scss)$/,
        use: [
          // MiniCssExtractPlugin.loader, // <= DELETE it
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              importLoaders: 2,
              esModule: false,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'resolve-url-loader',
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
      {
        // Loads fonts
        test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
        loader: 'url-loader',
        options: {
          limit: true,
          esModule: false,
        },
      },
      {
        // Load images
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'assets/[name][ext]',
        },
      },
      // DELETE the html rule, DON'T use the `html-loader`
      // {
      //   // Allow partials in html pages.
      //   test: /\.(html)$/,
      //   // exclude: /node_modules/,
      //   include: [
      //     path.resolve(__dirname, '../src/views/partials'),
      //     path.resolve(__dirname, '../src/components/icon-font/'),
      //   ],
      //   use: {
      //     loader: 'html-loader',
      //     options: {
      //       preprocessor: processNestedHtml,
      //     },
      //   },
      // },
    ],
  },
  stats: {
    children: true,
  },
  plugins: [
    // NOTE: you can define source image files directly in template using the webpack alias to the image directory,
    // then you don't need to copy source images into dist
    new FileManagerPlugin({
      events: {
        onEnd: [
          { delete: ['./dist/images'] },
          {
            delete: [path.join(__dirname, '../wp/wp-content/themes/2019-redesign/assets/*')],
          },
          {
            copy: [
              {
                source: path.join(__dirname, '../src/images'),
                destination: path.join(__dirname, '../dist/images'),
              },
            ],
          },
          {
            copy: [
              {
                source: path.join(__dirname, '../dist/images'),
                destination: path.join(__dirname, '../wp/wp-content/themes/2019-redesign/assets/images'),
              },
            ],
          },
          {
            copy: [
              {
                source: path.join(__dirname, '../dist/js'),
                destination: path.join(__dirname, '../wp/wp-content/themes/2019-redesign/assets/js'),
              },
            ],
          },
          {
            copy: [
              {
                source: path.join(__dirname, '../dist/css'),
                destination: path.join(__dirname, '../wp/wp-content/themes/2019-redesign/assets/css'),
              },
            ],
          },
        ],
      },
    }),

    // MiniCssExtractPlugin // <= DELETE it
    // new MiniCssExtractPlugin({
    //   filename: isHot ? '[name].css' : 'css/[name].css',
    //   chunkFilename: '[id].css',
    // }),
    new ESLintPlugin(),

    new CurrentTimePlugin(),

    new HtmlBundlerPlugin({
      entry: {
        article: './src/views/article.html',
      },
      js: {
        filename: 'js/[name].js',
      },
      css: {
        filename: 'css/[name].css',
        chunkFilename: 'css/[name].chunk.css',
      },
    }),
  ],
};

Please create a repo, then I can help you more.

@scott-primacy
Copy link
Author

Thanks so much for your help. I created this little repo to help me get this working:
https://github.com/scott-primacy/webpack

@scott-primacy
Copy link
Author

Unfortunately, it can't compile the html page tho.

Module build failed (from ./node_modules/html-bundler-webpack-plugin/src/Loader/index.js):
LoaderException: 
 HTML Bundler Plugin  Resolving of source files in the template file failed.
File: src/views/article.html
Error: Cannot find module '/Users/scottr/work/webpack-testing/src/styles/app.css'

@webdiscus
Copy link
Owner

@scott-primacy

Cannot find module '/Users/scottr/work/webpack-testing/src/styles/app.css'

of course is not found.
Did you see my PR?
Firstly merge my PR into your demo and see how it works.

You should load the source SCSS file, not CSS, because css not exists and will be generate by the bundler plugin.
Just add the source SCSS file into HTML:

<link href="@styles/app.scss" rel="stylesheet">

and remove this file from JS.

@styles is the webpack alias to /Users/scottr/work/webpack-testing/src/styles/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants