Reputation: 23383
I have a folder structure for my JS modules. I want one module per page. This is not a single page app.
How can I output files in a folder structure?
From what I can see, the only possibility is to output [name].js
. This could work if I make the names very unique, or I could make the names have a -
for a folder separator. That would mean a/b/c.js
would translate to name a-b-c
. I really don't like this. I would like to be able to require("a/b/c")
.
From what I can tell, I can't use a single bundled file either because require
is not available outside of the module. If it was, I could just build a single bundle and require("a/b/c")
on every page.
If there is a good way to do this that I'm not finding on the internet, please let me know.
It looks like I'm able to easily do this with require.js using r.js, but I don't want to use require.js and would like CommonJS modules.
Upvotes: 11
Views: 9217
Reputation: 2119
With a little wrangling with node you can create an entry
object to pass in the config. In my case I used the name of the folders of the second level to create different bundles, but you can easily adapt to your needs.
const path = require('path');
var glob = require('glob')
const exportPath = path.resolve(__dirname,`./../public/javascripts/plugins`);
// create a glob of files
const entryArray = glob.sync('./plugins/**/{svg,src}/**/*.*');
/**
* Create a dictionary of entries in format: folder: ['file', 'file2']
* https://webpack.js.org/configuration/entry-context/#entry
*/
var folders = []
var entries = {};
// list unique folders
entryArray.map((item) => {
const folderName = item.split('/')[2];
if (!folders.includes(folderName)) {
folders.push(folderName);
}
});
// assign files to each folder
folders.map((folder) => {
var imports = [];
entryArray.map((item) => {
const folderName = item.split('/')[2];
if (folder == folderName) {
imports.push(item);
}
});
entries[folder] = imports
});
module.exports = {
entry: entries,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
query: {
presets: [ '@babel/preset-env' ],
},
}
],
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
require('postcss-nested-ancestors'),
require('postcss-nested')
]
}
}
]
},
{
test: /\.svg$/,
loader: 'svg-inline-loader?removeSVGTagAttrs=false'
}
],
},
output: {
path: exportPath,
filename: '[name]/dist/bundle.js',
libraryTarget: 'umd',
libraryExport: 'default'
}
};
Upvotes: 0
Reputation: 691
You can define an entry point using slash, like this:
entry: {
"main-plugin/js/background":"./src/main-plugin/background"
}
And output
like this:
output: {
path: path.join(__dirname, 'public'),
filename: '[name].js'
},
This setup will create a public/main-plugin/js
folder and will place the background.js
into it. It works at least on Win7x64
.
Upvotes: 14
Reputation: 59
You can use [name] to make new folders too. Like this:
output: {
path: __dirname,
filename: '[name]/[name].js',
chunkFilename: '[name].js',
publicPath: '/assets/'
},
Upvotes: 1