8
votes

I am trying to bundle every angular module in webpack. My target is to have one app.js that will be bundled by webpack with this configuration:

entry: {
        app: "./app/app.js"
},
output: {
        path: "./build/ClientBin",
        filename: "bundle.js"
},

I will place this bundle script in my index.html so it will entry point of my app. Also I have many modules in ./app/components folder. Folder structure in like:

app
|--components
|  |
|  |--home
|  |  |
|  |  |--home.html
|  |  |--home.js
|--app.js
|--AppController.js

I have required home.html in home.js so when I load home.js all of its needed files will load. The problem is I have several components like home and I want to tell webpack to bundle each component separately and name it with its containing folder like home.

How can I config webpack to create these bundles and put them in ./build/components?

4

4 Answers

20
votes

A simpler way:

Use globs in your webpack.config.js:

Here's an example:

var glob = require("glob");

module.exports = {
  entry: {
     js: glob.sync("./app/components/**/*.js"),  
  }
}
4
votes

You can achieve what you want like this:

entry: {
    home: './app/app.js',
    page: './page/app.js',
},
output: {
    path: './build/ClientBin',
    filename: '[name].js',
},

This will generate home.js and page.js at your output path. Tweak, generalize as needed. You'll probably want to extract those entry paths to a variable and so on.

Note that with a bit of tweaking you are likely able to output the bundles exactly where you want. I expect you would then use a path like ./app/components/[name] or so.

4
votes

To have each file exported individually, you can use the following code snippet to do so:

const glob = require('glob')
const path = require('path')

const entryFiles = glob.sync('./app/components/**/*.js').reduce((previousValue, currentValue, currentIndex, array) => {
  return typeof previousValue === 'string' ?
    {
      [path.basename(previousValue, path.extname(previousValue))]: previousValue,
      [path.basename(currentValue, path.extname(currentValue))]: currentValue
    }
    :
    { ...previousValue, [path.basename(currentValue, path.extname(currentValue))]: currentValue }
})

module.exports = {
  entry: entryFiles,
  resolve: {
    extensions: [ '.js' ]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'build', 'ClientBin')
  }
}
3
votes

I ended up defining entries programmatically. I wrote this in my webpack.config.js:

function getDirectories(srcpath) {
    return fs.readdirSync(srcpath).filter(function (file) {
        return fs.statSync(path.join(srcpath, file)).isDirectory();
    });
}

var entry = {
    app: "./app/app.ts",
    vendor: ["angular", "oclazyload", "angular-new-router", "lodash"]
};
var components = getDirectories("./app/components");
for (var i = 0; i < components.length; i++) {
    entry[components[i]] = "./app/components/" + components[i] + "/" + components[i] + ".ts";
}

And then used entry variable in config.