Skip to content

Commit dbe7ea2

Browse files
authored
Merge branch 'master' into add-plugins
2 parents 225a0da + db980b4 commit dbe7ea2

File tree

8 files changed

+124
-25
lines changed

8 files changed

+124
-25
lines changed

appveyor.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cache:
2+
- node_modules
3+
4+
environment:
5+
matrix:
6+
- nodejs_version: "6"
7+
8+
platform:
9+
- x86
10+
- x64
11+
12+
install:
13+
- ps: Install-Product node $env:nodejs_version $env:platform
14+
- npm install
15+
16+
test_script:
17+
- node --version
18+
- npm --version
19+
- npm run test
20+
21+
build: off

index.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/*
2+
* This file is part of the Symfony package.
3+
*
4+
* (c) Fabien Potencier <fabien@symfony.com>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
110
'use strict';
211

312
const WebpackConfig = require('./lib/WebpackConfig');
@@ -141,6 +150,32 @@ module.exports = {
141150
return this;
142151
},
143152

153+
/**
154+
* Adds a custom loader config
155+
*
156+
* @param {object} loader The loader config object
157+
*
158+
* @returns {exports}
159+
*/
160+
addLoader(loader) {
161+
webpackConfig.addLoader(loader);
162+
163+
return this;
164+
},
165+
166+
/**
167+
* Alias to addLoader
168+
*
169+
* @param {object} rule
170+
*
171+
* @returns {exports}
172+
*/
173+
addRule(rule) {
174+
this.addLoader(rule);
175+
176+
return this;
177+
},
178+
144179
/**
145180
* When enabled, files are rendered with a hash based
146181
* on their contents (e.g. main.a2b61cc.js)

lib/WebpackConfig.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class WebpackConfig {
5050
this.providedVariables = {};
5151
this.babelConfigurationCallback = function() {};
5252
this.useReact = false;
53+
this.loaders = [];
5354
}
5455

5556
getContext() {
@@ -162,6 +163,10 @@ class WebpackConfig {
162163
this.plugins.push(plugin);
163164
}
164165

166+
addLoader(loader) {
167+
this.loaders.push(loader);
168+
}
169+
165170
enableVersioning(enabled = true) {
166171
this.useVersioning = enabled;
167172
}

lib/config-generator.js

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const webpack = require('webpack');
1313
const ExtractTextPlugin = require('extract-text-webpack-plugin');
1414
const ManifestPlugin = require('./webpack/webpack-manifest-plugin');
1515
const DeleteUnusedEntriesJSPlugin = require('./webpack/delete-unused-entries-js-plugin');
16-
const AssetsOutputDisplayPlugin = require('./friendly-errors/asset-output-display-plugin');
16+
const AssetOutputDisplayPlugin = require('./friendly-errors/asset-output-display-plugin');
1717
const loaderFeatures = require('./loader-features');
1818
const CleanWebpackPlugin = require('clean-webpack-plugin');
1919
const WebpackChunkHash = require('webpack-chunk-hash');
@@ -235,6 +235,10 @@ class ConfigGenerator {
235235
});
236236
}
237237

238+
this.webpackConfig.loaders.forEach((loader) => {
239+
rules.push(loader);
240+
});
241+
238242
return rules;
239243
}
240244

@@ -344,17 +348,9 @@ class ConfigGenerator {
344348

345349
if (this.webpackConfig.cleanupOutput) {
346350
plugins.push(
347-
new CleanWebpackPlugin([this.webpackConfig.outputPath], {
351+
new CleanWebpackPlugin(['**/*'], {
352+
root: this.webpackConfig.outputPath,
348353
verbose: false,
349-
/*
350-
* Instead of passing the "root" option and then making
351-
* the first argument (this.webpackConfig.outputPath) relative
352-
* to that (e.g. "builds"), we pass the absolute path as
353-
* the first argument. To the plugin, this looks like a
354-
* path that is "outside of the project root". This flag
355-
* says to ignore that.
356-
*/
357-
allowExternal: true
358354
})
359355
);
360356
}
@@ -410,11 +406,9 @@ class ConfigGenerator {
410406
});
411407
plugins.push(friendlyErrorsPlugin);
412408

413-
const outputPath = this.webpackConfig.outputPath.replace(this.webpackConfig.getContext() + '/', '');
414-
plugins.push(new AssetsOutputDisplayPlugin(outputPath, friendlyErrorsPlugin));
415-
416-
if (this.webpackConfig.useDevServer()) {
417-
plugins.push(new webpack.HotModuleReplacementPlugin());
409+
if (!this.webpackConfig.useDevServer()) {
410+
const outputPath = this.webpackConfig.outputPath.replace(this.webpackConfig.getContext() + '/', '');
411+
plugins.push(new AssetOutputDisplayPlugin(outputPath, friendlyErrorsPlugin));
418412
}
419413

420414
this.webpackConfig.plugins.forEach(function(plugin) {

lib/test/setup.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ function emptyTmpDir() {
9494

9595
function touchFileInOutputDir(filename, webpackConfig) {
9696
const fullPath = path.join(webpackConfig.outputPath, filename);
97+
fs.ensureDirSync(path.dirname(fullPath));
98+
9799
fs.writeFileSync(
98100
fullPath,
99101
''
@@ -156,7 +158,7 @@ function requestTestPage(webRootDir, scriptSrcs, callback) {
156158

157159
const browser = new Browser();
158160
browser.on('error', function(error) {
159-
throw new Error(error);
161+
throw new Error(`Error when running the browser: ${error}`);
160162
});
161163
browser.visit('http://127.0.0.1:8080/testing.html', () => {
162164
stopAllServers();

test/WebpackConfig.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,14 @@ describe('WebpackConfig object', () => {
290290
expect(config.plugins.length).to.equal(1);
291291
});
292292
});
293+
294+
describe('addLoader', () => {
295+
it('Adds a new loader', () => {
296+
const config = createConfig();
297+
298+
config.addLoader({ 'test': /\.custom$/, 'loader': 'custom-loader' });
299+
300+
expect(config.loaders).to.deep.equals([{ 'test': /\.custom$/, 'loader': 'custom-loader' }]);
301+
});
302+
});
293303
});

test/config-generator.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,19 @@ describe('The config-generator function', () => {
348348
});
349349
});
350350

351+
describe('addLoader() adds a custom loader', () => {
352+
it('addLoader()', () => {
353+
const config = createConfig();
354+
config.outputPath = '/tmp/output/public-path';
355+
config.publicPath = '/public-path';
356+
config.addLoader({ 'test': /\.custom$/, 'loader': 'custom-loader' });
357+
358+
const actualConfig = configGenerator(config);
359+
360+
expect(actualConfig.module.rules).to.deep.include({ 'test': /\.custom$/, 'loader': 'custom-loader' });
361+
});
362+
});
363+
351364
describe('.js rule receives different configuration', () => {
352365
it('Use default config', () => {
353366
const config = createConfig();

test/functional.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ function createWebpackConfig(outputDirName = '', command, argv = {}) {
2525
);
2626
}
2727

28+
function convertToManifestPath(assetSrc, webpackConfig) {
29+
const manifestData = JSON.parse(
30+
fs.readFileSync(path.join(webpackConfig.outputPath, 'manifest.json'), 'utf8')
31+
);
32+
33+
if (typeof manifestData[assetSrc] === 'undefined') {
34+
throw new Error(`Path ${assetSrc} not found in manifest!`);
35+
}
36+
37+
return manifestData[assetSrc];
38+
}
39+
2840
describe('Functional tests using webpack', function() {
2941
// being functional tests, these can take quite long
3042
this.timeout(5000);
@@ -101,7 +113,10 @@ describe('Functional tests using webpack', function() {
101113

102114
testSetup.requestTestPage(
103115
path.join(config.getContext(), 'public'),
104-
['/assets/main.js'],
116+
[
117+
// purposely load this NOT from the CDN
118+
'assets/main.js'
119+
],
105120
(browser) => {
106121
webpackAssert.assertResourcesLoadedCorrectly(browser, [
107122
'0.js',
@@ -147,15 +162,13 @@ describe('Functional tests using webpack', function() {
147162

148163
testSetup.requestTestPage(
149164
path.join(config.getContext(), 'public'),
150-
['/assets/main.js'],
165+
[
166+
convertToManifestPath('assets/main.js', config)
167+
],
151168
(browser) => {
152169
webpackAssert.assertResourcesLoadedCorrectly(browser, [
153170
'0.js',
154-
// guarantee that we assert that main.js is loaded from the
155-
// main server, as it's simply a script tag to main.js on the page
156-
// we did this to check that the internally-loaded assets
157-
// use the CDN, even if the entry point does not
158-
'http://127.0.0.1:8080/assets/main.js'
171+
'main.js'
159172
]);
160173

161174
done();
@@ -179,7 +192,9 @@ describe('Functional tests using webpack', function() {
179192
testSetup.requestTestPage(
180193
// the webroot will not include the /subdirectory/build part
181194
path.join(config.getContext(), ''),
182-
['/subdirectory/build/main.js'],
195+
[
196+
convertToManifestPath('build/main.js', config)
197+
],
183198
(browser) => {
184199
webpackAssert.assertResourcesLoadedCorrectly(browser, [
185200
'http://127.0.0.1:8080/subdirectory/build/0.js',
@@ -554,12 +569,16 @@ module.exports = {
554569
config.addEntry('main', './js/no_require');
555570
config.cleanupOutputBeforeBuild();
556571
testSetup.touchFileInOutputDir('file.txt', config);
572+
testSetup.touchFileInOutputDir('deeper/other.txt', config);
557573

558574
testSetup.runWebpack(config, (webpackAssert) => {
559575
// make sure the file was cleaned up!
560576
webpackAssert.assertOutputFileDoesNotExist(
561577
'file.txt'
562578
);
579+
webpackAssert.assertOutputFileDoesNotExist(
580+
'deeper/other.txt'
581+
);
563582

564583
done();
565584
});

0 commit comments

Comments
 (0)