如何使用webpack-dev-server和html-webpack-plugin观看index.html?

56
我正在使用webpack-dev-server进行开发,并使用html-webpack-plugin生成包含修订资源的index.html。问题是每次我更改index.html时,捆绑系统都不会再次重建。我知道index不在入口中,但有没有解决这个问题的方法?

1
我的解决方案解决了你的问题吗?我很想知道你是否找到了其他方法来做这件事。 - Gabriel Kunkel
我也是一样的情况。我正在努力避免在生产和开发中使用两个不同的index.html,引用不同的资源。 - Spock
1
@Spock 请看下面的回答。你可以在入口点中要求你的模板。每次更改模板时,开发服务器都应该更新。 - Gabriel Kunkel
6个回答

49

问题在于Webpack没有监视index.html文件。它只会监视那些在你的代码中“需要”或“导入”到其他文件中并被加载器测试的文件。

解决方案包括两个部分。

首先,在入口点(entry point)中要求(require) index.html文件。从技术上讲,您可以在应用程序的任何位置要求它,但这很方便。如果您正在使用html-webpack-plugin模板,则也可以只要求您的模板即可。

我在我的index.js文件(入口点)中要求了index.html文件:

require('./index.html')
const angular = require('angular')
const app = angular.module('app', [])
//...so on and so forth

最后,安装并将raw-loader与您的其他加载器一起添加到您的Webpack配置文件中。因此:

{
   test: /\.html$/,
   loader: "raw-loader"
}

原始加载器将把任何“required”文件转换为文本字符串,然后Webpack将观察它并在每次更改时刷新dev-server。

在加载阶段,Webpack本身或您的程序实际上不会对index.html文件(或模板)做任何操作。这在生产或测试环境中完全没有必要,因此我只在运行开发服务器时添加它:

/* eslint no-undef: 0 */

if (process.env.NODE_ENV === 'development') {
  require('./index.html')
}

const angular = require('angular')
const app = angular.module('app', [])
//...so on and so forth

理论上,您可以要求“引入”一堆您想要观察的其他静态HTML文件……或者文本文件。我个人使用raw-loader来处理Angular指令模板,但是我不必将它们添加到我的入口点开头。我只需在指令模板属性内部执行require,就像这样:

module.exports = function(app) {
  app.directive('myDirective', function(aListItem) {
    return {
      template: require('./myTemplate.html'),
      restrict: 'E',
      controller: function($scope) {
        $scope.someThingThatGoesInMyTemplate = 'I love raw-loader!'
      }
    }
  })
}

天啊,时间过得真快!很抱歉我没有回复您。这太棒了,运行得非常好! - Spock
我对获取process.env状态有些困惑。这是在服务器端运行吗?在我的index.js中使用该代码片段无法正常工作。由于它是客户端,所以无法识别该变量且未定义。您能否澄清如何使其工作? - spb
@spb 很抱歉,那可能会让人感到沮丧。我并不是想让我的示例被复制和粘贴。当你从命令行运行webpack时,可以设置process.env.NODE_ENV。我只需在我的webpack命令(或webpack-dev-sever命令,具体取决于我要运行什么)之前添加“NODE_ENV=development”或“NODE_ENV=production”。然后,我可以使用“process.env.NODE_ENV”从我的代码中获取该设置。如果需要进一步解释,请参阅以下链接:https://dev59.com/cmox5IYBdhLWcg3wcj94 - Gabriel Kunkel
1
不,这并不是那么严重的事情。看起来你只是在一个Angular文件中使用了process.env评估,但是可能它已经被处理了,比如你的webpack配置文件或其他一些运行在Node上的东西。无论如何,我通过使用你的raw-loader提示立即得到了需要的效果,这已经足够了。所以谢谢你。 :) - spb
2
@spb жҲ‘и®ӨдёәдҪ йңҖиҰҒдҪҝз”Ё DefinePlugin webpack жҸ’件жүҚиғҪеңЁеүҚз«Ҝ JavaScript д»Јз ҒдёӯдҪҝз”ЁзҺҜеўғеҸҳйҮҸгҖӮзұ»дјјиҝҷж ·пјҡnew webpack.DefinePlugin({ NODE_ENV: JSON.stringify(process.env.NODE_ENV) })然еҗҺеңЁдҪ зҡ„ app.js дёӯпјҡif (NODE_ENV === 'development') { ... }дҪҶд№ҹи®ё @GabrielKunkel еҸҜд»Ҙжӣҙе…·дҪ“ең°иҜҙжҳҺ他们еҰӮдҪ•еңЁеүҚз«Ҝд»Јз ҒдёӯдҪҝз”Ё process.env.VARIABLE... - adam-beck
显示剩余5条评论

44

只需在你的devServer配置中添加watchContentBase: true即可。webpack-dev-server将监视位于contentBase目录中的所有文件的更改。这里我们监视./src目录中的所有文件。

webpack.config.js:

...
 devServer: {
   port: 8080,
   contentBase: './src',
   watchContentBase: true

} 

我已经搜索了很长时间,以找到一个简单的解决方案来监视我的html / twig(模板)目录,并在这些更改时重新加载页面。我正在为非SPA网站(Craft CMS)使用webpack和dev-server。我所要做的就是将我的contentBase更改为'./templates'。这是一个简单的解决方案,一直在文档中,但没有注意到使用情况。感谢您提供的答案! - Chase Giunta
5
简单。我认为这应该是被接受的答案。 - user9298624
1
如果可以的话,我会给这个点赞二十次!比起通过一些webpack插件来处理HTML以实现自动重载,这简单多了。 - David
很遗憾,自 webpack-dev-server 4.11.1 版本起,此选项不再可用。 - Maxim Blinov

8
webpack > 5.x 开始,不再支持contentBasewatchContentBase 选项。
取而代之的是你可以这样做:
devServer: {
   watchFiles:['src/**/*'] // to detect changes on all files inside src directory
}

8

使用 webpack > 5.0 版本,需使用 watchFiles 选项

devServer: {
    open: true,
    watchFiles: ['src/**/*'],
},

3
如果你只是使用npx webpack --watch构建它,你可以将缓存设置为false,每次生成文件。
new HtmlWebpackPlugin({
  cache: false,
})

要进一步定制,请阅读此链接:htmlwebpackplugin


正是我所需要的,不确定为什么我在其他地方找不到它!!! - Benjamin Ashbaugh

2
另一种解决方案是使用file-loader在入口JavaScript文件中导入HTML文件。
import 'file-loader!../templates/index.html';

您可以像往常一样配置html-webpack-plugin
plugins: [
 new HtmlWebPackPlugin({
  template: path.resolve(__dirname, 'src/templates/index.html'),
  filename: path.resolve(__dirname, 'dist/index.html'),
  files: {
   css: ['style.css'],
   js: ['main.js'],
  }
 })
]

webpack-dev-server正在运行时,此操作不会将任何内容写入磁盘。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接