Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use HTMLWebpackPlugin with an EJS file

I want to use the HTMLWebpackPlugin to take my index.ejs template file, insert my bundled assets, and output a final index.ejs file.

This example has a EJS variable <%= API_URL %>, but webpack is interpreting it.

How can I stop webpack from substituting the variable?

Starting "template":

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Monitor</title>
    <script>
      window.config = {
        API_URL: "<%= API_URL %>"
      }
    </script>
  </head>
  <body>
    <div class="container"></div>
  </body>
</html>

When you try to run webpack:

ERROR in Template execution failed: ReferenceError: API_URL is not defined

Desired result index.ejs: (has bundled assets and EJS var)

Monitor window.config = { API_URL: "<%= API_URL %>" }

webpack.config.js

var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: {
    bundle: './src/index.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
    {
      test: /\.js$/,
      use: 'babel-loader',
      exclude: /node_modules/
    },
    {
      // CSS is imported in app.js.
      test: /\.scss$/,
      use: ExtractTextPlugin.extract({
        fallbackLoader: 'style-loader',
        loader: ["css-loader", "sass-loader"]
      })
    }]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV),
        'API_URL': JSON.stringify(process.env.API_URL)
      }
    }),
    new HtmlWebpackPlugin({
      template: 'src/index.ejs',
      inject: true
    }),
    new ExtractTextPlugin("styles.css")
  ],
};
like image 263
Don P Avatar asked May 05 '17 23:05

Don P


People also ask

What is the htmlwebpackplugin?

The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you, supply your own template using lodash templates, or use your own loader.

Do you deploy with Webpack or HTML?

Whilst most people use Webpack primarily for their JS scripts, there's always one final part of deploying that is forgotten: the HTML.

How do I generate an HTML5 File from a Webpack bundle?

You can either let the plugin generate an HTML file for you, supply your own template using lodash templates, or use your own loader. The plugin will generate an HTML5 file for you that includes all your webpack bundles in the body using script tags.

What file will be generated from a Webpack entry point?

This will generate a file dist/index.html containing the following: If you have multiple webpack entry points, they will all be included with <script> tags in the generated HTML.


1 Answers

Here is a really bad hacky solution, and I hope someone else has a real answer / understanding of how to do this.

In your template file (index.ejs), do this:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Monitor</title>
    <script>
      window.config = {
        API_URL: "<%= htmlWebpackPlugin.options.API_URL_TEMPLATE_VAR %>"
      }
    </script>
  </head>
  <body>
    <div class="container"></div>
  </body>
</html>

In your webpack config, do this (the relevant part is the new HtmlWebpackPlugin where I define a variable.:

plugins: [
    // Define environment variables that are accessible inside of app javascript.
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    }),
    // Adds bundled file links to the index.html
    new HtmlWebpackPlugin({
      // The input file name
      template: 'src/index.prod.ejs',
      // Injects scripts into the <body>
      inject: true,
      // This is so hacky. I inject a string so the built .ejs file has this template var. Lets us set api_url when server is started instead of at bundle time.
      API_URL_TEMPLATE_VAR: '<%= process.env.API_URL %>',
      // The output file name
      filename: 'index.ejs'
    }),
    new ExtractTextPlugin("styles.css")
  ],

Because I defined API_URL_TEMPLATE_VAR, when html-webpack-plugin evaluates it, it will print out <%= process.env.API_URL %> into the final template.

Hacky, but works. Not accepting my own answer / waiting for a better answer.

like image 61
Don P Avatar answered Oct 16 '22 14:10

Don P