Reputation: 2400
I have a large amount of javascript files split into 4 subdirectory in my app. In grunt I grab all of them and compile them into one file. These files do not have a module.exports function.
I want to use webpack and split it into 4 parts. I don't want to manually go in and require all my files.
I would like to create a plugin that on compilation walks the directory trees, then grabs all the .js file names and paths, then requires all files in the sub directories and adds it to the output.
I want all the files in each directories compiled into a module that I could then require from my entry point file, or include in the assets that http://webpack.github.io/docs/plugins.html mentions.
When adding a new file I just want to drop it in the correct directory and know it will be included.
Is there a way to do this with webpack or a plugin that someone has written to do this?
Upvotes: 113
Views: 111734
Reputation: 3679
All merits to @splintor (thanks).
But here it is my own derived version.
Benefits:
{module_name: exports_obj}
object.
EDIT: If, like me, you're sure your modules won't return anything else than (at least at root level) a regular javascript object, you can also "mount" them replicating their original directory structure (see Code (Deep Version) section at the end).
Code (Original Version):
function requireAll(r) {
return Object.fromEntries(
r.keys().map(function(mpath, ...args) {
const result = r(mpath, ...args);
const name = mpath
.replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
.replace(/\//g, '_') // Relace '/'s by '_'s
;
return [name, result];
})
);
};
const allModules = requireAll(require.context(
// Any kind of variables cannot be used here
'@models' // (Webpack based) path
, true // Use subdirectories
, /\.js$/ // File name pattern
));
Example:
Sample output for eventual console.log(allModules);
:
{
main: { title: 'Webpack Express Playground' },
views_home: {
greeting: 'Welcome to Something!!',
title: 'Webpack Express Playground'
}
}
Directory tree:
models
├── main.js
└── views
└── home.js
Code (Deep Version):
function jsonSet(target, path, value) {
let current = target;
path = [...path]; // Detach
const item = path.pop();
path.forEach(function(key) {
(current[key] || (current[key] = {}));
current = current[key];
});
current[item] = value;
return target;
};
function requireAll(r) {
const gather = {};
r.keys().forEach(function(mpath, ...args) {
const result = r(mpath, ...args);
const path = mpath
.replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
.split('/')
;
jsonSet(gather, path, result);
});
return gather;
};
const models = requireAll(require.context(
// Any kind of variables cannot be used here
'@models' // (Webpack based) path
, true // Use subdirectories
, /\.js$/ // File name pattern
));
Example:
Result of previous example using this version:
{
main: { title: 'Webpack Express Playground' },
views: {
home: {
greeting: 'Welcome to Something!!',
title: 'Webpack Express Playground'
}
}
}
Upvotes: 2
Reputation: 15878
Example of how to get a map of all images in the current folder.
const IMAGES_REGEX = /\.(png|gif|ico|jpg|jpeg)$/;
function mapFiles(context) {
const keys = context.keys();
const values = keys.map(context);
return keys.reduce((accumulator, key, index) => ({
...accumulator,
[key]: values[index],
}), {});
}
const allImages = mapFiles(require.context('./', true, IMAGES_REGEX));
Upvotes: 3
Reputation: 21
this works for me :
function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./js/', true, /\.js$/));
NOTE: this can require .js files in subdirs of ./js/ recursively.
Upvotes: 1
Reputation: 21497
How about a map of all the files in a folder?
// {
// './image1.png': 'data:image/png;base64,iVBORw0KGgoAAAANS',
// './image2.png': 'data:image/png;base64,iVBP7aCASUUASf892',
// }
Do this:
const allFiles = (ctx => {
let keys = ctx.keys();
let values = keys.map(ctx);
return keys.reduce((o, k, i) => { o[k] = values[i]; return o; }, {});
})(require.context('./path/to/folder', true, /.*/));
Upvotes: 12
Reputation: 2400
In my app file I ended up putting the require
require.context(
"./common", // context folder
true, // include subdirectories
/.*/ // RegExp
)("./" + expr + "")
courtesy of this post: https://github.com/webpack/webpack/issues/118
It is now adding all my files. I have a loader for html and css and it seems to work great.
Upvotes: 43
Reputation: 10154
This is what I did to achieve this:
function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./modules/', true, /\.js$/));
Upvotes: 136