Reputation: 71
I'm trying to split my React code (created with create-react-app) with the splitChunks plugin in the following way :
I have following components (JSX) structure :
and I want to have following output (build) :
(other runtimes / mains are at the root of /static/js)
Another restriction is that components are loaded dynamically with
const Component = lazy(() => import(componentPath));
...
<Suspense fallback={..}>Component</suspense>
"componentPath" is determined on the fly (when a user clicks on an icon then it opens a given service).
The reason for this is that I want to include each bundle into a separate Docker image running the backend. Then each Docker image is reachable thanks to Application routing :
static/js/serviceA/ ==> js served by Docker container running service A
static/js/serviceB/ ==> js served by Docker container running service B
static/js/serviceC/ ==> js served by Docker container running service C
So far, I'v tried to:
use the webpackChunkName with [name] and [request]:
[name] doesn't seem to work (got just litterally "[name]" as part of my directory name).
[request] flattens the name of the directories:
serviceA-ComponentA1 serviceA-ComponentA2 serviceA-subFolder-ComponentA3 serviceB-componentB1 serviceB-componentB2 ...
Then I tried to use the splitChunks plugin with following :
splitChunks: {
chunks: 'all',
name: function(module) {
let serviceName = module.rawRequest ? module.rawRequest : 'default';
serviceName = serviceName.replace('../', '').replace('./', '');
serviceName = serviceName.split('/')[0];
return serviceName;
},
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
},
serviceA: {
test: /[\\/]serviceA[\\/]/,
priority: -10
},
serviceB: {
test: /[\\/]serviceB[\\/]/,
priority: -10
},
serviceC: {
test: /[\\/]serviceC[\\/]/,
priority: -10
},
}
},
This approach looks like working as all my services are in their own directories. But I still have some additional directories as numbers (bundle ID probably) that I would have expect to be rather included into the default.
So the question is : is my approach correct ?
Upvotes: 7
Views: 2325
Reputation: 1398
I'm not sure if the following option would work for you. I had a similar problem, where I needed different folders to be outputed on different bundles.
In my case, I started with the glob solution, suggested here. Then, knowing that I needed an array of inputs for each desired output, I came up with this:
const path = require('path');
const glob = require('glob');
const plugins = [...];
module.exports = {
entry: glob.sync('./src/**/*.js').reduce((acc, item) => {
const path = item.split('/');
path.pop();
const rootFolder = path[2] ? `${path[0]}/${path[2]}` : path[0];
if (acc[rootFolder]) {
acc[rootFolder].push(item);
} else {
acc[rootFolder] = [item];
}
return acc;
}, {}),
output: {
filename: '[name]/main.js',
path: path.resolve(__dirname, 'dist'),
},
module: { ... },
plugins,
};
This is a simplified version of my config and it could probably be improved, but it works fine for my needs. :)
More info on glob library: https://github.com/isaacs/node-glob
Upvotes: 1