Dynamic Entries in Webpack

To create dynamic entries in Webpack by making use of glob.
If you are in hurry then check the below code otherwise you are most welcome to read the complete article for every aspects.

// dynamic entry
glob.sync('./directory-to-search-in/**/assets/js/**/*.js').reduce((acc, item) => {
    /**
        * The "[name]" placeholder in the "output" property will be replaced
        * with each key name in our "name" object. We replace .js so that we can use    
        * our js file with its name. ex path/a.js as path/a
        */
    var name = item.replace(/\.\/Modules\/|\.js/gi, '');
    acc[name] = item;
    // add entry for each js file 
    Encore.addEntry(name, item);
    return acc;
}, {});

Why we need dynamic entries?

In general we have a huge file structure and in case we have a modular structure or something like plugins based system then how can we manage assets of each plugin, any number of plugins can be installed. we are not going to add entry manually for each plugin installed.
Assuming that we have a file structure for a project is something.

Project
--  Modules
|    -- Module-abc
|        -- Assets
|            -- Js
|                -- app.js
|                -- app-vue.js
|    -- Module-xyz
|        -- Assets
|            -- Js
|                -- xyz.js
|                -- style.js

As per above file structure, in general we need to create entry for each of the Js file and every time we add any new module to our project which is not a good solution.

Creating Dynamic Entries in Webpack

Types of entries in Webpack Config

We can create a single entry in webpack.config.js which will include every assets file. The entry property of Webpack config allow us to do so.
entry property can accept:

  • String :
    ‘./Modules/Modules-abc/Assets/Js/app.js’
  • Array of Strings:
    [
    ‘./Modules/Module-abc/Assets/Js/app.js’,
    ‘./Modules/Module-abc/Assets/Js/app-vue.js’
    ]
  • Object:
    {
    ‘js/app’: ‘./Modules/Modules-abc/Assets/Js/app.js’,
    ‘js/app-vue’: ‘./Modules/Modules-abc/Assets/Js/app-vue.js’
    }

Adding Dynamic enteries to config file

We use ‘glob‘ for this, When passed a string, Glob will attempt to find each file that matches the path given and return each path to the file as string array.

webpack.config.js
we are considering the example for Symfony but the process is same in any framework.

var Encore = require('@symfony/webpack-encore');
/**
 * When passed a string, Glob will attempt to find each file that matches the
 * path given and return each path to the file as string[]
 */
const glob = require('glob')

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/resource/')
    .setPublicPath('/resource')
    .enableSourceMaps(!Encore.isProduction())

   // dynamic entry
   glob.sync('./Modules/**/assets/js/**/*.js').reduce((acc, item) => {
       /**
         * The "[name]" placeholder in the "output" property will be replaced
         * with each key name in our "name" object. We replace .js so that we can use    
         * our js file with its name. ex Module-abc/assets/js/a.js as Module-abc/assets/js/a
         */
       var name = item.replace(/\.\/Modules\/|\.js/gi, '');
       acc[name] = item;
       // add entry for each js file 
       Encore.addEntry(name, item);
       return acc;
   }, {});

  // module.exports = Encore.getWebpackConfig();
  const config = Encore.getWebpackConfig();
  
  // Export the final configuration
  module.exports = config;

Adding dynamic entries in core Webpack

entry: glob.sync('./Modules/**/assets/js/**/*.js').reduce((acc, path) => {
    /**
        * The "[name]" placeholder in the "output" property will be replaced
        * with each key name in our "name" object. We replace .js so that we can use    
        * our js file with its name. ex path/a.js as path/a
        */
    var name = item.replace(/\.\/Modules\/|\.js/gi, '');
    /**
        * each js file in the directory will be added to object
        */
    acc[name] = item;
    return acc
}, {}),

Elucidation

  • Glob plays an important role here, we pass a string ‘./Modules/**/assets/js/**/*.js’ this string tells glob to search for .js file in assets/js directory inside Modules
  • Glob return each matched file path.
  • Then we replace .js extension as to define the path with the same name as our file name.

1 thought on “Dynamic Entries in Webpack”

Leave a Comment

Your email address will not be published. Required fields are marked *

%d bloggers like this: