Skip to content

Commit 22a3ee1

Browse files
shmolfweaverryan
authored andcommitted
New Encore method for adding multiple entries at once
1 parent 17ed0a8 commit 22a3ee1

File tree

5 files changed

+185
-23
lines changed

5 files changed

+185
-23
lines changed

index.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,39 @@ class Encore {
235235
return this;
236236
}
237237

238+
/**
239+
* Adds a collection of JavaScript files that should be webpacked:
240+
*
241+
* ```
242+
* // final output file will be main.js in the output directory
243+
* Encore.addEntries({
244+
* main: './path/to/some_file.js',
245+
* secondary: './path/to/another_file.js',
246+
* });
247+
* ```
248+
*
249+
* If the JavaScript files imports/requires CSS/Sass/LESS files,
250+
* then a CSS file (e.g. main.css) will also be output.
251+
*
252+
* @param {Object.<string, string|array>} entries where the Keys are the
253+
* names (without extension) that will be used
254+
* as the output filename (e.g. app will become app.js)
255+
* in the output directory. The values are the path(s)
256+
* to the source file(s).
257+
* @returns {Encore}
258+
*/
259+
addEntries(entries) {
260+
webpackConfig.addEntries(entries);
261+
262+
return this;
263+
}
264+
238265
/**
239266
* Adds a CSS/SASS/LESS file that should be webpacked:
240267
*
241268
* ```
242269
* // final output file will be main.css in the output directory
243-
* Encore.addEntry('main', './path/to/some_file.css');
270+
* Encore.addStyleEntry('main', './path/to/some_file.css');
244271
* ```
245272
*
246273
* This is actually not something Webpack does natively, and you

lib/WebpackConfig.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -346,27 +346,27 @@ class WebpackConfig {
346346
}
347347

348348
addEntry(name, src) {
349-
if (this.entries.has(name)) {
350-
throw new Error(`Duplicate name "${name}" passed to addEntry(): entries must be unique.`);
351-
}
352-
353-
// also check for styleEntries duplicates
354-
if (this.styleEntries.has(name)) {
355-
throw new Error(`The "${name}" passed to addEntry conflicts with a name passed to addStyleEntry(). The entry names between addEntry() and addStyleEntry() must be unique.`);
356-
}
349+
this.validateNameIsNewEntry(name);
357350

358351
this.entries.set(name, src);
359352
}
360353

361-
addStyleEntry(name, src) {
362-
if (this.styleEntries.has(name)) {
363-
throw new Error(`Duplicate name "${name}" passed to addStyleEntry(): entries must be unique.`);
354+
/**
355+
* Provide a has of entries at once, as an alternative to calling `addEntry` several times.
356+
*
357+
* @param {Object.<string, string|string[]>} entries
358+
* @returns {Void}
359+
*/
360+
addEntries(entries = {}) {
361+
if (typeof entries !== 'object') {
362+
throw new Error('Argument 1 to addEntries() must be an object.');
364363
}
365364

366-
// also check for entries duplicates
367-
if (this.entries.has(name)) {
368-
throw new Error(`The "${name}" passed to addStyleEntry() conflicts with a name passed to addEntry(). The entry names between addEntry() and addStyleEntry() must be unique.`);
369-
}
365+
Object.entries(entries).forEach((entry) => this.addEntry(entry[0], entry[1]));
366+
}
367+
368+
addStyleEntry(name, src) {
369+
this.validateNameIsNewEntry(name);
370370

371371
this.styleEntries.set(name, src);
372372
}
@@ -1005,6 +1005,18 @@ class WebpackConfig {
10051005
isDevServer() {
10061006
return this.isDev() && this.runtimeConfig.useDevServer;
10071007
}
1008+
1009+
validateNameIsNewEntry(name) {
1010+
const entryNamesOverlapMsg = 'The entry names between addEntry(), addEntries(), and addStyleEntry() must be unique.';
1011+
1012+
if (this.entries.has(name)) {
1013+
throw new Error(`Duplicate name "${name}}" already exists as an Entrypoint. ${entryNamesOverlapMsg}`);
1014+
}
1015+
1016+
if (this.styleEntries.has(name)) {
1017+
throw new Error(`The "${name}" already exists as a Style Entrypoint. ${entryNamesOverlapMsg}`);
1018+
}
1019+
}
10081020
}
10091021

10101022
module.exports = WebpackConfig;

lib/config/validator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Validator {
4444
&& this.webpackConfig.styleEntries.size === 0
4545
&& this.webpackConfig.copyFilesConfigs.length === 0
4646
) {
47-
throw new Error('No entries found! You must call addEntry() or addStyleEntry() or copyFiles() at least once - otherwise... there is nothing to webpack!');
47+
throw new Error('No entries found! You must call addEntry() or addEntries() or addStyleEntry() or copyFiles() at least once - otherwise... there is nothing to webpack!');
4848
}
4949
}
5050

test/WebpackConfig.js

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,13 @@ describe('WebpackConfig object', () => {
347347
});
348348

349349
describe('addEntry', () => {
350-
it('Calling with a duplicate name throws an error', () => {
350+
it('Calling with a duplicate entrypoint name throws an error', () => {
351351
const config = createConfig();
352352
config.addEntry('entry_foo', './foo.js');
353353

354354
expect(() => {
355355
config.addEntry('entry_foo', './bar.js');
356-
}).to.throw('Duplicate name');
356+
}).to.throw('already exists as an Entrypoint');
357357
});
358358

359359
it('Calling with a duplicate of addStyleEntry', () => {
@@ -362,18 +362,56 @@ describe('WebpackConfig object', () => {
362362

363363
expect(() => {
364364
config.addEntry('main', './main.js');
365-
}).to.throw('conflicts with a name passed to addStyleEntry');
365+
}).to.throw('already exists as a Style Entrypoint');
366+
});
367+
368+
it('Calling with a duplicate of addEntries', () => {
369+
const config = createConfig();
370+
config.addEntries({ main: './foo.js' });
371+
372+
expect(() => {
373+
config.addEntry('main', './bar.js');
374+
}).to.throw('already exists as an Entrypoint');
375+
});
376+
});
377+
378+
describe('addEntries', () => {
379+
it('Calling with a duplicate entrypoint name throws an error', () => {
380+
const config = createConfig();
381+
config.addEntry('entry_foo', './foo.js');
382+
383+
expect(() => {
384+
config.addEntries({ entry_foo: './bar.js' });
385+
}).to.throw('already exists as an Entrypoint');
386+
});
387+
388+
it('Calling with a duplicate of addStyleEntry', () => {
389+
const config = createConfig();
390+
config.addStyleEntry('main', './main.scss');
391+
392+
expect(() => {
393+
config.addEntries({ main: './main.js' });
394+
}).to.throw('already exists as a Style Entrypoint');
395+
});
396+
397+
it('Calling with a duplicate of addEntries', () => {
398+
const config = createConfig();
399+
config.addEntries({ main: './foo.js' });
400+
401+
expect(() => {
402+
config.addEntries({ main: './bar.js' });
403+
}).to.throw('already exists as an Entrypoint');
366404
});
367405
});
368406

369407
describe('addStyleEntry', () => {
370-
it('Calling with a duplicate name throws an error', () => {
408+
it('Calling with a duplicate style entrypoint name throws an error', () => {
371409
const config = createConfig();
372410
config.addStyleEntry('entry_foo', './foo.css');
373411

374412
expect(() => {
375413
config.addStyleEntry('entry_foo', './bar.css');
376-
}).to.throw('Duplicate name');
414+
}).to.throw('already exists as a Style Entrypoint');
377415
});
378416

379417
it('Calling with a duplicate of addEntry', () => {
@@ -382,7 +420,16 @@ describe('WebpackConfig object', () => {
382420

383421
expect(() => {
384422
config.addStyleEntry('main', './main.js');
385-
}).to.throw('conflicts with a name passed to addEntry');
423+
}).to.throw('already exists as an Entrypoint');
424+
});
425+
426+
it('Calling with a duplicate of addEntries', () => {
427+
const config = createConfig();
428+
config.addEntries({ main: './main.js' });
429+
430+
expect(() => {
431+
config.addStyleEntry('main', './main.scss');
432+
}).to.throw('already exists as an Entrypoint');
386433
});
387434
});
388435

@@ -1513,4 +1560,33 @@ describe('WebpackConfig object', () => {
15131560
}).to.throw('"notExisting" is not a valid key for enableEslintLoader(). Valid keys: lintVue.');
15141561
});
15151562
});
1563+
1564+
describe('validateNameIsNewEntry', () => {
1565+
it('Providing a new name does not throw an error', () => {
1566+
const config = createConfig();
1567+
config.addEntry('entry_foo', './foo.js');
1568+
1569+
expect(() => {
1570+
config.validateNameIsNewEntry('unused_name');
1571+
}).to.not.throw;
1572+
});
1573+
1574+
it('Providing a name exists within Entries does throw an error', () => {
1575+
const config = createConfig();
1576+
config.addEntry('entry_foo', './foo.js');
1577+
1578+
expect(() => {
1579+
config.validateNameIsNewEntry('entry_foo');
1580+
}).to.throw('already exists as an Entrypoint');
1581+
});
1582+
1583+
it('Providing a name exists within Style Entries does throw an error', () => {
1584+
const config = createConfig();
1585+
config.addStyleEntry('entry_foo', './foo.js');
1586+
1587+
expect(() => {
1588+
config.validateNameIsNewEntry('entry_foo');
1589+
}).to.throw('already exists as a Style Entrypoint');
1590+
});
1591+
});
15161592
});

test/config-generator.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,53 @@ describe('The config-generator function', () => {
104104
}));
105105
});
106106

107+
it('addEntry and addEntries expectations are merged', () => {
108+
const config = createConfig();
109+
config.publicPath = '/';
110+
config.outputPath = '/tmp';
111+
config.addEntry('main', './main');
112+
config.addEntries({ main2: './main2' });
113+
114+
const actualConfig = configGenerator(config);
115+
116+
expect(JSON.stringify(actualConfig.entry)).to.equal(JSON.stringify({
117+
main: './main',
118+
main2: './main2',
119+
}));
120+
});
121+
122+
it('addStyleEntry and addEntries expectations are merged', () => {
123+
const config = createConfig();
124+
config.publicPath = '/';
125+
config.outputPath = '/tmp';
126+
config.addStyleEntry('style', ['./bootstrap.css', './main.css']);
127+
config.addEntries({ main: './main' });
128+
129+
const actualConfig = configGenerator(config);
130+
131+
expect(JSON.stringify(actualConfig.entry)).to.equal(JSON.stringify({
132+
main: './main',
133+
style: ['./bootstrap.css', './main.css'],
134+
}));
135+
});
136+
137+
it('addEntry, addStyleEntry and addEntries expectations are merged', () => {
138+
const config = createConfig();
139+
config.publicPath = '/';
140+
config.outputPath = '/tmp';
141+
config.addEntry('main', './main');
142+
config.addStyleEntry('style', ['./bootstrap.css', './main.css']);
143+
config.addEntries({ main2: './main2' });
144+
145+
const actualConfig = configGenerator(config);
146+
147+
expect(JSON.stringify(actualConfig.entry)).to.equal(JSON.stringify({
148+
main: './main',
149+
main2: './main2',
150+
style: ['./bootstrap.css', './main.css'],
151+
}));
152+
});
153+
107154
it('basic output', () => {
108155
const config = createConfig();
109156

0 commit comments

Comments
 (0)