如何在Webpack配置中创建多个输出路径

258

有人知道如何在webpack.config.js文件中创建多个输出路径吗?我正在使用带有几个不同字体文件等的bootstrap-sass。为了让webpack处理这些文件,我已经包含了file-loader,它正在正确地工作,但是它输出的文件被保存到我指定给其他文件的输出路径中:

    output: {
      path: __dirname + "/js",
      filename: "scripts.min.js"
    }

我希望能够实现这样的功能,即查看webpack输出的扩展类型,并将以.woff、.eot等结尾的内容重定向到不同的输出路径。这是否可行?
我进行了一些谷歌搜索,并发现了GitHub上的这个问题,其中提供了几种解决方案,但似乎需要知道入口点才能使用哈希方法指定输出,例如:
var entryPointsPathPrefix = './src/javascripts/pages';
var WebpackConfig = {
  entry : {
    a: entryPointsPathPrefix + '/a.jsx',
    b: entryPointsPathPrefix + '/b.jsx',
    c: entryPointsPathPrefix + '/c.jsx',
    d: entryPointsPathPrefix + '/d.jsx'
  },

  // send to distribution
  output: {
    path: './dist/js',
    filename: '[name].js'
  }
}

*https://github.com/webpack/webpack/issues/1189

然而在我的情况下,就字体文件而言,输入过程有点被抽象化了,我只知道输出结果。对于其他正在经历转换的文件,存在一个已知的点,在这个点上我需要将它们导入以便由我的加载器处理。如果有一种方法可以找出这个步骤发生的位置,那么我就可以使用哈希方法来自定义输出路径,但是我不知道这些文件在哪里被导入。
13个回答

363

Webpack可以支持多个输出路径。

将输出路径设置为入口键,并使用name作为输出模板。

webpack配置:


Webpack可以支持多个输出路径。

将输出路径设置为入口键,并使用name作为输出模板。

webpack配置:

entry: {
    'module/a/index': 'module/a/index.js',
    'module/b/index': 'module/b/index.js',
},
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
}

生成的:

└── module
    ├── a
    │   └── index.js
    └── b
        └── index.js

6
在我的情况下,我希望一个输出不包含chunkhash,是否有任何简单的解决方案?谢谢。 - Jón Trausti Arason
1
@zhengkenghong 我认为生成的输出路径需要包含 dist。因此,输出路径不应该是 module/a/index.js,而应该是 module/a/dist/index.js,否则你会覆盖你的入口文件。 - dance2die
2
@Sung dist文件夹已经在输出路径中配置好了。因此生成的文件实际上应该是dist/module/a/index.js,这一点我之前没有提到。 - zhengkenghong
8
我认为这应该成为被接受的答案,因为这是来自Webpack 4文档的答案。-> https://webpack.js.org/concepts/output/#multiple-entry-points - Will
3
虽然有点晚了,但你可以按照这里记录的方法使用 output.filename 函数来实现:https://webpack.js.org/configuration/output/#outputfilename - Thomas
显示剩余5条评论

286
我不确定我们是否遇到同样的问题,因为截至2016年6月,webpack仅支持每个配置一个输出。我猜你已经看到了Github上的问题
但是我使用multi-compiler分离了输出路径。(即将webpack.config.js的配置对象分离)。
var config = {
    // TODO: Add common Configuration
    module: {},
};

var fooConfig = Object.assign({}, config, {
    name: "a",
    entry: "./a/app",
    output: {
       path: "./a",
       filename: "bundle.js"
    },
});
var barConfig = Object.assign({}, config,{
    name: "b",
    entry: "./b/app",
    output: {
       path: "./b",
       filename: "bundle.js"
    },
});

// Return Array of Configurations
module.exports = [
    fooConfig, barConfig,       
];

如果它们有共同的配置,你可以使用extend库或ES6中的Object.assign,或者ES7中的{...}扩展运算符。

1
我没有运行这段代码,可能会出现错误或者打字错误。 - Yeo
1
我运行了你的代码片段,完美无瑕地工作了...惊讶于没有人发现这个问题,前端开发者啊,总是急于求成,缺乏耐心 ;-). 我也是以同样的方式导出配置文件,但我的声明方式不同/标准: var config = { entry: SOURCE_DIR + '/index.jsx', .... }我也没有使用任何多编译器 :-\ - Aubergine
你可以在npm中只需执行 webpack && cp etc 吗? - SuperUberDuper
1
这对我来说非常有用,可以在原始文件夹(自动测试在那里)和实现包的应用程序文件夹中部署npm包。通过这种方式,我可以跳过npm下载步骤,并实时测试我的更新包代码,直到新版本稳定并准备好发布到npm上。 - Adrian Moisa
我遇到了“Webpack已使用与API模式不匹配的配置对象进行初始化”的问题,因为我正在使用webpack合并配置文件来处理其他环境下的webpack文件。 - Tanner Summers
显示剩余4条评论

66

自 Webpack v5.0.0 起,您现在可以使用新的“描述符”语法 (https://webpack.js.org/configuration/entry-context/#entry-descriptor) 为每个入口指定唯一的输出路径。

module.exports = {
  entry: {
    home: { import: './home.js', filename: 'unique/path/1/[name][ext]' },
    about: { import: './about.js', filename: 'unique/path/2/[name][ext]' }
  }
};

1
经过这么多的搜索,终于找到了有用的东西!! - Gaurav
1
@bryanph 不再了。 - Wesley Brian Lachenal
3
从现在开始,这应该是被接受的答案。 - Duc Filan
3
非常感谢,这是非常有用的答案。不过由于某些原因,[ext] 不起作用,我必须手动添加文件扩展名,否则 [ext] 将与文件名连接在一起,所以:about: { import: './about.js', filename: 'unique/path/2/[name][ext]' } 最终将变成 about[ext]。请问是否有人遇到过这个问题或者知道原因? - Weam Adel
尽管生成的文件名为style.css,但它实际上是经过编译的Js形式,因此确实需要样式加载器才能将这些样式引入到头部。 - Shashank Bhatt
显示剩余2条评论

35

如果你可以容忍多个输出路径具有相同的深度和文件夹结构,那么在webpack 2中有一种方法可以实现这个目标(尚未测试webpack 1.x)

基本上,你不需要遵循文档规则,只需为文件名提供一个路径即可。

module.exports = {
    entry: {
      foo: 'foo.js',
      bar: 'bar.js'
    },

    output: {
      path: path.join(__dirname, 'components'),
      filename: '[name]/dist/[name].bundle.js', // Hacky way to force webpack   to have multiple output folders vs multiple files per one path
    }
};

那会采用这个文件夹结构

/-
  foo.js
  bar.js

并将其转化为

/-
  foo.js
  bar.js
  components/foo/dist/foo.js
  components/bar/dist/bar.js

@ccnixon 这里有文档 https://webpack.js.org/configuration/output/#outputfilename 搜索 "still allowed"。 - John Henckel

11

在我的情况下,我遇到了这种情况。

const config = {
    entry: {
    moduleA: './modules/moduleA/index.js',
    moduleB: './modules/moduleB/index.js',
    moduleC: './modules/moduleB/v1/index.js',
    moduleC: './modules/moduleB/v2/index.js',
  },
}

我是这样解决它的(webpack4)

const config = {
entry: {
        moduleA: './modules/moduleA/index.js',
        moduleB: './modules/moduleB/index.js',
        'moduleC/v1/moduleC': './modules/moduleB/v1/index.js',
        'moduleC/v2/MoculeC': './modules/moduleB/v2/index.js',
      },
    }

1
谢谢,它像魔法一样奏效了,而且这绝对是最简单的解决方案。如果早三天遇到这个问题,我可能会更加困难 ;) - vdechef
1
现在应该接受这个答案。简单易行,无需外部工具。 - Giorgia Sambrotta
点赞。问题已解决。只需在输出:{}中添加filename:“[name].js”或将其删除即可。 - user3772108

10
请不要使用任何绕过方式,因为它会影响构建性能。 Webpack文件管理器插件 安装简单,只需将此标签复制到webpack.config.js的顶部即可。
const FileManagerPlugin = require('filemanager-webpack-plugin');

安装

npm install filemanager-webpack-plugin --save-dev

添加插件

module.exports = {
    plugins: [
        new FileManagerPlugin({
            onEnd: {
                copy: [
                    {source: 'www', destination: './vinod test 1/'},
                    {source: 'www', destination: './vinod testing 2/'},
                    {source: 'www', destination: './vinod testing 3/'},
                ],
            },
        }),
    ],
};

截图

输入图片描述


1
事件.在结束时.复制 - Benjineer

7

你肯定可以从webpack.config文件中返回配置数组,但如果你只想要一个文档文件夹中的副本,这不是最优解决方案,因为它会让webpack重新构建你的代码,将构建时间翻倍。

在这种情况下,我建议使用FileManagerWebpackPlugin插件:

const FileManagerPlugin = require('filemanager-webpack-plugin');
// ...
plugins: [
    // ...
    new FileManagerPlugin({
      onEnd: {
        copy: [{
          source: './dist/*.*',
          destination: './public/',
        }],
      },
    }),
],

7
如果在所有答案之后还不清楚,您也可以将输出到完全不同的目录(例如标准dist文件夹之外的目录)。 您可以通过使用根路径作为路径(因为您只有一个路径),并将完整的“目录部分”移动到entry选项来实现这一点(因为您可以拥有多个条目):
entry: {
  'dist/main': './src/index.js',
  'docs/main': './src/index.js'
},
output: {
  filename: '[name].js',
  path: path.resolve(__dirname, './'),
}

这个配置将生成 ./dist/main.js./docs/main.js 两个文件。


4

你只能有一个输出路径。

来自文档 https://github.com/webpack/docs/wiki/configuration#output

影响编译结果输出的选项。输出选项告诉Webpack如何将编译后的文件写入磁盘。请注意,虽然可以有多个入口点,但只指定了一个输出配置。

如果使用任何哈希值([hash]或[chunkhash]),请确保模块具有一致的排序顺序。使用OccurenceOrderPlugin或recordsPath。


谢谢。我会留下这个问题,以防有人能够想出解决方法。 - spb
你需要两个输出路径的使用场景是什么?听起来像是你想要两个应用程序或一个应用程序和一个模块。 - ex-zac-tly
我原本认为需要一个专门用于文件加载器生成的输出的插件,因为所有内容都会进入项目的根目录,而我希望它们在自己的文件夹中。最终,我只是在加载器本身中重定向了输出路径,具体请参见下面的答案。 - spb
1
这并不完全正确。在技术上,你只能指定一个输出路径,但它将适用于条目对象中的每个键,从而允许您拥有多个输出 -- https://webpack.js.org/concepts/entry-points/ - sanjsanj

3

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