【问题标题】:How to create multiple output paths in Webpack config如何在 Webpack 配置中创建多个输出路径
【发布时间】:2016-06-24 12:22:42
【问题描述】:

有谁知道如何在 webpack.config.js 文件中创建多个输出路径?我正在使用带有一些不同字体文件等的 bootstrap-sass。为了让 webpack 处理这些,我已经包含了正常工作的文件加载器,但是它输出的文件被保存到我指定的输出路径中我的其余文件:

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

我想实现一些东西,我可以查看任何 webpack 输出的扩展类型,以及以 .woff .eot 等结尾的东西,将它们转移到不同的输出路径。这可能吗?

我做了一点谷歌搜索,在 github 上发现了这个 *issue,其中提供了几个解决方案,编辑:

但看起来你需要知道入口点才能使用散列方法指定输出 例如:

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

然而,就我而言,就字体文件而言,输入过程有点抽象,我只知道输出。在我的其他文件正在进行转换的情况下,有一个已知点我需要它们然后由我的加载器处理。如果有办法找出这一步发生在哪里,我可以使用 hash 方法自定义输出路径,但我不知道这些文件在哪里需要。

【问题讨论】:

    标签: path output config webpack loader


    【解决方案1】:

    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
    

    【讨论】:

    • 在我的情况下,我希望一个输出不包含 chunkhash,有什么简单的解决方案吗?谢谢。
    • @zhengkenghong 我相信生成的输出路径中需要dist。因此,而不是 module/a/index.js 作为输出路径,它应该是 module/a/dist/index.js 否则,您将覆盖您的入口文件。
    • @Sung dist 文件夹已在输出路径中配置。所以生成的文件实际上是dist/module/a/index.js,我没有提到。
    • 我认为这应该是公认的答案,因为它是来自 webpack 4 文档的答案。 -> webpack.js.org/concepts/output/#multiple-entry-points
    • @raRaRa 迟到了,但您可以使用output.filename 的函数来做到这一点,如下所述:webpack.js.org/configuration/output/#outputfilename
    【解决方案2】:

    我不确定我们是否有同样的问题,因为截至 2016 年 6 月,webpack 仅支持每个配置一个输出。我猜你已经看到了 issue on 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中的{...}扩展运算符。

    【讨论】:

    • 我没有运行sn-p,可能会出现一些错误或拼写错误
    • 我确实运行了你的 sn-p,像魅力一样工作......很惊讶没有人发现这一点,呃前端开发人员,没有耐心,总是很匆忙;-)。我以相同的方式导出配置,但我的声明不同/标准: var config = { entry: SOURCE_DIR + '/index.jsx', .... } 也没有使用任何多编译器:-\
    • 或者你可以在 npm 中做一个 webpack && cp etc
    • 这对我来说非常有用,既可以在原始文件夹中部署一个 npm 包(那里有自动测试),也可以在实现该包的应用程序的文件夹中。通过这种方式,我可以跳过 npm 下载步骤并实时测试我更新的包代码,直到新版本稳定并准备好在 npm 上发布。
    •  var config = { // TODO: 添加通用配置模块: {}, }; 
      module{} 对象不正确。这不是必需的。它将与关键字nameentryoutput(来自您的示例)在同一级别进行扩展/合并。
       { module: { mode: "development", devtool: "source-map" } }, name: "a", entry: "./a/app", output: { path: "/a ", 文件名: "bundle.js" } } 
    【解决方案3】:

    您现在可以(从 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]' }
      }
    };
    

    【讨论】:

    • 请注意,webpack 5.0 目前仍处于测试阶段
    • 找了这么多,终于找到有用的了!!
    • @bryanph 不再。
    • 从现在开始应该是公认的答案。
    • 非常感谢,真的是一个非常有用的答案。尽管由于某种原因 [ext] 不起作用,我必须手动添加文件扩展名,否则 [ext] 将连接到文件名,因此:about: { import: './about.js', filename : 'unique/path/2/[name][ext]' } 将结束于 [ext]。请问有人遇到这个问题或者有这个原因吗?
    【解决方案4】:

    如果您可以使用具有相同深度和文件夹结构的多个输出路径,则可以在 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
    

    【讨论】:

    【解决方案5】:

    如果在所有答案后不明显,您还可以输出到完全不同的目录(例如标准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

    【讨论】:

      【解决方案6】:

      您绝对可以从您的 webpack.config 文件中返回配置数组。但是,如果您只想将工件的副本放在项目文档的文件夹中,这不是最佳解决方案,因为它会使 webpack 构建您的代码两倍,从而使总构建时间翻倍。

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

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

      【讨论】:

        【解决方案7】:

        请不要使用任何解决方法,因为它会影响构建性能。

        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/'},
                        ],
                    },
                }),
            ],
        };
        

        截图

        【讨论】:

        • 应该是events.onEnd.copy
        【解决方案8】:

        就我而言,我遇到了这种情况

        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',
              },
            }
        

        【讨论】:

        • 谢谢,它就像一个魅力,它是迄今为止最简单的解决方案。三天前,我会更加挣扎;)
        • 这应该是现在公认的答案。简单,无需外部工具。
        【解决方案9】:

        你只能有一个输出路径。

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

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

        如果您使用任何散列([hash] 或 [chunkhash]),请确保模块的顺序一致。使用 OccurenceOrderPlugin 或 recordsPath。

        【讨论】:

        • 谢谢。我会留下 Q 以防万一有人能想出解决方法。
        • 您需要 2 个输出路径的用例是什么?听起来您想要 2 个应用程序或 1 个应用程序和 1 个模块。
        • 我认为我需要一个专用于文件加载器生成的输出的文件加载器,它全部进入项目的根目录,而我希望它在它自己的文件夹中。我最后只是根据下面的回答重定向加载器本身的输出路径。
        • 这并不完全正确。从技术上讲,您只能指定一个输出路径,但它将应用于条目对象中的每个键,从而允许您有多个输出 -- webpack.js.org/concepts/entry-points
        【解决方案10】:

        我写了一个插件,希望能做你想做的事,你可以指定已知或未知的入口点(使用glob)并指定确切的输出或使用入口文件路径和名称动态生成它们。 https://www.npmjs.com/package/webpack-entry-plus

        【讨论】:

          【解决方案11】:

          你会喜欢的

          var config = {
              // TODO: Add common Configuration
              module: {},
          };
          
          var x= Object.assign({}, config, {
              name: "x",
              entry: "./public/x/js/x.js",
              output: {
                 path: __dirname+"/public/x/jsbuild",
                 filename: "xbundle.js"
              },
          });
          var y= Object.assign({}, config, {
              name: "y",
              entry: "./public/y/js/FBRscript.js",
              output: {
                 path: __dirname+"/public/fbr/jsbuild",
                 filename: "ybundle.js"
              },
          });
          
          let list=[x,y];
          
          for(item of list){
              module.exports =item;
          }
          

          【讨论】:

          【解决方案12】:

          我实际上只是进入了文件加载器模块中的 index.js 并更改了内容的发送位置。这可能不是最佳解决方案,但在有其他方法之前,这很好,因为我确切地知道这个加载器正在处理什么,这只是字体。

          //index.js
          var loaderUtils = require("loader-utils");
          module.exports = function(content) {
              this.cacheable && this.cacheable();
              if(!this.emitFile) throw new Error("emitFile is required from module system");
              var query = loaderUtils.parseQuery(this.query);
              var url = loaderUtils.interpolateName(this, query.name || "[hash].[ext]", {
                  context: query.context || this.options.context,
                  content: content,
                  regExp: query.regExp
              });
              this.emitFile("fonts/"+ url, content);//changed path to emit contents to "fonts" folder rather than project root
              return "module.exports = __webpack_public_path__ + " + JSON.stringify( url) + ";";
          }
          module.exports.raw = true;
          

          【讨论】:

          【解决方案13】:

          问题已经出在语言上:

          • entry(这是一个对象(键/值),用于定义输入*)
          • 输出(这是一个对象(键/值),用于定义输出*)

          基于有限占位符(如“[name]”)区分输出的想法定义了限制。

          我喜欢 webpack 的核心功能,但它的使用需要用基于逻辑和简单性的抽象定义进行重写……软件开发中最难的事情……逻辑和简单性。

          所有这些都可以通过提供输入/输出定义列表来解决...列表输入/输出定义。

          Vinod Kumar's 好的解决方法是:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-11-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-20
            • 2011-07-17
            相关资源
            最近更新 更多