Skip to content

Is it possible to inject HTML code built from .ejs template into js while building and bundling with webpack? #1821

Open
@ar-IGT

Description

@ar-IGT

Description

Is it possible to inject HTML code built from .ejs template into js while building and bundling with webpack?
I want to build using all three configs, but the least step is to copy build outputs from first and then second step into last step's entry.
In single step/config, I neeed to have styles and HTML code to be injected and minified into corresponding js files, which are need to be also minified and uglified.
Last config is to just copy everything into single file.

Unfortunately this config doesn't work as intented, because it results with empty mm-bundle.[contenthash].js file, although all build processess aren't disrupted by errors.

Config

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');

const commonsAndVendorsConfig = {
  context: path.resolve(__dirname, '.'),
  devServer: {
    client: {
      logging: 'verbose',
      overlay: true,
    },
    static: {
      directory: path.join(__dirname, './dist'),
    },
    compress: true,
    port: 9001,
  },
  entry: {
    vendors: '../shared_libs/modules/vendors.js',
    commons: '../shared_libs/modules/commons.js',
  },
  mode: 'production',
  module: {
    rules: [
      {
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env']
          ]
        },
        test: /\.js$/
      }
    ]
  },
  name: 'vendors-and-commons',
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        test: /\.js$/i,
        minify: (file, sourceMap, minimizerOptions) => {
          const extractedComments = [];
          const { map, code } = require('uglify-js').minify(file, {});
          return { map, code, extractedComments };
        },
      })
    ]
  },
  output: {
    filename: 'js/[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  performance: {
    maxEntrypointSize: 512000,
    maxAssetSize: 512000
  },
  target: ['web', 'es5']
};

const multipleModulesConfig = {
  context: path.resolve(__dirname, '.'),
  dependencies: ['vendors-and-commons'],
  devServer: {
    client: {
      logging: 'verbose',
      overlay: true,
    },
    static: {
      directory: path.join(__dirname, './dist'),
    },
    compress: true,
    port: 9001,
  },
  entry: {
    xmg_mm_wrapper_bottom_banner: './modules/xgm_mm_wrapper_bottom_banner.js',
    xmg_mm_wrapper_overhead_display: './modules/xgm_mm_wrapper_overhead_display.js',
    xmg_media_scheduler: './modules/xmg_media_scheduler.js',
    xmg_window_manager: './modules/xmg_window_manager.js'
  },
  mode: 'production',
  module: {
    rules: [
      {
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env']
          ]
        },
        test: /\.js$/
      },
      {
        exclude: /node_modules/,
        test: /\.s[ac]ss$/i,
        use: [
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },
  name: 'multiple-mm-modules',
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        test: /\.css$/i
      }),
      new TerserPlugin({
        test: /\.js$/i,
        minify: (file, sourceMap, minimizerOptions) => {
          const extractedComments = [];
          const { map, code } = require('uglify-js').minify(file, {});
          return { map, code, extractedComments };
        },
      })
    ]
  },
  output: {
    filename: 'js/[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  performance: {
    maxEntrypointSize: 512000,
    maxAssetSize: 512000
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'xmg_mm_wrapper_bottom_banner.html',
      scriptLoading: 'blocking',
      template: 'src/html/xmg_mm_wrapper_template.ejs',
      templateParameters: {
        bodyClass: 'marketing-base',
        htmlClass: 'marketing-base',
        initConsoleLog: 'MMWrapper start'
      }
    }),
    new HtmlWebpackPlugin({
      filename: 'xmg_mm_wrapper_overhead_display.html',
      scriptLoading: 'blocking',
      template: 'src/html/xmg_mm_wrapper_template.ejs',
      templateParameters: {
        bodyClass: 'marketing-base',
        htmlClass: 'marketing-base',
        initConsoleLog: 'MMWrapper start'
      }
    }),
    new HtmlWebpackPlugin({
      filename: 'xmg_media_scheduler.html',
      scriptLoading: 'blocking',
      template: 'src/html/xmg_mm_wrapper_template.ejs',
      templateParameters: {
        bodyClass: 'media-scheduler-base',
        htmlClass: 'media-scheduler-base',
        initConsoleLog: 'xmg.MediaScheduler start'
      }
    }),
    new HtmlWebpackPlugin({
      filename: 'xmg_window_manager.html',
      scriptLoading: 'blocking',
      template: 'src/html/xmg_mm_wrapper_template.ejs',
      templateParameters: {
        bodyClass: 'window-manager-base',
        htmlClass: 'window-manager-base',
        initConsoleLog: 'xmg.WindowManager start'
      }
    })
  ],
  target: ['web', 'es5']
};

const singleModuleConfig = {
  context: path.resolve(__dirname, '.'),
  dependencies: ['multiple-mm-modules'],
  devServer: {
    client: {
      logging: 'verbose',
      overlay: true,
    },
    static: {
      directory: path.join(__dirname, './dist'),
    },
    compress: true,
    port: 9001,
  },
  entry: {
    'mm-bundle': { import: './modules/mm-bundle.js' },
  },
  mode: 'production',
  module: {
    rules: [
      {
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env']
          ]
        },
        test: /\.js$/
      },
      {
        exclude: /node_modules/,
        test: /\.s[ac]ss$/i,
        use: [
          'css-loader',
        ]
      }
    ]
  },
  name: 'mm-bundle',
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        test: /\.css$/i
      }),
      new TerserPlugin({
        test: /\.js$/i,
        minify: (file, sourceMap, minimizerOptions) => {
          const extractedComments = [];
          const { map, code } = require('uglify-js').minify(file, {});
          return { map, code, extractedComments };
        },
      })
    ]
  },
  output: {
    clean: true,
    filename: 'js/[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  performance: {
    maxEntrypointSize: 512000,
    maxAssetSize: 512000
  },
  target: ['web', 'es5']
};

module.exports = [commonsAndVendorsConfig, multipleModulesConfig, singleModuleConfig];

And here's template:

<html class="<%= htmlClass %>">
<head>
    <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>
    <title>Window Manager</title>

    <script type='application/javascript'>
        console.log('<%= initConsoleLog %>');
    </script>
</head>

<body class="<%= bodyClass %>">
    <div class="mmContentContainer"></div>
</body>

</html>

Environment

Node.js v14.21.3, win32 10.0.19045
npm version: 6.14.18
[email protected]
[email protected]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions