102

How to set multiple file entry/output in project with webpack?

I follow http://webpack.github.io/docs/tutorials/getting-started/ success compile if only one file in one entry/output...

directory

app
webpack.config.js
./assets
././javascripts/Administrator/Article/Create/Base.js
././javascripts/Administrator/Article/Edit/Base.js
././javascripts/Account/Index/Base.js
././javascripts/Contact/Index/Base.js
...

how to output like this?

././javascripts/Administrator/Article/Create/bundle.js
././javascripts/Administrator/Article/Edit/bundle.js
././javascripts/Account/Index/bundle.js
././javascripts/Contact/Index/bundle.js

webpack.config.js

module.exports = {
  entry: {
    'AdministratorArticleCreate':['./assets/javascripts/Administrator/Article/Create/Base.js']
  },
  output: {
    path: 
  }

    // if only one file
    // entry: "./assets/javascripts/Administrator/Article/Create/Base.js",
    // output: {
    //     // path: __dirname,
    //     path: "./assets/javascripts/Administrator/Article/Create/",
    //     filename: "bundle.js"
    // }
};
user1775888
  • 3,147
  • 13
  • 45
  • 65
  • 1
    I also met this problem and cannot find any solution. Would be great if someone could share a solution – Kania Oct 09 '15 at 13:27

9 Answers9

90

For many entry points use arrays as a value of entry property:

entry: {
  app: ['./app/main.js', '.lib/index.js'],
  vendors: ['react']
}

app and vendors are arrays, so you can put there as many file paths as you need.

For output case:

output: {
  path: staticPath,
  filename: '[name].js'
}

The [name] is taken from entry properties, so if we have app and vendors as properties, we got 2 output files - app.js and vendors.js.

Documentation link

aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
Kania
  • 2,342
  • 4
  • 28
  • 36
86

If you want to output to multiple directories, you can use the path as the entry name. For example if you want this directory structure:

apps
├── dir1
│   └── js
│       ├── main.js [entry 1]
│       └── bundle.js [output 1]
└── dir2
    ├── index.js [entry 2]
    └── foo.js [output 2]

Then try this in your module.exports:

{
  entry: {
    'dir1/js/bundle': path.resolve(__dirname, '/apps/dir1/js/main.js'),
    'dir2/foo' : path.resolve(__dirname, '/apps/dir2/index.js')
  },
  output: {
    path: path.resolve(__dirname, '/apps'),
    filename: '[name].js'
  },
  ...
}
Peter Tseng
  • 13,613
  • 4
  • 67
  • 57
40

what really solved it for me was this:

entry:  {
    app : __dirname + "/app/views/app/app.js",
    admin : __dirname + "/app/views/admin/admin.js"
}

output: {
    path: __dirname + "/public",
    filename: "[name].js"
},
mbuechmann
  • 5,413
  • 5
  • 27
  • 40
João Sobral
  • 411
  • 4
  • 6
  • 5
    The only thing I would note is that this uses the key to replace "[name]" so you can't have invalid characters in the key (e.g. _local-admin_ would not be valid), but this is rather minor. – Sirius_B Aug 02 '16 at 20:41
12

You can detect multiple entries and generate separate output files by using glob sync patterns.

Put this into your webpack.config.js (without the ...)

const glob = require("glob");
...
module.exports = (env, options) => ({
  ...
  entry: glob.sync("./javascripts/**/*.js").reduce((acc, item) => {
    const path = item.split("/");
    path.pop();
    const name = path.join('/');
    acc[name] = item;
    return acc;
  }, {}),
  output: {
    filename: "[name]/bundle.js",
    path: path.resolve(__dirname, "")
  },
  ...
});

This "should" give you the desired output.

Peter
  • 1,110
  • 10
  • 25
9

What if you want to get output files as foo.css and bar.js at the same time? the answers above seem incapable to handle this.

The sane way is to use multi-compiler. One input file one config object one output file. From this answer.

tcpiper
  • 2,456
  • 2
  • 28
  • 41
5

this webpack plugin web-webpack-plugin can resolve it in a sample way.

AutoWebPlugin can find all page entry in an directory,then auto config an WebPlugin for every page to output an html file,you can use it as below:

webpack config

module.exports = {
    plugins: [
        new AutoWebPlugin(
            // the directory hold all pages
            './src/', 
            {
            // the template file path used by all pages
            template: './src/template.html',
            // javascript main file for current page,if it is null will use index.js in current page directory as main file
            entity: null,
            // extract common chunk for all pages and then put it into a file named common,if it is null then not do extract action
            // achieve by CommonsChunkPlugin
            commonsChunk: 'common',
            // pre append to all page's entry
            preEntrys:['./path/to/file1.js'],
            // post append to all page's entry
            postEntrys:['./path/to/file2.js'],
        }),
    ]
};

src directory

── src
│   ├── home
│   │   └── index.js
│   ├── ie_polyfill.js
│   ├── login
│   │   └── index.js
│   ├── polyfill.js
│   ├── signup
│   │   └── index.js
│   └── template.html

output directory

├── dist
│   ├── common.js
│   ├── home.html
│   ├── home.js
│   ├── ie_polyfill.js
│   ├── login.html
│   ├── login.js
│   ├── polyfill.js
│   ├── signup.html
│   └── signup.js

AutoWebPlugin find all page home login signup directory in ./src/,for this three page home login signup will use index.js as main file and output three html file home.html login.html signup.html`

see doc:auto detect html entry

吴浩麟
  • 141
  • 2
  • 6
2

This question is 2 years old so I think the author has almost certainly moved on from this issue, but to anyone landing here more recently I had a really similar need and was able to write my own plugin to allow for dynamic output paths/names from known and/or unknown entry points.

My problem and thought process for the solution can be found here.

And the Node package itself here.

sanjsanj
  • 1,003
  • 9
  • 20
1

For my use case I actually needed to use different templates based on environment. To achieve this I passed in the NODE_ENV variable

module.exports = (env, argv) => {
  const ENVIRONMENT = env.NODE_ENV;
  let INDEX_HTML = 'index.html';
  if (ENVIRONMENT === 'staging') {
    INDEX_HTML = 'index-stg.html';
  }

Then:

if (NODE_ENV === 'staging') {
   INDEX_HTML = 'index-stg.html';
}

In the output:

output: {
      path: process.cwd() + '/build',
      filename: `[name].js`,
      chunkFilename: `[${HASH_MODE}].[name].js`
    },

plugins:

new HtmlWebpackPlugin({
        inject: true,
        template: `app/${INDEX_HTML}`,
      }),
llamacorn
  • 551
  • 4
  • 23
1

Using the following, I was able to get webpack to search for typescript and sass files.

...
entry: glob
  .sync("./src/{sass,js}/**/*.{ts,scss}")
  .reduce(function (obj, el) {
    obj[path.parse(el).name] = el;
    return obj;
  }, {}),
...
Bayo
  • 251
  • 2
  • 4