diff --git a/fixtures/js/css_import.js b/fixtures/js/css_import.js new file mode 100644 index 00000000..ab8aea6d --- /dev/null +++ b/fixtures/js/css_import.js @@ -0,0 +1,2 @@ + +require('./../css/h1_style.css'); diff --git a/index.js b/index.js index 0254ac12..e10a89ec 100644 --- a/index.js +++ b/index.js @@ -1046,6 +1046,22 @@ class Encore { return this; } + /** + * Call this if you don't want imported CSS to be extracted + * into a .css file. All your styles will then be injected + * into the page by your JS code. + * + * Internally, this disables the mini-css-extract-plugin + * and uses the style-loader instead. + * + * @returns {Encore} + */ + disableCssExtraction() { + webpackConfig.disableCssExtraction(); + + return this; + } + /** * Call this to change how the name of each output * file is generated. diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 1dfe85ba..be28c767 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -53,6 +53,7 @@ class WebpackConfig { this.useVersioning = false; this.useSourceMaps = false; this.cleanupOutput = false; + this.extractCss = true; this.useImagesLoader = true; this.useFontsLoader = true; this.usePostCssLoader = false; @@ -657,6 +658,10 @@ class WebpackConfig { this.useFontsLoader = false; } + disableCssExtraction() { + this.extractCss = false; + } + configureFilenames(configuredFilenames = {}) { if (typeof configuredFilenames !== 'object') { throw new Error('Argument 1 to configureFilenames() must be an object.'); diff --git a/lib/config-generator.js b/lib/config-generator.js index 23d5038c..614b9b9d 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -397,7 +397,9 @@ class ConfigGenerator { buildPluginsConfig() { const plugins = []; - miniCssExtractPluginUtil(plugins, this.webpackConfig); + if (this.webpackConfig.extractCss) { + miniCssExtractPluginUtil(plugins, this.webpackConfig); + } // register the pure-style entries that should be deleted deleteUnusedEntriesPluginUtil(plugins, this.webpackConfig); diff --git a/lib/loaders/css-extract.js b/lib/loaders/css-extract.js index 440f1858..a718bb66 100644 --- a/lib/loaders/css-extract.js +++ b/lib/loaders/css-extract.js @@ -20,6 +20,17 @@ module.exports = { * @return {Array} */ prependLoaders(webpackConfig, loaders) { + if (!webpackConfig.extractCss) { + // If the CSS extraction is disabled, use the + // style-loader instead. + return [{ + loader: 'style-loader', + options: { + sourceMap: webpackConfig.useSourceMaps, + } + }, ...loaders]; + } + return [MiniCssExtractPlugin.loader, ...loaders]; } }; diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index 17eb8f89..6a26ed15 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -1033,6 +1033,21 @@ describe('WebpackConfig object', () => { }); }); + describe('disableCssExtraction', () => { + it('By default the CSS extraction is enabled', () => { + const config = createConfig(); + + expect(config.extractCss).to.be.true; + }); + + it('Calling it disables the CSS extraction', () => { + const config = createConfig(); + config.disableCssExtraction(); + + expect(config.extractCss).to.be.false; + }); + }); + describe('configureFilenames', () => { it('Calling method sets it', () => { const config = createConfig(); diff --git a/test/functional.js b/test/functional.js index 37a39eb4..5619996a 100644 --- a/test/functional.js +++ b/test/functional.js @@ -2204,5 +2204,55 @@ module.exports = { }); }); }); + + describe('CSS extraction', () => { + it('With CSS extraction enabled', (done) => { + const config = createWebpackConfig('build', 'dev'); + config.setPublicPath('/build'); + config.disableSingleRuntimeChunk(); + config.addEntry('main', './js/css_import'); + + testSetup.runWebpack(config, (webpackAssert) => { + expect(config.outputPath).to.be.a.directory() + .with.files([ + 'manifest.json', + 'entrypoints.json', + 'main.js', + 'main.css', + ]); + + webpackAssert.assertOutputFileContains( + 'main.css', + 'font-size: 50px;' + ); + + done(); + }); + }); + + it('With CSS extraction disabled', (done) => { + const config = createWebpackConfig('build', 'dev'); + config.setPublicPath('/build'); + config.disableSingleRuntimeChunk(); + config.addEntry('main', './js/css_import'); + config.disableCssExtraction(); + + testSetup.runWebpack(config, (webpackAssert) => { + expect(config.outputPath).to.be.a.directory() + .with.files([ + 'manifest.json', + 'entrypoints.json', + 'main.js' + ]); + + webpackAssert.assertOutputFileContains( + 'main.js', + 'font-size: 50px;' + ); + + done(); + }); + }); + }); }); }); diff --git a/test/index.js b/test/index.js index abc649de..58f57c24 100644 --- a/test/index.js +++ b/test/index.js @@ -324,6 +324,15 @@ describe('Public API', () => { }); + describe('disableCssExtraction', () => { + + it('must return the API object', () => { + const returnedValue = api.disableCssExtraction(); + expect(returnedValue).to.equal(api); + }); + + }); + describe('configureFilenames', () => { it('must return the API object', () => {