12/11/2020

webpack

Multiple Webpack entry points with a wildcard

A how-to step by step.

The main goal for this approach was to make sure all .js files inside ..javascripts/pages are automatically added as entry points in webpack's configuration.

The project files' tree looks something like this:

source/
├── images/
├── javascripts/
|   ├── pages/
│   |   ├── about.js
│   |   ├── blog.js
│   |   ├── home.js
│   |   ├── labs.js
│   |   ├── proyects.js
│   |   └── staff.js
│   ├── mobile.js
│   ├── tweets.js
│   └── ...
├── stylesheet/
│   ├── all.css.scss
│   └── ...
├── home.html
├── about.html
├── webpack.config.js
└── ...

Several other programmers encountered the same challenge and this was Webpack's creator suggested solution.

// webpack.config.js
const path = require('path');
const glob = require('glob');

module.exports = {
  mode: 'development',
  entry: glob.sync('./source/javascripts/pages/*.js'),
  output: {
    path: path.resolve(__dirname, '.tmp/dist'),
    filename: '[name].min.js',
  },

After implementing the solution above, all .js files end up minified in a single output file named main.min.js under a new path: .tmp/dist.

.temp/dist/
├── main.min.js
source/
├── javascripts/
|   ├── ...

This approach would work just fine if all html pages in the project had a script tag somewhere linking to that main.min.js file. However, the final goal was to generate a minified.js file for each file included in the Webpack entry point.

// webpack.config.js

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

module.exports = {
  mode: 'development',
  
  // First we generate the array of file paths with glob.sync()
  // Then we create an object from that array of strings
  entry: glob.sync('./source/javascripts/pages/*.js').reduce((files, path) => {
    const name = path.split('/').pop().replace(/\.[^]+$/, '')
    return { ...files, [name]: path }
  }, {}),
  output: {
    path: path.resolve(__dirname, '.tmp/dist'),
    filename: '[name].min.js',
  },

Result

module.exports = {
  mode: 'development',
  
  // The final solution ends up generating the following object
  entry: {
    about: "./source/javascripts/pages/about.js",
    blog: "./source/javascripts/pages/blog.js",
    home: "./source/javascripts/pages/home.js",
    labs: "./source/javascripts/pages/labs.js",
    projects: "./source/javascripts/pages/projects.js",
    staff: "./source/javascripts/pages/staff.js"
  }