Как динамически разделить по каталогам с помощью плагина Webpack/SplitChunks?
Я пытаюсь разделить код React (созданный с помощью create-реагировать-приложение) с помощью плагина splitChunks следующим образом:
У меня есть следующие компоненты (JSX) структура:
- Сервисы
- serviceA
- ComponentA1
- ComponentA2
- пОДПАПКА
- ComponentA3
- ...
- serviceB
- ComponentB1
- ComponentB2
- ...
- serviceC
- ComponentB1
- ComponentB2
- ...
- ...
- serviceA
и я хочу иметь следующий вывод (сборка):
- статические / JS
- serviceA
- serviceA.bundle.chunkhash.js
- serviceB
- serviceB.bundle.chunkhash.js
- serviceC
- serviceC.bundle.chunkhash.js
- serviceA
(другие среды выполнения / сети находятся в корне / static/js)
Другое ограничение заключается в том, что компоненты загружаются динамически с
const Component = lazy(() => import(componentPath));
...
<Suspense fallback={..}>Component</suspense>
"componentPath" определяется на лету (когда пользователь нажимает на значок, он открывает данный сервис).
Причина этого заключается в том, что я хочу включить каждый пакет в отдельный образ Docker, на котором выполняется серверная часть. Тогда каждый образ Docker доступен благодаря маршрутизации приложений:
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
До сих пор я пытался:
- установите для output.chunkFilename значение [name]/[name].[chunkhash].js
используйте webpackChunkName с [name] и [request]:
[имя], похоже, не работает (буквально буквально "[имя]" является частью моего имени каталога).
[request] выравнивает название каталогов:
serviceA-ComponentA1 serviceA-ComponentA2 serviceA-subFolder-ComponentA3 serviceB-компонент B1 сервис B-компонент B2 ...
Затем я попытался использовать плагин splitChunks со следующим:
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
},
}
},
Этот подход выглядит как работающий, так как все мои сервисы находятся в своих собственных каталогах. Но у меня все еще есть некоторые дополнительные каталоги в виде чисел (вероятно, идентификатор пакета), которые я бы предпочел включить в стандартную.
Итак, вопрос в том, правильный ли мой подход?
0 ответов
Я не уверен, подойдет ли вам следующий вариант. У меня была аналогичная проблема, когда мне нужно было, чтобы разные папки выводились в разных пакетах.
В моем случае я начал с предложенного здесь решения glob. Затем, зная, что мне нужен массив входных данных для каждого желаемого результата, я придумал следующее:
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,
};
Это упрощенная версия моей конфигурации, и ее, вероятно, можно было бы улучшить, но она отлично подходит для моих нужд.:)
Дополнительная информация о библиотеке glob: https://github.com/isaacs/node-glob