Skip to content

Commit baf45d3

Browse files
committed
bug #930 Fix Encore.copyFiles() when copying images/fonts (Lyrkan)
This PR was merged into the main branch. Discussion ---------- Fix Encore.copyFiles() when copying images/fonts This PR fixes an issue that prevented `Encore.copyFiles()` from working properly when copying files that matched one of the default `asset/resource` rules. Note that it has two drawbacks: * it introduces what could be considered as a small breaking change for users calling `configureLoaderRule('images', ...)` or `configureLoaderRule('fonts', ...)` since it adds a new `oneOf` at the top-level of each rule * if an user create a new rule that also matches files handled by `Encore.copyFiles(...)` they'll have to use the same `oneOf`/`resourceQuery` pattern to avoid conflicts Closes #894 Commits ------- f21427e Fix Encore.copyFiles() when copying images/fonts
2 parents 17d8591 + f21427e commit baf45d3

File tree

4 files changed

+82
-17
lines changed

4 files changed

+82
-17
lines changed

lib/config-generator.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class ConfigGenerator {
212212

213213
return buffer + `
214214
const context_${index} = require.context(
215-
'${stringEscaper(`!${copyFilesLoaderConfig}!${copyFrom}`)}',
215+
'${stringEscaper(`!!${copyFilesLoaderConfig}!${copyFrom}?copy-files-loader`)}',
216216
${!!entry.includeSubdirectories},
217217
${entry.pattern}
218218
);
@@ -269,9 +269,16 @@ class ConfigGenerator {
269269
ruleCallback,
270270
{
271271
test: testRegex,
272-
type: ruleOptions.type,
273-
generator: generatorOptions,
274-
parser: parserOptions,
272+
oneOf: [
273+
{
274+
resourceQuery: /copy-files-loader/,
275+
type: 'javascript/auto',
276+
},{
277+
type: ruleOptions.type,
278+
generator: generatorOptions,
279+
parser: parserOptions
280+
}
281+
]
275282
},
276283
);
277284

lib/plugins/manifest.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const manifestKeyPrefixHelper = require('../utils/manifest-key-prefix-helper');
2222
* @return {void}
2323
*/
2424
module.exports = function(plugins, webpackConfig) {
25-
const manifestPluginOptions = {
25+
let manifestPluginOptions = {
2626
seed: {},
2727
basePath: manifestKeyPrefixHelper(webpackConfig),
2828
// always write a manifest.json file, even with webpack-dev-server
@@ -36,10 +36,26 @@ module.exports = function(plugins, webpackConfig) {
3636
}
3737
};
3838

39+
manifestPluginOptions = applyOptionsCallback(
40+
webpackConfig.manifestPluginOptionsCallback,
41+
manifestPluginOptions
42+
);
43+
44+
const userMapOption = manifestPluginOptions.map;
45+
manifestPluginOptions.map = (file) => {
46+
const newFile = Object.assign({}, file, {
47+
name: file.name.replace('?copy-files-loader', ''),
48+
});
49+
50+
if (typeof userMapOption === 'function') {
51+
return userMapOption(newFile);
52+
}
53+
54+
return newFile;
55+
};
56+
3957
plugins.push({
40-
plugin: new WebpackManifestPlugin(
41-
applyOptionsCallback(webpackConfig.manifestPluginOptionsCallback, manifestPluginOptions)
42-
),
58+
plugin: new WebpackManifestPlugin(manifestPluginOptions),
4359
priority: PluginPriorities.WebpackManifestPlugin
4460
});
4561
};

test/config-generator.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,13 @@ describe('The config-generator function', () => {
778778

779779
const actualConfig = configGenerator(config);
780780

781-
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules);
781+
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules).oneOf[1];
782782
expect(imagesRule.type).to.equal('asset/resource');
783783
expect(imagesRule.generator).to.eql({ filename: 'images/[name].[hash:8][ext]' });
784784
expect(imagesRule.parser).to.eql({});
785-
expect(imagesRule).to.include.keys('test', 'type', 'generator', 'parser');
785+
expect(imagesRule).to.include.keys('type', 'generator', 'parser');
786786

787-
const fontsRule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, actualConfig.module.rules);
787+
const fontsRule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, actualConfig.module.rules).oneOf[1];
788788
expect(fontsRule.type).to.equal('asset/resource');
789789
expect(fontsRule.generator).to.eql({ filename: 'fonts/[name].[hash:8][ext]' });
790790
});
@@ -801,7 +801,7 @@ describe('The config-generator function', () => {
801801

802802
const actualConfig = configGenerator(config);
803803

804-
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules);
804+
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules).oneOf[1];
805805
expect(imagesRule.type).to.equal('asset/resource');
806806
expect(imagesRule.generator).to.eql({ filename: 'file.[hash][ext]' });
807807
});
@@ -818,7 +818,7 @@ describe('The config-generator function', () => {
818818

819819
const actualConfig = configGenerator(config);
820820

821-
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules);
821+
const imagesRule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, actualConfig.module.rules).oneOf[1];
822822
expect(imagesRule.parser).to.eql({ dataUrlCondition: { maxSize: 3000 } });
823823
});
824824

@@ -1122,22 +1122,22 @@ describe('The config-generator function', () => {
11221122

11231123
it('configure rule for "images"', () => {
11241124
config.configureLoaderRule('images', (loaderRule) => {
1125-
loaderRule.generator.filename = 'dirname-images/[hash:42][ext]';
1125+
loaderRule.oneOf[1].generator.filename = 'dirname-images/[hash:42][ext]';
11261126
});
11271127

11281128
const webpackConfig = configGenerator(config);
1129-
const rule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, webpackConfig.module.rules);
1129+
const rule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, webpackConfig.module.rules).oneOf[1];
11301130

11311131
expect(rule.generator.filename).to.equal('dirname-images/[hash:42][ext]');
11321132
});
11331133

11341134
it('configure rule for "fonts"', () => {
11351135
config.configureLoaderRule('fonts', (loader) => {
1136-
loader.generator.filename = 'dirname-fonts/[hash:42][ext]';
1136+
loader.oneOf[1].generator.filename = 'dirname-fonts/[hash:42][ext]';
11371137
});
11381138

11391139
const webpackConfig = configGenerator(config);
1140-
const rule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, webpackConfig.module.rules);
1140+
const rule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, webpackConfig.module.rules).oneOf[1];
11411141

11421142
expect(rule.generator.filename).to.equal('dirname-fonts/[hash:42][ext]');
11431143
});

test/functional.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,6 +2480,48 @@ module.exports = {
24802480
done();
24812481
});
24822482
});
2483+
2484+
it('Does not prevent from setting the map option of the manifest plugin', (done) => {
2485+
const config = createWebpackConfig('www/build', 'production');
2486+
config.addEntry('main', './js/no_require');
2487+
config.setPublicPath('/build');
2488+
config.copyFiles({
2489+
from: './images',
2490+
pattern: /symfony_logo\.png/,
2491+
includeSubdirectories: false
2492+
});
2493+
2494+
config.configureManifestPlugin(options => {
2495+
options.map = (file) => {
2496+
return Object.assign({}, file, {
2497+
name: `${file.name}.test`,
2498+
});
2499+
};
2500+
});
2501+
2502+
testSetup.runWebpack(config, (webpackAssert) => {
2503+
expect(config.outputPath).to.be.a.directory()
2504+
.with.files([
2505+
'entrypoints.json',
2506+
'runtime.js',
2507+
'main.js',
2508+
'manifest.json',
2509+
'symfony_logo.png'
2510+
]);
2511+
2512+
webpackAssert.assertManifestPath(
2513+
'build/main.js.test',
2514+
'/build/main.js'
2515+
);
2516+
2517+
webpackAssert.assertManifestPath(
2518+
'build/symfony_logo.png.test',
2519+
'/build/symfony_logo.png'
2520+
);
2521+
2522+
done();
2523+
});
2524+
});
24832525
});
24842526

24852527
describe('entrypoints.json & splitChunks()', () => {

0 commit comments

Comments
 (0)