@pixolith/webpack-sw6-config 11.0.9 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixolith/webpack-sw6-config",
3
3
  "public": true,
4
- "version": "11.0.9",
4
+ "version": "12.0.0",
5
5
  "description": "",
6
6
  "main": "src/index.js",
7
7
  "scripts": {},
@@ -21,7 +21,7 @@
21
21
  "url": "https://github.com/pixolith/webpack-plugins/issues"
22
22
  },
23
23
  "homepage": "https://github.com/pixolith/webpack-plugins/tree/master/packages/webpack-hook-plugin/#readme",
24
- "gitHead": "043bba0319a06f598d397a462d9c25609bddc4bc",
24
+ "gitHead": "5c29b0a4c1b2e0876f25a05f517100c83fc9a36c",
25
25
  "dependencies": {
26
26
  "@babel/cli": "7.25.9",
27
27
  "@babel/core": "^7.26.0",
@@ -29,15 +29,15 @@
29
29
  "@babel/plugin-proposal-decorators": "7.25.9",
30
30
  "@babel/preset-env": "7.26.0",
31
31
  "@babel/preset-typescript": "7.26.0",
32
- "@pixolith/eslint-config-sw6": "^11.0.0",
33
- "@pixolith/external-svg-sprite-loader": "^11.0.0",
34
- "@pixolith/stylelint-config-standard": "^11.0.0",
35
- "@pixolith/webpack-assets-copy-plugin": "^11.0.0",
36
- "@pixolith/webpack-filename-linter-plugin": "^11.0.0",
37
- "@pixolith/webpack-hook-plugin": "^11.0.0",
38
- "@pixolith/webpack-sw6-plugin-map-emitter": "^11.0.0",
39
- "@pixolith/webpack-twig-assets-emitter-plugin": "^11.0.8",
40
- "@pixolith/webpack-watcher": "^11.0.5",
32
+ "@pixolith/eslint-config-sw6": "^12.0.0",
33
+ "@pixolith/external-svg-sprite-loader": "^12.0.0",
34
+ "@pixolith/stylelint-config-standard": "^12.0.0",
35
+ "@pixolith/webpack-assets-copy-plugin": "^12.0.0",
36
+ "@pixolith/webpack-filename-linter-plugin": "^12.0.0",
37
+ "@pixolith/webpack-hook-plugin": "^12.0.0",
38
+ "@pixolith/webpack-sw6-plugin-map-emitter": "^12.0.0",
39
+ "@pixolith/webpack-twig-assets-emitter-plugin": "^12.0.0",
40
+ "@pixolith/webpack-watcher": "^12.0.0",
41
41
  "@swc/core": "^1.9.3",
42
42
  "autoprefixer": "^10.4.20",
43
43
  "babel-loader": "^9.2.1",
package/src/config.js CHANGED
@@ -6,11 +6,22 @@ const config = {
6
6
  isProd: process.env.NODE_ENV === 'production',
7
7
  isDebug: !!process.env.DEBUG || false,
8
8
  shopwareMode: process.env.SHOPWARE_MODE,
9
- shopwareVersion: process.env.SHOPWARE_VERSION || '6.6',
10
9
 
11
10
  assetUrl: process.env.ASSET_URL || '/',
12
11
  pluginPrefixes: process.env.PLUGIN_PREFIXES || 'Pxsw',
13
12
 
13
+ // Multi-theme build configuration (mandatory in v12+)
14
+ themeNames: process.env.THEME_NAMES
15
+ ? process.env.THEME_NAMES.split(',')
16
+ .map((s) => s.trim())
17
+ .filter(Boolean)
18
+ : [],
19
+ skipPlugins: process.env.SKIP_PLUGINS
20
+ ? process.env.SKIP_PLUGINS.split(',')
21
+ .map((s) => s.trim())
22
+ .filter(Boolean)
23
+ : [],
24
+
14
25
  pxSharedPath: process.env.SHARED_SCSS_PATH || '../../shared',
15
26
  scssFolder: process.env.SCSS_FOLDER || 'scss',
16
27
  jsFolder: process.env.JS_FOLDER || 'js',
@@ -32,11 +43,35 @@ const config = {
32
43
  shopwareVendorPath: Path.join(process.cwd(), 'vendor/shopware/storefront/Resources/app/storefront/vendor'),
33
44
  shopwarePluginPath: Path.join(process.cwd(), 'vendor/shopware/storefront/Resources/app/storefront/src'),
34
45
 
35
- allowedExtensions: ['.ts', '.js', '.scss', '.css', '.svg']
46
+ allowedExtensions: ['.ts', '.js', '.scss', '.css', '.svg'],
47
+ };
48
+
49
+ // PICKED_THEME: optional filter to build/watch a single theme from THEME_NAMES
50
+ let pickedTheme = process.env.PICKED_THEME
51
+ ? process.env.PICKED_THEME.trim()
52
+ : '';
53
+
54
+ if (pickedTheme && config.themeNames.indexOf(pickedTheme) === -1) {
55
+ process.stderr.write(
56
+ `PICKED_THEME "${pickedTheme}" is not in THEME_NAMES [${config.themeNames.join(', ')}].\n`,
57
+ );
58
+ process.exit(1);
36
59
  }
37
60
 
38
- const pxEntryPath = process.env.PX_ENTRY_PATH || (process.env.SHOPWARE_MODE === 'storefront' ? 'src/Resources/app/storefront/private' : 'src/Resources/app/administration/src');
39
- const pxRouteSplitPath = process.env.PX_ROUTE_SPLIT_PATH || (process.env.SHOPWARE_MODE === 'storefront' ? 'src/Resources/app/storefront/private/scss-route-split/*' : '');
61
+ // buildThemes: the subset of themeNames that actually get compiled
62
+ // themeNames stays as the full list (used for _global_resources exclusion)
63
+ config.buildThemes = pickedTheme ? [pickedTheme] : config.themeNames;
64
+
65
+ const pxEntryPath =
66
+ process.env.PX_ENTRY_PATH ||
67
+ (process.env.SHOPWARE_MODE === 'storefront'
68
+ ? 'src/Resources/app/storefront/private'
69
+ : 'src/Resources/app/administration/src');
70
+ const pxRouteSplitPath =
71
+ process.env.PX_ROUTE_SPLIT_PATH ||
72
+ (process.env.SHOPWARE_MODE === 'storefront'
73
+ ? 'src/Resources/app/storefront/private/scss-route-split/*'
74
+ : '');
40
75
 
41
76
  // Create a glob regex to match the plugin prefixes
42
77
  let prefixes = config.pluginPrefixes.split(',').map(p => `${p}*`).join('|');
@@ -49,6 +84,7 @@ const routeSplitMatch = new RegExp(`/scss-route-split\/([\\w-]*)`);
49
84
 
50
85
  module.exports = {
51
86
  ...config,
87
+
52
88
  pluginSrcPath: Path.join(pluginSrcPath, pxEntryPath),
53
89
  pluginScssPath: Path.join(pluginSrcPath, pxEntryPath, config.scssFolder),
54
90
  pluginJsPath: Path.join(pluginSrcPath, pxEntryPath, config.jsFolder),
@@ -70,5 +106,9 @@ module.exports = {
70
106
  pluginRouteSplitPath: Path.join(pluginSrcPath, pxRouteSplitPath),
71
107
  vendorRouteSplitPath: Path.join(vendorSrcPath, pxRouteSplitPath),
72
108
 
73
- resourcesPath: process.env.RESOURCES_PATHS
74
- }
109
+ // Raw glob base paths for multi-theme resource resolution
110
+ pluginGlobBase: pluginSrcPath,
111
+ vendorGlobBase: vendorSrcPath,
112
+ pxEntryPath: pxEntryPath,
113
+ resourcesPath: process.env.RESOURCES_PATHS,
114
+ };
package/src/index.js CHANGED
@@ -1,15 +1,20 @@
1
+ const Fs = require('fs');
2
+ const Glob = require('glob');
1
3
  const config = require('./config');
2
4
  const production = require('./webpack.config.production');
3
- const storefront = require('./webpack.config.storefront');
4
- const dev = require('./webpack.config.dev');
5
- const administration = require('./webpack.config.administration');
5
+ const createStorefrontConfig = require('./webpack.config.storefront');
6
+ const createDevConfig = require('./webpack.config.dev');
7
+ const createAdministrationConfig = require('./webpack.config.administration');
6
8
  const pkg = require('./../package.json');
7
9
  const watcher = require('@pixolith/webpack-watcher');
8
10
  const { merge } = require('webpack-merge');
11
+ const ChangeCase = require('change-case');
9
12
 
10
13
  const setup = () => {
11
14
  watcher.clean(config);
12
- watcher.run(null, config);
15
+ config.buildThemes.forEach((themeName) => {
16
+ watcher.compileTheme(themeName, config);
17
+ });
13
18
 
14
19
  if (config.isDebug) {
15
20
  console.table({
@@ -29,14 +34,207 @@ const setup = () => {
29
34
  isProd: config.isProd,
30
35
  shopwareMode: config.shopwareMode,
31
36
  assetUrl: config.assetUrl,
37
+ themeNames: config.themeNames.join(', ') + (config.buildThemes.length < config.themeNames.length ? ' (building: ' + config.buildThemes.join(', ') + ')' : ''),
32
38
  version: pkg.version,
33
39
  });
34
40
  }
35
41
  };
36
42
 
37
- setup();
43
+ /**
44
+ * Build per-theme resource paths for sass-resources-loader.
45
+ *
46
+ * Each theme gets:
47
+ * 1. uses.scss (shared vendor utilities)
48
+ * 2. vendor global resources (vendor/pxsw/...)
49
+ * 3. all non-theme plugin _global_resources (custom/plugins + custom/static-plugins
50
+ * that are NOT in THEME_NAMES)
51
+ * 4. this theme's _global_resources (overrides everything)
52
+ *
53
+ * Other themes' global resources are excluded to prevent style bleeding.
54
+ *
55
+ * @param {string} themeName - Theme name (e.g. 'PxswEbertTheme')
56
+ * @param {Object} options
57
+ * @param {string[]} options.uses - Paths to shared vendor uses.scss
58
+ * @param {string[]} options.sharedVendorResourcePaths - Paths to shared vendor _global_resources
59
+ * @returns {string[]} Array of SCSS resource paths
60
+ */
61
+ const getResourcesPaths = (themeName, options) => {
62
+ let uses = options.uses || [];
63
+ let sharedVendorResourcePaths = options.sharedVendorResourcePaths || [];
64
+ let paths = [].concat(uses, sharedVendorResourcePaths);
65
+ let globalResourcesSuffix = '/src/Resources/app/_global_resources';
66
+ let scssGlob = '/**/*.scss';
67
+
68
+ // Collect base plugin global resources (plugins NOT in THEME_NAMES)
69
+ let pluginDirs = ['custom/plugins', 'custom/static-plugins'];
70
+ pluginDirs.forEach((dir) => {
71
+ if (!Fs.existsSync(dir)) {
72
+ return;
73
+ }
74
+
75
+ let entries = Fs.readdirSync(dir).filter((name) => {
76
+ // Must match plugin prefix pattern
77
+ let prefixes = (config.pluginPrefixes || 'Pxsw').split(',');
78
+ let matchesPrefix = prefixes.some((p) =>
79
+ name.startsWith(p.trim()),
80
+ );
81
+ if (!matchesPrefix) {
82
+ return false;
83
+ }
84
+ // Exclude ALL themes from base pool — prevents style bleeding
85
+ let isTheme = config.themeNames.some(
86
+ (t) => name.indexOf(t) !== -1,
87
+ );
88
+ return !isTheme;
89
+ });
90
+
91
+ entries.forEach((name) => {
92
+ let glob = dir + '/' + name + globalResourcesSuffix + scssGlob;
93
+ if (Glob.sync(glob).length) {
94
+ paths.push(glob);
95
+ }
96
+ });
97
+ });
98
+
99
+ // Add this theme's global resources LAST (overrides base)
100
+ pluginDirs.forEach((dir) => {
101
+ if (!Fs.existsSync(dir)) {
102
+ return;
103
+ }
104
+
105
+ let themeGlob =
106
+ dir + '/*' + themeName + '*' + globalResourcesSuffix + scssGlob;
107
+ if (Glob.sync(themeGlob).length) {
108
+ paths.push(themeGlob);
109
+ }
110
+ });
111
+
112
+ return paths;
113
+ };
114
+
115
+ /**
116
+ * Create an array of webpack configs, one per theme.
117
+ * Each theme gets its own dev config (with per-theme resourcesPaths for
118
+ * sass-resources-loader) and its own storefront config (with per-theme entry).
119
+ *
120
+ * @param {Object} options
121
+ * @param {string[]} options.uses - Paths to shared vendor uses.scss
122
+ * @param {string[]} options.sharedVendorResourcePaths - Paths to shared vendor _global_resources
123
+ * @returns {Object[]} Array of webpack config objects (one per theme)
124
+ */
125
+ const createThemeConfigs = (options) => {
126
+ setup();
127
+
128
+ return config.buildThemes.map((themeName, index) => {
129
+ let resourcesPaths = getResourcesPaths(themeName, options);
130
+ let themeSlug = ChangeCase.kebabCase(themeName);
131
+ let themeOptions = {
132
+ themeName: themeName,
133
+ resourcesPaths: resourcesPaths,
134
+ };
135
+
136
+ let devCfg = createDevConfig(themeOptions);
137
+ let storefrontCfg = createStorefrontConfig(themeOptions);
138
+ let merged = merge(
139
+ devCfg,
140
+ storefrontCfg,
141
+ config.isProd ? production : {},
142
+ );
143
+
144
+ // Only the first compiler should have devServer (webpack multi-compiler limitation)
145
+ if (index > 0) {
146
+ delete merged.devServer;
147
+ }
148
+
149
+ // Per-theme filesystem cache to avoid collisions between compilers
150
+ merged.cache = {
151
+ type: 'filesystem',
152
+ name: themeSlug,
153
+ buildDependencies: {
154
+ config: [__filename],
155
+ },
156
+ };
157
+
158
+ return merged;
159
+ });
160
+ };
161
+
162
+ const setupAdministration = () => {
163
+ watcher.clean(config);
164
+ config.buildThemes.forEach((themeName) => {
165
+ watcher.compileAdministration(themeName, config);
166
+ });
167
+
168
+ if (config.isDebug) {
169
+ console.table({
170
+ ...config,
171
+
172
+ version: pkg.version,
173
+
174
+ pluginMatch: config.pluginMatch.toString(),
175
+ vendorMatch: config.vendorMatch.toString(),
176
+ allowedExtensions: config.allowedExtensions.toString(),
177
+ });
178
+ } else {
179
+ console.table({
180
+ isProd: config.isProd,
181
+ shopwareMode: config.shopwareMode,
182
+ assetUrl: config.assetUrl,
183
+ themeNames: config.themeNames.join(', ') + (config.buildThemes.length < config.themeNames.length ? ' (building: ' + config.buildThemes.join(', ') + ')' : ''),
184
+ version: pkg.version,
185
+ });
186
+ }
187
+ };
188
+
189
+ /**
190
+ * Create an array of webpack configs for administration, one per theme.
191
+ * Each theme gets its own dev config (with per-theme resourcesPaths for
192
+ * sass-resources-loader) and its own administration config (with per-theme
193
+ * SCSS entries for theme-specific styling).
194
+ *
195
+ * @param {Object} options
196
+ * @param {string[]} options.uses - Paths to shared vendor uses.scss
197
+ * @param {string[]} options.sharedVendorResourcePaths - Paths to shared vendor _global_resources
198
+ * @returns {Object[]} Array of webpack config objects (one per theme)
199
+ */
200
+ const createAdminConfigs = (options) => {
201
+ setupAdministration();
202
+
203
+ return config.buildThemes.map((themeName, index) => {
204
+ let resourcesPaths = getResourcesPaths(themeName, options);
205
+ let themeSlug = ChangeCase.kebabCase(themeName);
206
+ let themeOptions = {
207
+ themeName: themeName,
208
+ resourcesPaths: resourcesPaths,
209
+ };
210
+
211
+ let devCfg = createDevConfig(themeOptions);
212
+ let adminCfg = createAdministrationConfig(themeOptions);
213
+ let merged = merge(
214
+ devCfg,
215
+ adminCfg,
216
+ config.isProd ? production : {},
217
+ );
218
+
219
+ // Only the first compiler should have devServer (webpack multi-compiler limitation)
220
+ if (index > 0) {
221
+ delete merged.devServer;
222
+ }
223
+
224
+ // Per-theme filesystem cache to avoid collisions between compilers
225
+ merged.cache = {
226
+ type: 'filesystem',
227
+ name: themeSlug + '-admin',
228
+ buildDependencies: {
229
+ config: [__filename],
230
+ },
231
+ };
232
+
233
+ return merged;
234
+ });
235
+ };
38
236
 
39
237
  module.exports = {
40
- storefront: merge(dev, storefront, config.isProd ? production : {}),
41
- administration: merge(dev, administration, config.isProd ? production : {}),
238
+ createThemeConfigs: createThemeConfigs,
239
+ createAdminConfigs: createAdminConfigs,
42
240
  };
@@ -5,178 +5,110 @@ const Path = require('path'),
5
5
  Entry = require('webpack-glob-entry'),
6
6
  ChangeCase = require('change-case'),
7
7
  MiniCssExtractPlugin = require('mini-css-extract-plugin'),
8
- Consola = require('consola'),
9
- AssetsCopyPlugin = require('@pixolith/webpack-assets-copy-plugin'),
10
- SvgStorePlugin = require('@pixolith/external-svg-sprite-loader'),
11
- TwigAssetEmitterPlugin = require('@pixolith/webpack-twig-assets-emitter-plugin'),
12
- outputConfig = {
8
+ Consola = require('consola');
9
+
10
+ module.exports = function createAdministrationConfig(themeOptions) {
11
+ let themeName = themeOptions && themeOptions.themeName;
12
+ let themeSlug = themeName
13
+ ? ChangeCase.kebabCase(themeName)
14
+ : 'administration';
15
+
16
+ let outputConfig = {
13
17
  path: config.outputPath,
14
- publicPath: config.shopwareVersion === '6.6' ? '/' : config.assetUrl,
15
- filename: (chunkData) => {
16
- let pluginName = chunkData.chunk.name.toLowerCase().replace('pxsw-pxsw-', 'pxsw-');
17
- pluginName = config.shopwareVersion === '6.6' ? pluginName.replace('vendor-', '') : pluginName;
18
- return config.shopwareVersion === '6.6' ?
19
- `${pluginName.replace(/-/g, '',)}/administration/js/${pluginName}.js` :
20
- `js/${chunkData.chunk.name.toLowerCase()}${
21
- config.isProd ? '.admin.[contenthash]' : ''
22
- }.js`;
23
- }
24
- },
25
- miniCssChunksConfig = {
18
+ publicPath: config.assetUrl,
26
19
  filename: (chunkData) => {
27
- let pluginName = chunkData.chunk.name.toLowerCase().replace('pxsw-pxsw-', 'pxsw-');
28
- pluginName = config.shopwareVersion === '6.6' ? pluginName.replace('vendor-', '') : pluginName;
29
- return config.shopwareVersion === '6.6' ?
30
- `${pluginName.replace(/-/g, '',)}/administration/css/${pluginName}.css` :
31
- `css/[name]${
32
- config.isProd ? '.admin.[contenthash]' : ''
33
- }.css`;
34
- }
35
- }
20
+ return `js/${chunkData.chunk.name.toLowerCase()}${
21
+ config.isProd ? '.admin.[contenthash]' : ''
22
+ }.js`;
23
+ },
24
+ uniqueName: themeSlug + '-admin',
25
+ };
36
26
 
37
- module.exports = {
38
- entry: () => {
39
- let entriesPlugins = Entry(
40
- (filePath) =>
41
- ChangeCase.kebabCase(
42
- filePath.match(config.pluginMatch)[1],
43
- ),
44
- Path.join(config.pluginSrcPath, 'index.js'),
45
- );
27
+ let miniCssChunksConfig = {
28
+ filename: (chunkData) => {
29
+ return `css/[name]${
30
+ config.isProd ? '.admin.[contenthash]' : ''
31
+ }.css`;
32
+ },
33
+ };
46
34
 
47
- let entriesVendor = Entry(
48
- (filePath) =>
49
- ChangeCase.kebabCase(
50
- filePath.match(config.vendorMatch)[1],
51
- ),
52
- Path.resolve(config.vendorSrcPath, 'index.js'),
53
- );
35
+ return {
36
+ name: themeSlug + '-admin',
37
+ entry: () => {
38
+ let entriesPlugins = Entry(
39
+ (filePath) =>
40
+ ChangeCase.kebabCase(filePath.match(config.pluginMatch)[2]),
41
+ Path.join(config.pluginSrcPath, 'index.js'),
42
+ );
54
43
 
55
- if (process.env.DEBUG) {
56
- Consola.info('[DEBUG]: Webpack entry points:');
57
- console.table({...entriesPlugins, ...entriesVendor });
58
- }
44
+ let entriesVendor = Entry(
45
+ (filePath) =>
46
+ ChangeCase.kebabCase(filePath.match(config.vendorMatch)[1]),
47
+ Path.resolve(config.vendorSrcPath, 'index.js'),
48
+ );
59
49
 
60
- return {...entriesPlugins, ...entriesVendor };
61
- },
62
- module: {
63
- rules: [
64
- {
65
- test: /\.js$/,
66
- exclude: (file) => /node_modules/.test(file),
67
- loader: 'babel-loader',
68
- options: {
69
- configFile: Path.resolve(__dirname, 'babel.config.js'),
70
- },
71
- },
72
- {
73
- test: /\.(jpe?g|png|gif|ico)(\?v=\d+\.\d+\.\d+)?$/,
74
- type: 'asset/resource',
75
- generator: {
76
- filename: config.shopwareVersion === '6.6' ? '../img/[name][ext]' : 'img/[name][ext]'
77
- }
78
- },
79
- {
80
- test: /\.(eot|ttf|woff2?)(\?v=\d+\.\d+\.\d+)?$/,
81
- type: 'asset/resource',
82
- generator: {
83
- filename: config.shopwareVersion === '6.6' ? '../fonts/[name][ext]' : 'fonts/[name][ext]'
84
- }
85
- },
86
- {
87
- test: /\.svg$/,
88
- use: [
89
- {
90
- loader: SvgStorePlugin.loader,
91
- options: {
92
- name: 'sprite/sprite.svg',
93
- iconName: '[name]',
94
- overrideOrder: config.spriteOrder,
95
- ignoreIconsByName: config.ignoreIcons,
96
- onlySymbols: true,
97
- },
98
- },
99
- {
100
- loader: 'svgo-loader',
101
- options: {
102
- plugins: [
103
- 'cleanupAttrs',
104
- 'removeDoctype',
105
- 'removeXMLProcInst',
106
- 'cleanupEnableBackground',
107
- 'convertStyleToAttrs',
108
- 'convertPathData',
109
- 'cleanupIds',
110
- 'minifyStyles',
111
- 'removeUselessDefs',
112
- 'convertShapeToPath',
113
- 'removeUnusedNS',
114
- 'removeDimensions',
115
- 'convertTransform',
116
- 'collapseGroups',
117
- 'removeComments',
118
- 'removeEditorsNSData',
119
- 'removeUnknownsAndDefaults',
120
- ],
121
- },
122
- },
123
- ],
124
- },
125
- ],
126
- },
127
- output: outputConfig,
128
- plugins: [
129
- new SvgStorePlugin(),
130
- new MiniCssExtractPlugin(miniCssChunksConfig),
131
- ].concat(
132
- config.isProd && config.shopwareVersion === '6.6' ?
133
- new AssetsCopyPlugin({
134
- includes: ['js', 'css'],
135
- ignoreFiles: [/[-\w.]*.hot-update.js/],
136
- files: [
137
- {
138
- from: config.outputPath,
139
- to: '$pluginPath/$plugin/src/Resources/public',
140
- replace: async (fromPath, toPath) => {
141
- let composerPluginName = Path.basename(fromPath).replace(
142
- Path.extname(fromPath),
143
- '',
144
- ).replace('pxsw-', ''),
145
- pluginName = 'Pxsw' + ChangeCase.pascalCase(composerPluginName);
50
+ // Discover the consolidated admin SCSS entry from .theme-entries/{theme-slug}/
51
+ let scssEntries = {};
52
+ let scssEntryDir = Path.join(
53
+ config.outputPath,
54
+ '.theme-entries',
55
+ themeSlug,
56
+ );
57
+ let scssEntryFile = Path.join(
58
+ scssEntryDir,
59
+ themeSlug + '-admin.scss',
60
+ );
146
61
 
147
- let isPlugin = await Fs.existsSync(`custom/plugins/${pluginName}/src`),
148
- isStaticPlugin = await Fs.existsSync(`custom/static-plugins/${pluginName}/src`);
62
+ if (Fs.existsSync(scssEntryFile)) {
63
+ scssEntries[themeSlug + '-admin-scss'] = scssEntryFile;
64
+ }
149
65
 
150
- let pluginFolder = isPlugin ? 'custom/plugins' : (isStaticPlugin ? 'custom/static-plugins' : 'vendor/pxsw');
66
+ let allEntries = {
67
+ ...entriesPlugins,
68
+ ...entriesVendor,
69
+ ...scssEntries,
70
+ };
151
71
 
152
- toPath = toPath.replace('$pluginPath', pluginFolder);
153
- if (!isPlugin && !isStaticPlugin) {
154
- let isDoublePxswPlugin = await Fs.existsSync(`vendor/pxsw/pxsw-${composerPluginName}/src`);
155
- toPath = toPath.replace('$plugin', isDoublePxswPlugin ? `pxsw-${composerPluginName}` : composerPluginName);
156
- } else {
157
- toPath = toPath.replace('$plugin', pluginName);
158
- }
72
+ if (config.isDebug) {
73
+ Consola.info(
74
+ `[${themeName || themeSlug}] Administration webpack entry points:`,
75
+ );
76
+ console.table(allEntries);
77
+ }
159
78
 
160
- return toPath;
161
- },
79
+ return allEntries;
80
+ },
81
+ module: {
82
+ rules: [
83
+ {
84
+ test: /\.js$/,
85
+ exclude: (file) => /node_modules/.test(file),
86
+ loader: 'babel-loader',
87
+ options: {
88
+ configFile: Path.resolve(__dirname, 'babel.config.js'),
162
89
  },
163
- ],
164
- }) : [],
165
- ).concat(
166
- config.isProd && config.shopwareVersion !== '6.6' ?
167
- new TwigAssetEmitterPlugin({
168
- includes: ['js', 'css'],
169
- ignoreFiles: [/.*icons.*\.js/],
170
- template: {
171
- admin: {
172
- assetUrl: config.assetUrl,
173
- filename: 'index.html.twig',
90
+ },
91
+ {
92
+ test: /\.(jpe?g|png|gif|ico)(\?v=\d+\.\d+\.\d+)?$/,
93
+ type: 'asset/resource',
94
+ generator: {
95
+ filename: 'img/[name][ext]',
96
+ },
97
+ },
98
+ {
99
+ test: /\.(eot|ttf|woff2?)(\?v=\d+\.\d+\.\d+)?$/,
100
+ type: 'asset/resource',
101
+ generator: {
102
+ filename: 'fonts/[name][ext]',
174
103
  },
175
104
  },
176
- }) : [],
177
- ),
105
+ ],
106
+ },
107
+ output: outputConfig,
108
+ plugins: [new MiniCssExtractPlugin(miniCssChunksConfig)],
178
109
 
179
- optimization: {
180
- splitChunks: false,
181
- },
110
+ optimization: {
111
+ splitChunks: false,
112
+ },
113
+ };
182
114
  };