Skip to content

Commit 3ae0fe0

Browse files
committed
Updating our custom formatting of vue loader problems
1 parent 5d940f0 commit 3ae0fe0

File tree

14 files changed

+94
-139
lines changed

14 files changed

+94
-139
lines changed

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class Encore {
210210
* // final output file will be main.js in the output directory
211211
* Encore.addEntry('main', './path/to/some_file.js');
212212
*
213-
* If the JavaScript file imports/requires CSS/SASS/LESS files,
213+
* If the JavaScript file imports/requires CSS/Sass/LESS files,
214214
* then a CSS file (e.g. main.css) will also be output.
215215
*
216216
* @param {string} name The name (without extension) that will be used

lib/features.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const features = {
1919
sass: {
2020
method: 'enableSassLoader()',
2121
packages: ['sass-loader', 'node-sass'],
22-
description: 'load SASS files'
22+
description: 'load Sass files'
2323
},
2424
less: {
2525
method: 'enableLessLoader()',

lib/friendly-errors/formatters/missing-loader.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ function formatErrors(errors) {
1919
}
2020

2121
let messages = [];
22+
2223
for (let error of errors) {
2324
const fixes = [];
2425

@@ -38,10 +39,17 @@ function formatErrors(errors) {
3839
fixes.push('You may need to install and configure a special loader for this file type.');
3940
}
4041

41-
messages = messages.concat([
42-
chalk.red(`Error loading ${chalk.yellow(error.file)}`),
43-
''
44-
]);
42+
// vue hides their filenames (via a stacktrace) inside error.origin
43+
if (error.isVueLoader) {
44+
messages.push(error.message);
45+
messages.push(error.origin);
46+
messages.push('');
47+
} else {
48+
messages = messages.concat([
49+
chalk.red(`Error loading ${chalk.yellow(error.file)}`),
50+
''
51+
]);
52+
}
4553

4654
if (error.loaderName) {
4755
messages.push(`${chalk.bgGreen.black('', 'FIX', '')} To ${loaderFeatures.getFeatureDescription(error.loaderName)}:`);

lib/friendly-errors/formatters/vue-unactivated-loader-error.js

Lines changed: 0 additions & 42 deletions
This file was deleted.

lib/friendly-errors/transformers/missing-loader.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,24 @@ function isMissingLoaderError(e) {
2323
return true;
2424
}
2525

26+
function isErrorFromVueLoader(filename) {
27+
return filename.includes('??vue-loader-options');
28+
}
29+
2630
function getFileExtension(filename) {
31+
// ??vue-loader-options
32+
if (isErrorFromVueLoader(filename)) {
33+
// vue is strange, the "filename" is reported as something like
34+
// /path/to/project/node_modules/vue-loader/lib??vue-loader-options!./vuejs/App.vue?vue&type=style&index=1&lang=scss
35+
const langPos = filename.indexOf('lang=') + 5;
36+
let endLangPos = filename.indexOf('&', langPos);
37+
if (endLangPos === -1) {
38+
endLangPos = filename.length;
39+
}
40+
41+
return filename.substring(langPos, endLangPos);
42+
}
43+
2744
const str = filename.replace(/\?.*/, '');
2845
const split = str.split('.');
2946

@@ -36,6 +53,7 @@ function transform(error) {
3653
}
3754

3855
error = Object.assign({}, error);
56+
error.isVueLoader = isErrorFromVueLoader(error.file);
3957

4058
const extension = getFileExtension(error.file);
4159
switch (extension) {
@@ -49,6 +67,9 @@ function transform(error) {
4967
case 'jsx':
5068
error.loaderName = 'react';
5169
break;
70+
case 'vue':
71+
error.loaderName = 'vue';
72+
break;
5273
case 'tsx':
5374
case 'ts':
5475
error.loaderName = 'typescript';

lib/friendly-errors/transformers/vue-unactivated-loader-error.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

lib/loaders/sass.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = {
2424

2525
const sassLoaders = [...cssLoader.getLoaders(webpackConfig)];
2626
if (true === webpackConfig.sassOptions.resolveUrlLoader) {
27-
// responsible for resolving SASS url() paths
27+
// responsible for resolving Sass url() paths
2828
// without this, all url() paths must be relative to the
2929
// entry file, not the file that contains the url()
3030
sassLoaders.push({

lib/loaders/vue-unactivated-loader.js

Lines changed: 0 additions & 36 deletions
This file was deleted.

lib/plugins/friendly-errors.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const missingLoaderTransformer = require('../friendly-errors/transformers/missin
1414
const missingLoaderFormatter = require('../friendly-errors/formatters/missing-loader');
1515
const missingPostCssConfigTransformer = require('../friendly-errors/transformers/missing-postcss-config');
1616
const missingPostCssConfigFormatter = require('../friendly-errors/formatters/missing-postcss-config');
17-
const vueUnactivatedLoaderTransformer = require('../friendly-errors/transformers/vue-unactivated-loader-error');
18-
const vueUnactivatedLoaderFormatter = require('../friendly-errors/formatters/vue-unactivated-loader-error');
1917
const applyOptionsCallback = require('../utils/apply-options-callback');
2018

2119
/**
@@ -27,13 +25,11 @@ module.exports = function(webpackConfig) {
2725
clearConsole: false,
2826
additionalTransformers: [
2927
missingLoaderTransformer,
30-
missingPostCssConfigTransformer,
31-
vueUnactivatedLoaderTransformer
28+
missingPostCssConfigTransformer
3229
],
3330
additionalFormatters: [
3431
missingLoaderFormatter,
35-
missingPostCssConfigFormatter,
36-
vueUnactivatedLoaderFormatter
32+
missingPostCssConfigFormatter
3733
],
3834
compilationSuccessInfo: {
3935
messages: []

lib/plugins/loader-options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = function(plugins, webpackConfig) {
2323
* This section is a bit mysterious. The "minimize"
2424
* true is read and used to minify the CSS.
2525
* But as soon as this plugin is included
26-
* at all, SASS begins to have errors, until the context
26+
* at all, Sass begins to have errors, until the context
2727
* and output options are specified. At this time, I'm
2828
* not totally sure what's going on here
2929
* https://github.com/jtangelder/sass-loader/issues/285

test/friendly-errors/formatters/missing-loader.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('formatters/missing-loader', () => {
3939
};
4040

4141
const actualErrors = formatter([error]);
42-
expect(JSON.stringify(actualErrors)).to.contain('To load SASS files');
42+
expect(JSON.stringify(actualErrors)).to.contain('To load Sass files');
4343
expect(JSON.stringify(actualErrors)).to.contain('Encore.enableSassLoader()');
4444
// all needed packages will be present when running tests
4545
expect(JSON.stringify(actualErrors)).to.not.contain('yarn add');
@@ -55,5 +55,21 @@ describe('formatters/missing-loader', () => {
5555
expect(JSON.stringify(actualErrors)).to.contain('To load /some/file.jpg');
5656
expect(JSON.stringify(actualErrors)).to.contain('You may need to install and configure a special loader');
5757
});
58+
59+
it('vue loader error includes original message & origin', () => {
60+
const error = {
61+
message: 'I am a message from vue-loader',
62+
isVueLoader: true,
63+
loaderName: 'sass',
64+
origin: 'Some stacktrace info from origin',
65+
type: 'loader-not-enabled',
66+
file: '/path/to/project/node_modules/vue-loader/lib??vue-loader-options!./vuejs/App.vue?vue&type=style&index=1&lang=scss'
67+
};
68+
69+
const actualErrors = formatter([error]);
70+
expect(JSON.stringify(actualErrors)).to.contain('I am a message from vue-loader');
71+
expect(JSON.stringify(actualErrors)).to.contain('Some stacktrace info from origin');
72+
expect(JSON.stringify(actualErrors)).to.not.contain('/path/to/project/node_modules/vue-loader');
73+
});
5874
});
5975
});

test/friendly-errors/transformers/missing-loader.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ describe('transform/missing-loader', () => {
4141
const startError = {
4242
name: 'ModuleParseError',
4343
message: 'You may need an appropriate loader',
44-
file: '/path/to/file.jpg'
44+
file: '/path/to/file.jpg',
45+
isVueLoader: false
4546
};
4647
const actualError = transform(Object.assign({}, startError));
4748

@@ -73,5 +74,32 @@ describe('transform/missing-loader', () => {
7374
expect(actualError.type).to.deep.equal('loader-not-enabled');
7475
expect(actualError.loaderName).to.deep.equal('typescript');
7576
});
77+
78+
it('vue-loader is handled correctly', () => {
79+
const startError = {
80+
name: 'ModuleParseError',
81+
message: 'Module parse failed: Unexpected character \'#\' (35:0)\nYou may need an appropriate loader to handle this file type.\n| \n| \n| #app {\n| display: flex;\n| color: #2c3e90;',
82+
file: '/path/to/project/node_modules/vue-loader/lib??vue-loader-options!./vuejs/App.vue?vue&type=style&index=1&lang=scss'
83+
};
84+
const actualError = transform(Object.assign({}, startError));
85+
86+
expect(actualError.name).to.deep.equal('Loader not enabled');
87+
expect(actualError.type).to.deep.equal('loader-not-enabled');
88+
expect(actualError.loaderName).to.deep.equal('sass');
89+
expect(actualError.isVueLoader).to.be.true;
90+
});
91+
92+
it('vue-loader is handled correctly, more options after lang=', () => {
93+
const startError = {
94+
name: 'ModuleParseError',
95+
message: 'Module parse failed: Unexpected character \'#\' (35:0)\nYou may need an appropriate loader to handle this file type.\n| \n| \n| #app {\n| display: flex;\n| color: #2c3e90;',
96+
file: '/path/to/project/node_modules/vue-loader/lib??vue-loader-options!./vuejs/App.vue?vue&type=style&index=1&lang=scss&foo=bar'
97+
};
98+
const actualError = transform(Object.assign({}, startError));
99+
100+
expect(actualError.name).to.deep.equal('Loader not enabled');
101+
expect(actualError.type).to.deep.equal('loader-not-enabled');
102+
expect(actualError.loaderName).to.deep.equal('sass');
103+
});
76104
});
77105
});

test/functional.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -961,10 +961,10 @@ module.exports = {
961961
config.addEntry('main', './vuejs/main');
962962
config.enableVueLoader();
963963

964-
testSetup.runWebpack(config, (webpackAssert, stats) => {
965-
expect(stats.toJson().errors[0]).to.contain('Cannot process lang="less" inside');
966-
expect(stats.toJson().errors[1]).to.contain('Cannot process lang="sass" inside');
967-
expect(stats.toJson().errors[2]).to.contain('Cannot process lang="scss" inside');
964+
testSetup.runWebpack(config, (webpackAssert, stats, output) => {
965+
expect(output).to.contain('To load LESS files');
966+
expect(output).to.contain('To load Sass files');
967+
968968
done();
969969
}, true);
970970
});

test/helpers/setup.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ function createWebpackConfig(testAppDir, outputDirName = '', command, argv = {})
6161

6262
function runWebpack(webpackConfig, callback, allowCompilationError = false) {
6363
const stdoutWrite = process.stdout.write;
64+
const stdOutContents = [];
6465

6566
try {
6667
// Mute stdout
67-
process.stdout.write = () => {};
68+
process.stdout.write = (message) => {
69+
stdOutContents.push(message);
70+
};
6871

6972
validator(webpackConfig);
7073

@@ -94,7 +97,7 @@ function runWebpack(webpackConfig, callback, allowCompilationError = false) {
9497

9598
// Restore stdout and then call the callback
9699
process.stdout.write = stdoutWrite;
97-
callback(assertUtil(webpackConfig), stats);
100+
callback(assertUtil(webpackConfig), stats, stdOutContents.join("\n"));
98101
});
99102
} catch (e) {
100103
// Restore stdout and then re-throw the exception

0 commit comments

Comments
 (0)