diff --git a/fixtures/css/postcss_extension.postcss b/fixtures/css/postcss_extension.postcss
new file mode 100644
index 00000000..4dce6d71
--- /dev/null
+++ b/fixtures/css/postcss_extension.postcss
@@ -0,0 +1 @@
+@import "autoprefixer_test.css";
\ No newline at end of file
diff --git a/fixtures/vuejs-css-modules/App.vue b/fixtures/vuejs-css-modules/App.vue
index 9dbff2fb..3e09beb0 100644
--- a/fixtures/vuejs-css-modules/App.vue
+++ b/fixtures/vuejs-css-modules/App.vue
@@ -1,5 +1,5 @@
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/config-generator.js b/lib/config-generator.js
index df8176a2..51461509 100644
--- a/lib/config-generator.js
+++ b/lib/config-generator.js
@@ -236,6 +236,15 @@ class ConfigGenerator {
return applyOptionsCallback(this.webpackConfig.loaderConfigurationCallbacks[name], defaultRules);
};
+ // When the PostCSS loader is enabled, allow to use
+ // files with the `.postcss` extension. It also
+ // makes it possible to use `lang="postcss"` in Vue
+ // files.
+ const cssExtensions = ['css'];
+ if (this.webpackConfig.usePostCssLoader) {
+ cssExtensions.push('postcss');
+ }
+
let rules = [
applyRuleConfigurationCallback('javascript', {
// match .js and .jsx
@@ -246,9 +255,9 @@ class ConfigGenerator {
applyRuleConfigurationCallback('css', {
resolve: {
mainFields: ['style', 'main'],
- extensions: ['.css'],
+ extensions: cssExtensions.map(ext => `.${ext}`),
},
- test: /\.css$/,
+ test: new RegExp(`\\.(${cssExtensions.join('|')})$`),
oneOf: [
{
resourceQuery: /module/,
diff --git a/test/config-generator.js b/test/config-generator.js
index b9aa8bf3..6f3ce7f0 100644
--- a/test/config-generator.js
+++ b/test/config-generator.js
@@ -1052,7 +1052,7 @@ describe('The config-generator function', () => {
});
const webpackConfig = configGenerator(config);
- const rule = findRule(/\.css$/, webpackConfig.module.rules);
+ const rule = findRule(/\.(css)$/, webpackConfig.module.rules);
expect(rule.camelCase).to.be.true;
});
@@ -1210,4 +1210,42 @@ describe('The config-generator function', () => {
expect(rule.use[0].options.fooBar).to.be.equal('fooBar');
});
});
+
+ describe('enablePostCssLoader() makes the CSS rule process .postcss file', () => {
+ it('without enablePostCssLoader()', () => {
+ const config = createConfig();
+ config.outputPath = '/tmp/output/public-path';
+ config.publicPath = '/public-path';
+ config.enableSingleRuntimeChunk();
+ config.addEntry('main', './main');
+ // do not call disableImagesLoader
+
+ const actualConfig = configGenerator(config);
+
+ expect(function() {
+ findRule(/\.(css)$/, actualConfig.module.rules);
+ }).not.to.throw();
+ expect(function() {
+ findRule(/\.(css|postcss)$/, actualConfig.module.rules);
+ }).to.throw();
+ });
+
+ it('with enablePostCssLoader()', () => {
+ const config = createConfig();
+ config.outputPath = '/tmp/output/public-path';
+ config.publicPath = '/public-path';
+ config.addEntry('main', './main');
+ config.enableSingleRuntimeChunk();
+ config.enablePostCssLoader();
+
+ const actualConfig = configGenerator(config);
+
+ expect(function() {
+ findRule(/\.(css)$/, actualConfig.module.rules);
+ }).to.throw();
+ expect(function() {
+ findRule(/\.(css|postcss)$/, actualConfig.module.rules);
+ }).to.not.throw();
+ });
+ });
});
diff --git a/test/functional.js b/test/functional.js
index b213da46..36e0edaa 100644
--- a/test/functional.js
+++ b/test/functional.js
@@ -948,6 +948,7 @@ module.exports = {
// load a file that @import's another file, so that we can
// test that @import resources are parsed through postcss
config.addStyleEntry('styles', ['./css/imports_autoprefixer.css']);
+ config.addStyleEntry('postcss', './css/postcss_extension.postcss');
config.enablePostCssLoader();
testSetup.runWebpack(config, (webpackAssert) => {
@@ -957,6 +958,14 @@ module.exports = {
'-webkit-full-screen'
);
+ // check that the .postcss file was also processed
+ // correctly (it also @import the autoprefixer_test.css
+ // file)
+ webpackAssert.assertOutputFileContains(
+ 'postcss.css',
+ '-webkit-full-screen'
+ );
+
done();
});
});
@@ -1421,7 +1430,7 @@ module.exports = {
});
});
- it('Vue.js supports CSS/Sass/Less/Stylus modules', (done) => {
+ it('Vue.js supports CSS/Sass/Less/Stylus/PostCSS modules', (done) => {
const appDir = testSetup.createTestAppDir();
const config = testSetup.createWebpackConfig(appDir, 'www/build', 'dev');
config.enableSingleRuntimeChunk();
@@ -1437,6 +1446,18 @@ module.exports = {
options.localIdentName = '[local]_foo';
});
+ // Enable the PostCSS loader so we can use `lang="postcss"`
+ config.enablePostCssLoader();
+ fs.writeFileSync(
+ path.join(appDir, 'postcss.config.js'),
+ `
+module.exports = {
+ plugins: [
+ require('autoprefixer')()
+ ]
+} `
+ );
+
testSetup.runWebpack(config, (webpackAssert) => {
expect(config.outputPath).to.be.a.directory().with.deep.files([
'main.js',
@@ -1457,11 +1478,13 @@ module.exports = {
expectClassDeclaration('large'); // Standard SCSS
expectClassDeclaration('justified'); // Standard Less
expectClassDeclaration('lowercase'); // Standard Stylus
+ expectClassDeclaration('block'); // Standard Postcss
expectClassDeclaration('italic_foo'); // CSS Module
expectClassDeclaration('bold_foo'); // SCSS Module
expectClassDeclaration('underline_foo'); // Less Module
expectClassDeclaration('rtl_foo'); // Stylus Module
+ expectClassDeclaration('hidden_foo'); // Stylus Module
testSetup.requestTestPage(
path.join(config.getContext(), 'www'),
@@ -1474,11 +1497,13 @@ module.exports = {
browser.assert.hasClass('#app', 'large'); // Standard SCSS
browser.assert.hasClass('#app', 'justified'); // Standard Less
browser.assert.hasClass('#app', 'lowercase'); // Standard Stylus
+ browser.assert.hasClass('#app', 'block'); // Standard Stylus
browser.assert.hasClass('#app', 'italic_foo'); // CSS module
browser.assert.hasClass('#app', 'bold_foo'); // SCSS module
browser.assert.hasClass('#app', 'underline_foo'); // Less module
browser.assert.hasClass('#app', 'rtl_foo'); // Stylus module
+ browser.assert.hasClass('#app', 'hidden_foo'); // Stylus module
done();
}