Webpack配置如何将index.html文件复制到dist文件夹中

235

我正在尝试自动化资产进入/dist。我有以下config.js:

module.exports = {
  context: __dirname + "/lib",
  entry: {
    main: [
      "./baa.ts"
    ]
  },
  output: {
    path: __dirname + "/dist",
    filename: "foo.js"
  },
  devtool: "source-map",
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'awesome-typescript-loader'
      },
      { test: /\.css$/, loader: "style-loader!css-loader" }
    ]
  },
  resolve: {
    // you can now require('file') instead of require('file.js')
    extensions: ['', '.js', '.json']
  }
}

当我运行webpack时,我希望将与/lib同级的main.html包含进/dist文件夹中。我该如何做?

更新 2017_____________

我现在最喜欢的方法是使用html-webpack-plugin和一个模板文件。感谢被接受的答案!这种方式的优点是,索引文件还会自动添加缓存破坏后的js链接!

11个回答

216

选项1

在你的index.js文件(即Webpack入口文件)中通过file-loader插件将index.html引用进来,例如:

require('file-loader?name=[name].[ext]!../index.html');

使用Webpack构建项目后,index.html将会输出到输出文件夹中。

选项2

使用html-webpack-plugin插件避免手动创建index.html文件。Webpack将自动生成该文件。

如果你想要保留自己的index.html文件作为模板,则可以使用以下配置:

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

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    })
  ]
}

查看文档以获取更多信息。


2
我能否通过在配置文件中编写某些内容来加载它? - codeVerine
4
在webpack v2中,似乎不能省略“-loader”后缀。例如:require('file-loader?name=[name].[ext]!../index.html'); - overthink
1
@codeVerine 是的,可以通过在webpack配置文件的loaders数组中添加类似于{ test: /index\.html/, loader: 'file-loader', query: { name: '[name].[ext]' }这样的内容来实现。但是我无法让webpack-dev-server提供服务,导致在请求/时(根目录不存在!)出现了404错误,这很有趣。 - Brian McCutchon
1
抱歉,我的问题可能有些幼稚,但如果我的HTML文件非常复杂,内部包括很多div和大量的结构,那么webpack如何为我生成一个index.html文件呢? - João Pimentel Ferreira
1
选项2需要安装npm install html-webpack-plugin,然后将其放入webpack.config.js文件中的const HtmlWebpackPlugin = require('html-webpack-plugin'); - Nabi K.A.Z.
显示剩余7条评论

76

我将为VitalyB的答案添加一个选项:

选项 3

通过npm。如果您通过npm运行命令,则可以将此设置添加到您的package.json中(也请查看其中的webpack.config.js)。对于开发,请运行npm start,在这种情况下无需复制index.html,因为Web服务器将从源文件目录运行,并且bundle.js将从相同位置(bundle.js仅位于内存中,但可用,如同与index.html一起)获取。对于生产,请运行npm run build,dist文件夹将包含您的bundle.js并使用良好的旧cp命令复制index.html,如下所示:

"scripts": {
    "test": "NODE_ENV=test karma start",
    "start": "node node_modules/.bin/webpack-dev-server --content-base app",
    "build": "NODE_ENV=production node node_modules/.bin/webpack && cp app/index.html dist/index.html"
  }

更新:选项4

有一个copy-webpack-plugin,如这个Stackoverflow答案所述。

但通常情况下,除了像index.html这样的第一个文件和较大的资源(如大型图像或视频)之外,将CSS、HTML、图像等直接通过require引入你的应用程序中,webpack会为你包含它们(在正确设置加载器和可能的插件后)。


14
选项3应该改为选项1。 - Gil Epshtain
3
我尝试了选项三,但是 index.html 的热重载没有起作用。你不经常编辑你的 index.html 吗?这是一个严肃的问题。 - stone
3
如果您希望支持跨操作系统的开发环境,请使用ncp而不是cp。 - V Maharajh

43

你可以使用CopyWebpackPlugin。它的工作方式就像这样:

module.exports = {
  plugins: [
    new CopyWebpackPlugin([{
      from: './*.html'
    }])
  ]
}

现在Webpack已经取代了Gulp和Grunt,不仅仅是做捆绑,还有许多其他构建相关的任务,这个解决方案是我在大多数项目中看到的。package.json中的脚本仅用于启动测试运行器或开发服务器等简单的事情。 - Robert Jack Will
这似乎不会在对原始文件进行更改时自动重新加载,我是不是漏掉了什么? - TCB13

16
我认为答案是:你不能这样做(或者至少不应该这样做)。这不是Webpack的本职工作。Webpack是一个打包工具,不应该用于其他任务(在这种情况下,复制静态文件是另一项任务)。你应该使用像Grunt或Gulp这样的工具来完成这些任务。将Webpack作为Grunt任务Gulp任务是非常常见的。它们都有其他有用的任务,比如像你描述的复制文件,例如grunt-contrib-copygulp-copy
对于其他资产(不是index.html),您可以将它们与Webpack捆绑在一起(这正是Webpack的用途)。例如:var image = require('assets/my_image.png');。但我假设您的index.html不能成为捆绑包的一部分,因此它不是捆绑器的工作。

66
我会尽力为您提供准确的翻译,以下是需要翻译的内容:我之所以使用webpack,是因为我不想再使用grunt或gulp。是否还有其他选择?如果必须使用gulp,那么我为什么要费心去用webpack呢? - SuperUberDuper
5
问题的立场有些颠倒了。如果可以使用grunt或gulp,为何需要使用webpack?它们都是非常好的任务/构建系统。Webpack(或browserify或r.js)是你可以使用的工具,用于将许多JS文件(和其他资源)打包成一个大的(或多个)JavaScript捆绑包。应该根据任务需要选择正确的工具。而且,通常情况下可以从grunt或gulp运行webpack、browserify或其他打包器。 - Brodie Garnet
1
有许多方法可以使用webpack实现这一点。您可以使用file-loader,它基本上只是将文件/图像复制到输出目录并在需要时提供URL:var url = require('myFile');。正如我所说,捆绑包可以是一个或多个文件。 - Brodie Garnet
1
我可能会使用Broccoli作为父构建过程。 - SuperUberDuper
1
这对我来说是正确的答案。在大型/复杂项目中,webpack构建性能是一个重要的考虑因素。各种文件复制插件会给webpack增加不必要的成本,让webpack专注于JS打包是一个更好的想法。 - Evi Song
显示剩余4条评论

15
为了将已经存在的 index.html 文件复制到 dist 目录中,您可以简单地使用 HtmlWebpackPlugin 插件,并将源 index.html 指定为模板
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // ...
  plugins: [    
    new HtmlWebpackPlugin({
      template: './path/to/index.html',
    })
  ],
  // ...
};

创建的 dist/index.html 文件基本上与您的源文件相同,不同之处在于webpack会使用<script>标签注入.js文件等打包资源。可以配置缩小和其他选项,详见github文档


这比任何复制插件都要好得多。如果需要,HtmlWebpackPlugin 可以自动生成 index.html。因此,无需为 SPA 创建几乎空的 HTML 页面。 - hastrb

14

您可以直接将索引添加到条目配置中,并使用file-loader加载它

module.exports = {

  entry: [
    __dirname + "/index.html",
    .. other js files here
  ],

  module: {
    rules: [
      {
        test: /\.html/, 
        loader: 'file-loader?name=[name].[ext]', 
      },
      .. other loaders
    ]
  }

}

7
如果你只想拿到 index.html,除了使用其他包的方法之外,你还可以使用 CopyPlugin。这种方法的主要动机是,为每个类型和配置添加许多包是一场噩梦。最简单的方法是为所有内容使用 CopyPlugin。详见CopyPlugin 说明文档
npm install copy-webpack-plugin --save-dev

那么。
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    new CopyPlugin([
      { from: 'static', to: 'static' },
      { from: 'index.html', to: 'index.html', toType: 'file'},
    ]),
  ],
};

如您所见,它会将整个静态文件夹及其所有内容复制到dist文件夹中。不需要任何css、插件或其他文件。 虽然这种方法并不适用于所有情况,但它可以简单而快速地完成工作。

4

这在Windows上运行良好:

  1. npm install --save-dev copyfiles
  2. package.json文件中添加一个复制任务:"copy": "copyfiles -u 1 ./app/index.html ./deploy"

这将我的index.html从app文件夹移动到deploy文件夹。


我明白如何使用这里的答案:https://dev59.com/8VkT5IYBdhLWcg3wRNQR#51371023 - IsraGab

0

Webpack 5带有资产模块,因此您不再需要任何复制插件或文件加载器


0

好的,你可以通过npm安装copy-webpack-plugin来复制文件。我这里使用的版本是11.0.0。

下面的指令告诉webpack源js文件在./src/index.js。要构建资产的目录是“dist”目录。 然后在底部,CopyPlugin将所有html文件从'src'目录复制到'dist'目录:

const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "./src/*.html",
          to({ context, absoluteFilename }) {
            return "[name][ext]";
          },
        },
      ],
    }),
  ]
};

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