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

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

Open
ar-IGT opened this issue Aug 21, 2023 · 3 comments

Comments

@ar-IGT
Copy link

ar-IGT commented Aug 21, 2023

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
webpack@5.88.1
html-webpack-plugin@5.5.3
@alexander-akait
Copy link
Collaborator

Hello, you need loader for such behaviour. Do you want to prebuild templates?

@ar-IGT
Copy link
Author

ar-IGT commented Dec 20, 2023

What kind of loader, what specific plugin?

Do you want to prebuild templates

I don't know myself if I really need to prebuild the templates.
If there's no easier way, then I guess I want to prebuild them.

@alexander-akait
Copy link
Collaborator

@ar-IGT I ask this because I want to understand, if you want to load ejs and build template on your client you don't need this plugin, if you want to use ejs as a template for your HTML files, you need to install ejs-loader

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

No branches or pull requests

2 participants