You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何DefinePlugin在html-loader配合extract-loader时未完成变量替换?

Why DefinePlugin Isn't Working with extract-loader + html-loader?

Let’s break down why you’re hitting this error and how to fix it.

The Root Cause

You’re right that webpack runs loaders right-to-left (bottom-to-top in the use array), but there’s a critical timing issue here:

  • DefinePlugin operates during webpack’s compilation phase: it scans the AST of processed modules and replaces matching identifiers after loaders have finished their work.
  • extract-loader works differently: it executes the output of the preceding loader (html-loader) during the loader processing phase, before webpack runs its full compilation steps (including DefinePlugin’s variable replacements).

When you add extract-loader to the chain, html-loader first converts your ${TITLE} into raw JS code referencing the TITLE variable. Then extract-loader tries to execute this code immediately—but since DefinePlugin hasn’t had a chance to replace TITLE with your string value yet, you get the ReferenceError: TITLE is not defined error.

This doesn’t happen when using html-loader alone or with HtmlWebpackPlugin because:

  • With just html-loader: the processed module goes through webpack’s full compilation, where DefinePlugin replaces TITLE before the code is bundled.
  • With HtmlWebpackPlugin: the plugin processes the template after webpack’s compilation is complete, so DefinePlugin’s replacements are already applied.

Fixes to Try

1. Use HtmlWebpackPlugin (Recommended)

This is the simplest and most idiomatic solution for generating standalone HTML files with webpack. It automatically handles the timing issue and doesn’t require extract-loader:

const { DefinePlugin } = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'none',
  entry: ["./src/index.js"], // Keep your JS entry, or omit if you only need HTML
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          { loader: "html-loader", options: { interpolate: true } }
        ]
      }
    ]
  },
  plugins: [
    new DefinePlugin({ TITLE: JSON.stringify('My page title') }),
    new HtmlWebpackPlugin({
      template: './src/index.html' // Point to your HTML template
    })
  ]
};

2. Pre-Replace Variables with string-replace-loader

Add string-replace-loader to your loader chain to replace ${TITLE} before html-loader and extract-loader process the file. This skips the need for DefinePlugin to handle the HTML variable:

const { DefinePlugin } = require('webpack');

module.exports = {
  mode: 'none',
  entry: ["./src/index.html"],
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          "extract-loader",
          { loader: "html-loader", options: { interpolate: true } },
          {
            loader: "string-replace-loader",
            options: {
              search: /\${\s*TITLE\s*}/, // Match `${ TITLE }` with optional whitespace
              replace: JSON.stringify('My page title'),
            }
          }
        ]
      }
    ]
  },
  // Keep DefinePlugin if you need it for other files
  plugins: [new DefinePlugin({ TITLE: JSON.stringify('My page title') })],
};

3. Switch to a Template Loader Like ejs-loader

Use a loader that supports passing template parameters directly, avoiding dependency on DefinePlugin’s compilation-phase replacement:

First, update your index.html to use EJS-style interpolation:

<!DOCTYPE html>
<html>
<head>
<title><%= TITLE %></title>
</head>
<body>
</body>
</html>

Then adjust your webpack config:

module.exports = {
  mode: 'none',
  entry: ["./src/index.html"],
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          "extract-loader",
          {
            loader: "ejs-loader",
            options: {
              data: {
                TITLE: 'My page title' // Pass your variables directly here
              }
            }
          }
        ]
      }
    ]
  }
};

内容的提问来源于stack exchange,提问作者NReilingh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:22:49