Reputation: 63768
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")
],
};
Upvotes: 11
Views: 18143
Reputation: 3103
As far as I understand EJS, your problem would be solved by using <%%=
as explained in the EJS docs, so replacing your code by:
API_URL: "<%%= API_URL %>"
,
Upvotes: 0
Reputation: 69
If you want Webpack to ignore your file from the build you can prepend raw-loader in front of the file path like this:
new HtmlWebpackPlugin({
inject: true,
filename: "index.ejs",
template: "!!raw-loader!" + 'src/index.ejs',
}),
And in case you want to inject variables into your template directly from Webpack you can use a dependency called react-dev-utils
, which has a very handy plugin for this:
new InterpolateHtmlPlugin(HtmlWebpackPlugin, {
PUBLIC_URL: publicUrl,
// You can pass any key-value pairs, this was just an example.
// WHATEVER: 42 will replace %WHATEVER% with 42 in index.html.
}),
Haven't tried with an ejs template myself but I see no reason that it shouldn't work.
Upvotes: -1
Reputation: 5138
The HTMLWebpackPlugin uses lodash.template for this and it should be possible though not very easy to change the default delimiter for it to something like <?
so you can use the <%
delimiter for the frontend. However if you're using the ejs package for the frontend it would be a lot easier to change the delimiter there and keep the normal one for webpack.
ejs:
<div>
<%=SOME_WEBPACK_VAR%>
<br />
<?=SOME_EJS_VAR%>
</div>
javascript:
ejs.render(yourHtml, {SOME_EJS_VAR: 'foo'}, {delimiter: '?'});
Upvotes: 1
Reputation: 21
I ran into the same issue and adding a quote (") to the definition of the variable solved it:
In your case:
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'API_URL': '"' + JSON.stringify(process.env.API_URL) + '"'
}
})
...
Upvotes: 0
Reputation: 63768
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.
Upvotes: 6