最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Template in HTML, with Webpack, get error "variable" is not defined - Stack Overflow

programmeradmin10浏览0评论

I created template in index.html to generate html-code with js, code below. My Webpack configuration also below. When I run it with webpack-dev-server, I get error: title is not defined. Somehow webpack tries to resolve 'title' by self, instead of delegate it to 'lodash/template'. Please help me fix code, I'm in despair(.

import path from 'path';
import glob from 'glob';
import webpack from 'webpack';

import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';

const inProduction = process.env.mode === 'production';

export default {
  entry: {
    app: [
      './src/scripts/main.js',
    ],
  },
  output: {
    path: path.join(__dirname, 'build'),
    filename: '[name].[chunkhash].js',
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/,
        use: ExtractTextPlugin.extract({
          use: ['css-loader', 'sass-loader'],
          fallback: 'style-loader',
        }),
      },
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: '/node_modules',
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin('[name].[chunkhash].css'),
    new webpack.LoaderOptionsPlugin({
      minimize: inProduction,
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, './src/index.html'),
    }),
  ],
};

I created template in index.html to generate html-code with js, code below. My Webpack configuration also below. When I run it with webpack-dev-server, I get error: title is not defined. Somehow webpack tries to resolve 'title' by self, instead of delegate it to 'lodash/template'. Please help me fix code, I'm in despair(.

import path from 'path';
import glob from 'glob';
import webpack from 'webpack';

import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';

const inProduction = process.env.mode === 'production';

export default {
  entry: {
    app: [
      './src/scripts/main.js',
    ],
  },
  output: {
    path: path.join(__dirname, 'build'),
    filename: '[name].[chunkhash].js',
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/,
        use: ExtractTextPlugin.extract({
          use: ['css-loader', 'sass-loader'],
          fallback: 'style-loader',
        }),
      },
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: '/node_modules',
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin('[name].[chunkhash].css'),
    new webpack.LoaderOptionsPlugin({
      minimize: inProduction,
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, './src/index.html'),
    }),
  ],
};

import temp from 'lodash/template'
import data from './data';

const titlePicDiscHalf = temp(document.getElementById('titlePicDiscHalf').innerHTML);
document.write(titlePicDiscHalf({ title: 'Hello World!' }));
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  </head>
  <body>
    <script type="text/template" id="titlePicDiscHalf">
      <div class="titlePicDiscHalf">
        <div class="picture"></div>
        <div class="title"><%=title%></div>
        <div class="discription"></div>
        <div class="buttons"></div>
      </div>
    </script>
  </body>
</html>

Share asked Mar 8, 2018 at 14:20 Rami ChasygovRami Chasygov 2,78410 gold badges26 silver badges39 bronze badges 4
  • Change <%= and %> delimirters used by template. – dfsq Commented Mar 8, 2018 at 14:24
  • @dfsq, if I change it to other symbols like <$=title$>, no errors, but it render <$=title$>, instead "Hello world" – Rami Chasygov Commented Mar 8, 2018 at 14:28
  • html-webpack-plugin uses the same templating syntax. Maybe the error es from the plugin trying to resolve title? – lukas-reineke Commented Mar 8, 2018 at 14:36
  • 2 @lukas-reineke yes, this is exactly the issue. – dfsq Commented Mar 8, 2018 at 14:36
Add a ment  | 

2 Answers 2

Reset to default 7

The problem is that html-webpack-plugin uses the same template tags <%= %> to insert bundle information into template.

You have two options.

1. Change lodash.template delimiters

You could change delimiters used by client-side lodash/template to something else, so Webpack would ignore it. For example:

_.templateSettings.interpolate = /<\$=([\s\S]+?)\$>/g;

Check out this demo.

_.templateSettings.interpolate = /<\$=([\s\S]+?)\$>/g;

const temp = _.template
const titlePicDiscHalf = temp(document.getElementById('titlePicDiscHalf').innerHTML);

document.write(titlePicDiscHalf({ title: 'Hello World!' }));
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

<script type="text/template" id="titlePicDiscHalf">
  <div class="titlePicDiscHalf">
    <div class="picture"></div>
    <div class="title">
      <$=title$>
    </div>
    <div class="discription"></div>
    <div class="buttons"></div>
  </div>
</script>

2. Change html-webpack-plugin delimiters

Install ejs-loader separately and configure html-webpack-plugin to use it to load your template. There you can change delimiters to yours. It could look something like this:

plugins: [
  new HtmlWebpackPlugin({
    template: './index.html.ejs',
  })
],
module: {
  rules: [
    { test: /\.ejs$/, loader: 'ejs-loader', query: {
      interpolate: /<\$=([\s\S]+?)\$>/g,
      evaluate: /<\$([\s\S]+?)\$>/g,
    }},
  ]
},

Now, you can configure your template with two different set of delimiters, one for client bundle lodash template and another for html-webpack-plugin:

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title><$= htmlWebpackPlugin.options.title $></title>
  </head>
  <body>
    <script type="text/template" id="titlePicDiscHalf">
      <div class="titlePicDiscHalf">
        <div class="picture"></div>
        <div class="title"><%= title %></div>
        <div class="discription"></div>
        <div class="buttons"></div>
      </div>
    </script>
  </body>
</html>

Note, <title><$= htmlWebpackPlugin.options.title $></title> is used by webpack, and <div class="title"><%= title %></div> is by client-side lodash.

Just in case someone else falls in the same trap where one simply wants to use a static html file with some <script> inside and subsequently encountering an error like Referenceerror: variable is not defined.

Make sure you are not using JS template strings!

E.g. instead of doing something like

function addLoginStatus(user) {
    document.querySelector('.login-status').textContent = `You logged in as user.firstName`;
}

use something like this:

function addLoginStatus(user) {
    document.querySelector('.login-status').textContent = 'You logged in as ' + user.firstName;
}

I found that with template strings, the webpack-html-plugin template will naturally try to interpret them, which was not intended in my case.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论