diff --git a/hotModuleReplacement.js b/hotModuleReplacement.js index 2d965960..543cf06c 100644 --- a/hotModuleReplacement.js +++ b/hotModuleReplacement.js @@ -1,7 +1,8 @@ module.exports = function(publicPath, outputFilename) { if (document) { - var origin = document.location.protocol + '//' + document.location.hostname + (document.location.port ? ':' + document.location.port: ''); - var newHref = origin + publicPath + outputFilename + var origin = document.location.protocol + + '//' + document.location.hostname + (document.location.port ? ':' + document.location.port: ''); + var newHref = origin + publicPath + outputFilename; var styleSheets = document.getElementsByTagName('link'); //update the stylesheet corresponding to `outputFilename` @@ -20,4 +21,4 @@ module.exports = function(publicPath, outputFilename) { } } } -} +}; diff --git a/index.js b/index.js index 51cc1b30..ba59598b 100644 --- a/index.js +++ b/index.js @@ -1,53 +1,49 @@ /* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ var fs = require('fs'); var ConcatSource = require("webpack-sources").ConcatSource; -var CachedSource = require("webpack-sources").CachedSource; var async = require("async"); var ExtractedModule = require("./ExtractedModule"); var Chunk = require("webpack/lib/Chunk"); +var NormalModule = require("webpack/lib/NormalModule"); var OrderUndefinedError = require("./OrderUndefinedError"); var loaderUtils = require("loader-utils"); -var schemaTester = require('./schema/validator'); -var loaderSchema = require('./schema/loader-schema'); -var pluginSchema = require('./schema/plugin-schema.json'); +var validateOptions = require('schema-utils'); +var path = require('path'); var NS = fs.realpathSync(__dirname); -var DEV = process.env.NODE_ENV === 'development'; + var nextId = 0; function ExtractTextPluginCompilation() { this.modulesByIdentifier = {}; } -// ExtractTextPlugin.prototype.mergeNonInitialChunks = function(chunk, intoChunk, checkedChunks) { -// if (chunk.chunks) { -// // Fix error when hot module replacement used with CommonsChunkPlugin -// chunk.chunks = chunk.chunks.filter(function(c) { -// return typeof c !== 'undefined'; -// }) -// } +function isInitialOrHasNoParents(chunk) { + return chunk.isInitial() || chunk.parents.length === 0; +} -// if(!intoChunk) { -// checkedChunks = []; -// chunk.chunks.forEach(function(c) { -// if(c.isInitial()) return; -// this.mergeNonInitialChunks(c, chunk, checkedChunks); -// }, this); -// } else if(checkedChunks.indexOf(chunk) < 0) { -// checkedChunks.push(chunk); -// chunk.modules.slice().forEach(function(module) { -// intoChunk.addModule(module); -// module.addChunk(intoChunk); -// }); -// chunk.chunks.forEach(function(c) { -// if(c.isInitial()) return; -// this.mergeNonInitialChunks(c, intoChunk, checkedChunks); -// }, this); -// } -// }; +ExtractTextPlugin.prototype.mergeNonInitialChunks = function(chunk, intoChunk, checkedChunks) { + if(!intoChunk) { + checkedChunks = []; + chunk.chunks.forEach(function(c) { + if(isInitialOrHasNoParents(c)) return; + this.mergeNonInitialChunks(c, chunk, checkedChunks); + }, this); + } else if(checkedChunks.indexOf(chunk) < 0) { + checkedChunks.push(chunk); + chunk.modules.slice().forEach(function(module) { + intoChunk.addModule(module); + module.addChunk(intoChunk); + }); + chunk.chunks.forEach(function(c) { + if(isInitialOrHasNoParents(c)) return; + this.mergeNonInitialChunks(c, intoChunk, checkedChunks); + }, this); + } +}; ExtractTextPluginCompilation.prototype.addModule = function(identifier, originalModule, source, additionalInformation, sourceMap, prevModules) { var m; @@ -115,26 +111,25 @@ function getOrder(a, b) { } function ExtractTextPlugin(options) { - options = options || {} - if(arguments.length > 1) { throw new Error("Breaking change: ExtractTextPlugin now only takes a single argument. Either an options " + - "object *or* the name of the result file.\n" + - "Example: if your old code looked like this:\n" + - " new ExtractTextPlugin('css/[name].css', { disable: false, allChunks: true })\n\n" + - "You would change it to:\n" + - " new ExtractTextPlugin({ filename: 'css/[name].css', disable: false, allChunks: true })\n\n" + - "The available options are:\n" + - " filename: string\n" + - " allChunks: boolean\n" + - " disable: boolean\n"); + "object *or* the name of the result file.\n" + + "Example: if your old code looked like this:\n" + + " new ExtractTextPlugin('css/[name].css', { disable: false, allChunks: true })\n\n" + + "You would change it to:\n" + + " new ExtractTextPlugin({ filename: 'css/[name].css', disable: false, allChunks: true })\n\n" + + "The available options are:\n" + + " filename: string\n" + + " allChunks: boolean\n" + + " disable: boolean\n" + + " ignoreOrder: boolean\n"); } if(isString(options)) { options = { filename: options }; } else { - schemaTester(pluginSchema, options); + validateOptions(path.resolve(__dirname, './schema/plugin.json'), options, 'Extract Text Plugin'); } - this.filename = options.filename || (DEV ? '[name].css' : '[name].[contenthash].css'); + this.filename = options.filename; this.id = options.id != null ? options.id : ++nextId; this.options = {}; mergeOptions(this.options, options); @@ -192,15 +187,15 @@ ExtractTextPlugin.prototype.loader = function(options) { ExtractTextPlugin.prototype.extract = function(options) { if(arguments.length > 1) { throw new Error("Breaking change: extract now only takes a single argument. Either an options " + - "object *or* the loader(s).\n" + - "Example: if your old code looked like this:\n" + - " ExtractTextPlugin.extract('style-loader', 'css-loader')\n\n" + - "You would change it to:\n" + - " ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })\n\n" + - "The available options are:\n" + - " use: string | object | loader[]\n" + - " fallback: string | object | loader[]\n" + - " publicPath: string\n"); + "object *or* the loader(s).\n" + + "Example: if your old code looked like this:\n" + + " ExtractTextPlugin.extract('style-loader', 'css-loader')\n\n" + + "You would change it to:\n" + + " ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })\n\n" + + "The available options are:\n" + + " use: string | object | loader[]\n" + + " fallback: string | object | loader[]\n" + + " publicPath: string\n"); } if(options.fallbackLoader) { console.warn('fallbackLoader option has been deprecated - replace with "fallback"'); @@ -211,7 +206,7 @@ ExtractTextPlugin.prototype.extract = function(options) { if(Array.isArray(options) || isString(options) || typeof options.options === "object" || typeof options.query === 'object') { options = { loader: options }; } else { - schemaTester(loaderSchema, options); + validateOptions(path.resolve(__dirname, './schema/loader.json'), options, 'Extract Text Plugin (Loader)'); } var loader = options.use ||  options.loader; var before = options.fallback || options.fallbackLoader || []; @@ -231,7 +226,7 @@ ExtractTextPlugin.prototype.extract = function(options) { return [this.loader(options)] .concat(before, loader) .map(getLoaderObject); -} +}; ExtractTextPlugin.extract = ExtractTextPlugin.prototype.extract.bind(ExtractTextPlugin); @@ -239,6 +234,7 @@ ExtractTextPlugin.prototype.apply = function(compiler) { var options = this.options; compiler.plugin("this-compilation", function(compilation) { var extractCompilation = new ExtractTextPluginCompilation(); + var toRemoveModules = {}; compilation.plugin("normal-module-loader", function(loaderContext, module) { loaderContext[NS] = function(content, opt) { if(options.disable) @@ -274,29 +270,49 @@ ExtractTextPlugin.prototype.apply = function(compiler) { }); async.forEach(chunks, function(chunk, callback) { var extractedChunk = extractedChunks[chunks.indexOf(chunk)]; - - // SETTING THIS TO TRUE INSURES ALL CHUNKS ARE HANDLED: - var shouldExtract = true; //!!(options.allChunks || chunk.isInitial()); - + var shouldExtract = !!(options.allChunks || isInitialOrHasNoParents(chunk)); async.forEach(chunk.modules.slice(), function(module, callback) { var meta = module[NS]; if(meta && (!meta.options.id || meta.options.id === id)) { var wasExtracted = Array.isArray(meta.content); if(shouldExtract !== wasExtracted) { - module[NS + "/extract"] = shouldExtract; // eslint-disable-line no-path-concat - compilation.rebuildModule(module, function(err) { + var newModule = new NormalModule( + module.request, + module.userRequest, + module.rawRequest, + module.loaders, + module.resource, + module.parser + ); + newModule[NS + "/extract"] = shouldExtract; // eslint-disable-line no-path-concat + // build a new module and save result to extracted compilations + compilation.buildModule(newModule, false, newModule, null, function(err) { if(err) { compilation.errors.push(err); return callback(); } - meta = module[NS]; + meta = newModule[NS]; + // Error out if content is not an array and is not null if(!Array.isArray(meta.content) && meta.content != null) { - err = new Error(module.identifier() + " doesn't export content"); + err = new Error(newModule.identifier() + " doesn't export content"); compilation.errors.push(err); return callback(); } - if(meta.content) - extractCompilation.addResultToChunk(module.identifier(), meta.content, module, extractedChunk); + if(meta.content) { + var ident = module.identifier(); + extractCompilation.addResultToChunk(ident, meta.content, newModule, extractedChunk); + // remove generated result from chunk + if(toRemoveModules[ident]) { + toRemoveModules[ident].chunks.push(chunk) + } else { + toRemoveModules[ident] = { + module: newModule, + moduleToRemove: module, + chunks: [chunk] + }; + } + + } callback(); }); } else { @@ -311,23 +327,47 @@ ExtractTextPlugin.prototype.apply = function(compiler) { }); }, function(err) { if(err) return callback(err); - // REMOVING THIS CODE IS ALL THAT'S NEEDED TO CREATE CSS FILES PER CHUNK: - // extractedChunks.forEach(function(extractedChunk) { - // if(extractedChunk.isInitial()) - // this.mergeNonInitialChunks(extractedChunk); - // }, this); - // extractedChunks.forEach(function(extractedChunk) { - // if(!extractedChunk.isInitial()) { - // extractedChunk.modules.slice().forEach(function(module) { - // extractedChunk.removeModule(module); - // }); - // } - // }); + extractedChunks.forEach(function(extractedChunk) { + if(isInitialOrHasNoParents(extractedChunk)) + this.mergeNonInitialChunks(extractedChunk); + }, this); + extractedChunks.forEach(function(extractedChunk) { + if(!isInitialOrHasNoParents(extractedChunk)) { + extractedChunk.modules.slice().forEach(function(module) { + extractedChunk.removeModule(module); + }); + } + }); compilation.applyPlugins("optimize-extracted-chunks", extractedChunks); callback(); }.bind(this)); }.bind(this)); - + compilation.plugin("optimize-module-ids", function(modules){ + modules.forEach(function (module) { + var data = toRemoveModules[module.identifier()]; + if (data) { + var id = module.id; + var newModule = new NormalModule( + module.request, + module.userRequest, + module.rawRequest, + module.loaders, + module.resource, + module.parser + ); + newModule.id = id; + newModule._source = data.module._source; + data.chunks.forEach(function (chunk) { + chunk.removeModule(data.moduleToRemove); + var deps = data.moduleToRemove.dependencies.slice(); + deps.forEach(d => { + chunk.removeModule(d.module); + }); + chunk.addModule(newModule); + }); + } + }); + }); compilation.plugin("additional-assets", function(callback) { extractedChunks.forEach(function(extractedChunk) { if(extractedChunk.modules.length) { @@ -361,38 +401,7 @@ ExtractTextPlugin.prototype.apply = function(compiler) { }); } }, this); - - // duplicate js chunks into secondary files that don't have css injection, - // giving the additional js files the extension: `.no_css.js` - Object.keys(compilation.assets).forEach(function(name) { - var asset = compilation.assets[name]; - - if (/\.js$/.test(name) && asset._source) { - var regex = /\/\*__START_CSS__\*\/[\s\S]*?\/\*__END_CSS__\*\//g - var source = asset.source(); - - if (!source.match(regex)) { - return; - } - var newName = name.replace(/\.js/, '.no_css.js'); - var newAsset = new CachedSource(asset._source); - // remove js that adds css to DOM via style-loader, so that React Loadable - // can serve smaller files (without css) in initial request. - newAsset._cachedSource = source.replace(regex, ''); - - compilation.assets[newName] = newAsset; - - // add no_css file to files associated with chunk so that they are minified, - // and receive source maps, and can be found by React Loadable - extractedChunks.forEach(function(extractedChunk) { - var chunk = extractedChunk.originalChunk; - if (chunk.files.indexOf(name) > -1) { - chunk.files.push(newName); - } - }) - } - }) - callback() + callback(); }.bind(this)); }.bind(this)); }; diff --git a/loader.js b/loader.js index 16ef2efd..cc81743f 100644 --- a/loader.js +++ b/loader.js @@ -2,10 +2,8 @@ MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ -var path = require("path"); var fs = require("fs"); var loaderUtils = require("loader-utils"); -var jsesc = require("jsesc"); var NodeTemplatePlugin = require("webpack/lib/node/NodeTemplatePlugin"); var NodeTargetPlugin = require("webpack/lib/node/NodeTargetPlugin"); var LibraryTemplatePlugin = require("webpack/lib/LibraryTemplatePlugin"); @@ -15,17 +13,10 @@ var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin" var NS = fs.realpathSync(__dirname); module.exports = function(source) { - if(this.cacheable) this.cacheable(); - // Even though this gets overwritten if extract+remove are true, without it, the runtime doesn't get added to the chunk - return `require("style-loader/lib/addStyles.js"); - if (module.hot) { require('${require.resolve("./hotModuleReplacement.js")}'); } - ${source}`; + return source; }; module.exports.pitch = function(request) { - var self = this; - var remainingRequest = request; - if(this.cacheable) this.cacheable(); var query = loaderUtils.getOptions(this) || {}; var loaders = this.loaders.slice(this.loaderIndex + 1); this.addDependency(this.resourcePath); @@ -127,21 +118,12 @@ module.exports.pitch = function(request) { }); }); this[NS](text, query); + if(typeof resultSource !== "undefined") { if (text.locals) { resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";"; } - - // module.hot.data is undefined on initial load, and an object in hot updates - var jsescOpts = { wrap: true, quotes: "double" }; resultSource += ` -/*__START_CSS__*/ -var moduleId = ${jsesc(text[0][0], jsescOpts)}; -var css = ${jsesc(text[0][1], jsescOpts)}; -var addStyles = require("style-loader/lib/addStyles.js"); -addStyles([[moduleId, css]], ""); -/*__END_CSS__*/ - if (module.hot) { module.hot.accept(); if (module.hot.data) { @@ -152,7 +134,6 @@ if (module.hot) { } catch(e) { return callback(e); } - if(resultSource) callback(null, resultSource); else diff --git a/package.json b/package.json index e8cff4c1..604fad35 100644 --- a/package.json +++ b/package.json @@ -48,10 +48,11 @@ "mocha": "^3.2.0", "mocha-lcov-reporter": "1.3.0", "raw-loader": "^0.5.1", + "rimraf": "^2.6.1", "semantic-release": "^6.3.2", "should": "^11.1.2", "standard-version": "^4.0.0", - "webpack": "^2.2.0" + "webpack": "2.6.0" }, "homepage": "http://github.com/faceyspacey/extract-css-chunks-webpack-plugin", "repository": { diff --git a/schema/loader-schema.js b/schema/loader-schema.js deleted file mode 100644 index 80266761..00000000 --- a/schema/loader-schema.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "additionalProperties": false, - "properties": { - "allChunks": { "type": "boolean"}, - "disable": { "type": "boolean" }, - "omit": { "type": "boolean" }, - "remove": { "type": "boolean" }, - "fallback": { "type": ["string", "array", "object"] }, - "filename": { "type": "string" }, - "use": { "type": ["string", "array", "object"] }, - "publicPath": { "type": "string" }, - - // deprecated - "fallbackLoader": { "type": ["string", "array", "object"] }, - "loader": { "type": ["string", "array", "object"] } - } -}; diff --git a/schema/loader.json b/schema/loader.json new file mode 100644 index 00000000..bca660af --- /dev/null +++ b/schema/loader.json @@ -0,0 +1,36 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "allChunks": { + "type": "boolean" + }, + "disable": { + "type": "boolean" + }, + "omit": { + "type": "boolean" + }, + "remove": { + "type": "boolean" + }, + "fallback": { + "type": ["string", "array", "object"] + }, + "filename": { + "type": "string" + }, + "use": { + "type": ["string", "array", "object"] + }, + "publicPath": { + "type": "string" + }, + "fallbackLoader": { + "type": ["string", "array", "object"] + }, + "loader": { + "type": ["string", "array", "object"] + } + } +} diff --git a/schema/plugin-schema.json b/schema/plugin.json similarity index 76% rename from schema/plugin-schema.json rename to schema/plugin.json index 7b507d17..4fcf2e66 100644 --- a/schema/plugin-schema.json +++ b/schema/plugin.json @@ -1,5 +1,4 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "additionalProperties": false, "properties": { @@ -14,16 +13,13 @@ "fallback": { "description": "A loader that webpack can fall back to if the original one fails.", "modes": { - "type": "string", - "type": "object", - "type": "array" + "type": ["string", "object", "array"] } }, "filename": { "description": "The filename and path that ExtractTextPlugin will extract to", "modes": { - "type": "string", - "type": "function" + "type": ["string", "function"] } }, "ignoreOrder": { @@ -33,9 +29,7 @@ "loader": { "description": "The loader that ExtractTextPlugin will attempt to load through.", "modes": { - "type": "string", - "type": "object", - "type": "array" + "type": ["string", "object", "array"] } }, "publicPath": { diff --git a/schema/validator.js b/schema/validator.js deleted file mode 100644 index 5e5f9174..00000000 --- a/schema/validator.js +++ /dev/null @@ -1,13 +0,0 @@ -var Ajv = require('ajv'); -var ajv = new Ajv({allErrors: true}); - -module.exports = function validate(schema, data) { - var ajv = new Ajv({ - errorDataPath: 'property' - }); - var isValid = ajv.validate(schema, data); - - if(!isValid) { - throw new Error(ajv.errorsText()); - } -} diff --git a/test/TestCases.test.js b/test/TestCases.test.js index bbcb3712..415d1094 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -3,6 +3,7 @@ var vm = require("vm"); var path = require("path"); var webpack = require("webpack"); var should = require("should"); +var rimraf = require('rimraf'); var ExtractTextPlugin = require("../"); var cases = process.env.CASES ? process.env.CASES.split(",") : fs.readdirSync(path.join(__dirname, "cases")); @@ -12,36 +13,39 @@ describe("TestCases", function() { it(testCase, function(done) { var testDirectory = path.join(__dirname, "cases", testCase); var outputDirectory = path.join(__dirname, "js", testCase); - var options = { entry: { test: "./index.js" } }; - var configFile = path.join(testDirectory, "webpack.config.js"); - if(fs.existsSync(configFile)) - options = require(configFile); - options.context = testDirectory; - if(!options.module) options.module = {}; - if(!options.module.loaders) options.module.loaders = [ - { test: /\.txt$/, loader: ExtractTextPlugin.extract("raw-loader") } - ]; - if(!options.output) options.output = { filename: "[name].js" }; - if(!options.output.path) options.output.path = outputDirectory; - if(process.env.CASES) { - console.log("\nwebpack." + testCase + ".config.js " + JSON.stringify(options, null, 2)); - } - webpack(options, function(err, stats) { - if(err) return done(err); - if(stats.hasErrors()) return done(new Error(stats.toString())); - var testFile = path.join(outputDirectory, "test.js"); - if(fs.existsSync(testFile)) - require(testFile)(suite); - var expectedDirectory = path.join(testDirectory, "expected"); - fs.readdirSync(expectedDirectory).forEach(function(file) { - var filePath = path.join(expectedDirectory, file); - var actualPath = path.join(outputDirectory, file); - readFileOrEmpty(actualPath).should.be.eql( - readFileOrEmpty(filePath), - file + " should be correct"); + function test() { + var options = { entry: { test: "./index.js" } }; + var configFile = path.join(testDirectory, "webpack.config.js"); + if (fs.existsSync(configFile)) + options = require(configFile); + options.context = testDirectory; + if (!options.module) options.module = {}; + if (!options.module.loaders) options.module.loaders = [ + { test: /\.txt$/, loader: ExtractTextPlugin.extract("raw-loader") } + ]; + if (!options.output) options.output = { filename: "[name].js" }; + if (!options.output.path) options.output.path = outputDirectory; + if (process.env.CASES) { + console.log("\nwebpack." + testCase + ".config.js " + JSON.stringify(options, null, 2)); + } + webpack(options, function (err, stats) { + if (err) return done(err); + if (stats.hasErrors()) return done(new Error(stats.toString())); + var testFile = path.join(outputDirectory, "test.js"); + if (fs.existsSync(testFile)) + require(testFile)(suite); + var expectedDirectory = path.join(testDirectory, "expected"); + fs.readdirSync(expectedDirectory).forEach(function (file) { + var filePath = path.join(expectedDirectory, file); + var actualPath = path.join(outputDirectory, file); + readFileOrEmpty(actualPath).should.be.eql( + readFileOrEmpty(filePath), + file + " should be correct"); + }); + done(); }); - done(); - }); + } + rimraf(outputDirectory, test); }); }); }); diff --git a/test/cases/common-async/a.js b/test/cases/common-async/a.js new file mode 100644 index 00000000..2d7d820b --- /dev/null +++ b/test/cases/common-async/a.js @@ -0,0 +1,2 @@ +require("./a.txt"); +require("./b.txt"); diff --git a/test/cases/common-async/a.txt b/test/cases/common-async/a.txt new file mode 100644 index 00000000..78981922 --- /dev/null +++ b/test/cases/common-async/a.txt @@ -0,0 +1 @@ +a diff --git a/test/cases/common-async/b.js b/test/cases/common-async/b.js new file mode 100644 index 00000000..caac53f4 --- /dev/null +++ b/test/cases/common-async/b.js @@ -0,0 +1,3 @@ +require("./a.txt"); +require("./c.txt"); + diff --git a/test/cases/common-async/b.txt b/test/cases/common-async/b.txt new file mode 100644 index 00000000..61780798 --- /dev/null +++ b/test/cases/common-async/b.txt @@ -0,0 +1 @@ +b diff --git a/test/cases/common-async/c.txt b/test/cases/common-async/c.txt new file mode 100644 index 00000000..f2ad6c76 --- /dev/null +++ b/test/cases/common-async/c.txt @@ -0,0 +1 @@ +c diff --git a/test/cases/common-async/expected/file.css b/test/cases/common-async/expected/file.css new file mode 100644 index 00000000..de980441 --- /dev/null +++ b/test/cases/common-async/expected/file.css @@ -0,0 +1,3 @@ +a +b +c diff --git a/test/cases/common-async/index.js b/test/cases/common-async/index.js new file mode 100644 index 00000000..624fa419 --- /dev/null +++ b/test/cases/common-async/index.js @@ -0,0 +1,14 @@ +require.ensure( + [], + function() { + require("./a.js"); + }, + 'async-chunk-a' +); +require.ensure( + [], + function() { + require("./b.js"); + }, + 'async-chunk-b' +); diff --git a/test/cases/common-async/webpack.config.js b/test/cases/common-async/webpack.config.js new file mode 100644 index 00000000..758d08a1 --- /dev/null +++ b/test/cases/common-async/webpack.config.js @@ -0,0 +1,17 @@ +var webpack = require('webpack'); +var ExtractTextPlugin = require("../../../index"); + +module.exports = { + entry: "./index", + plugins: [ + new webpack.optimize.CommonsChunkPlugin({ + name: 'common', + filename: 'common.js', + chunks: ['async-chunk-a', 'async-chunk-b'] + }), + new ExtractTextPlugin({ + filename: "file.css", + allChunks: true + }) + ] +}; diff --git a/test/cases/multiple-entries-all-async/default-styles.css b/test/cases/multiple-entries-all-async/default-styles.css new file mode 100644 index 00000000..f0d5b13b --- /dev/null +++ b/test/cases/multiple-entries-all-async/default-styles.css @@ -0,0 +1,3 @@ +body { + background: red; +} diff --git a/test/cases/multiple-entries-all-async/entries/contact.js b/test/cases/multiple-entries-all-async/entries/contact.js new file mode 100644 index 00000000..66b458c2 --- /dev/null +++ b/test/cases/multiple-entries-all-async/entries/contact.js @@ -0,0 +1,2 @@ +require('../router'); +require('../routes/contact'); diff --git a/test/cases/multiple-entries-all-async/entries/homepage.js b/test/cases/multiple-entries-all-async/entries/homepage.js new file mode 100644 index 00000000..7a8e5aea --- /dev/null +++ b/test/cases/multiple-entries-all-async/entries/homepage.js @@ -0,0 +1,2 @@ +require('../router'); +require('../routes/homepage'); diff --git a/test/cases/multiple-entries-all-async/expected/0.js b/test/cases/multiple-entries-all-async/expected/0.js new file mode 100644 index 00000000..da5c0eb6 --- /dev/null +++ b/test/cases/multiple-entries-all-async/expected/0.js @@ -0,0 +1,28 @@ +webpackJsonp([0],{ + +/***/ 2: +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(7); + +modules.export = function() { + return 'Route Homepage'; +}; + + +/***/ }), + +/***/ 7: +/***/ (function(module, exports, __webpack_require__) { + +// removed by extract-text-webpack-plugin +if (false) { + module.hot.accept(); + if (module.hot.data) { + require("/home/david/Projekte/extract-css-chunks-webpack-plugin/hotModuleReplacement.js")("undefined", "homepage.css"); + } +} + +/***/ }) + +}); \ No newline at end of file diff --git a/test/cases/multiple-entries-all-async/expected/1.js b/test/cases/multiple-entries-all-async/expected/1.js new file mode 100644 index 00000000..ae1a3a2d --- /dev/null +++ b/test/cases/multiple-entries-all-async/expected/1.js @@ -0,0 +1,28 @@ +webpackJsonp([1],{ + +/***/ 1: +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(6); + +modules.export = function() { + return 'Route Contact'; +}; + + +/***/ }), + +/***/ 6: +/***/ (function(module, exports, __webpack_require__) { + +// removed by extract-text-webpack-plugin +if (false) { + module.hot.accept(); + if (module.hot.data) { + require("/home/david/Projekte/extract-css-chunks-webpack-plugin/hotModuleReplacement.js")("undefined", "homepage.css"); + } +} + +/***/ }) + +}); \ No newline at end of file diff --git a/test/cases/multiple-entries-all-async/expected/contact.css b/test/cases/multiple-entries-all-async/expected/contact.css new file mode 100644 index 00000000..c952ccfd --- /dev/null +++ b/test/cases/multiple-entries-all-async/expected/contact.css @@ -0,0 +1,9 @@ +body { + background: red; +} +.contact { + color: black; +} +.homepage { + color: black; +} diff --git a/test/cases/multiple-entries-all-async/expected/homepage.css b/test/cases/multiple-entries-all-async/expected/homepage.css new file mode 100644 index 00000000..c952ccfd --- /dev/null +++ b/test/cases/multiple-entries-all-async/expected/homepage.css @@ -0,0 +1,9 @@ +body { + background: red; +} +.contact { + color: black; +} +.homepage { + color: black; +} diff --git a/test/cases/multiple-entries-all-async/router.js b/test/cases/multiple-entries-all-async/router.js new file mode 100644 index 00000000..d9855317 --- /dev/null +++ b/test/cases/multiple-entries-all-async/router.js @@ -0,0 +1,6 @@ +require('./default-styles.css'); +module.export = function (route) { + return import(/* webpackChunkName: "route-[request]" */ './routes/' + route + 'index.js').then(function (route) { + return route; + }); +}; diff --git a/test/cases/multiple-entries-all-async/routes/contact/index.js b/test/cases/multiple-entries-all-async/routes/contact/index.js new file mode 100644 index 00000000..c16daacb --- /dev/null +++ b/test/cases/multiple-entries-all-async/routes/contact/index.js @@ -0,0 +1,5 @@ +require('./styles.css'); + +modules.export = function() { + return 'Route Contact'; +}; diff --git a/test/cases/multiple-entries-all-async/routes/contact/styles.css b/test/cases/multiple-entries-all-async/routes/contact/styles.css new file mode 100644 index 00000000..fd8a667d --- /dev/null +++ b/test/cases/multiple-entries-all-async/routes/contact/styles.css @@ -0,0 +1,3 @@ +.contact { + color: black; +} diff --git a/test/cases/multiple-entries-all-async/routes/homepage/index.js b/test/cases/multiple-entries-all-async/routes/homepage/index.js new file mode 100644 index 00000000..bb86d26e --- /dev/null +++ b/test/cases/multiple-entries-all-async/routes/homepage/index.js @@ -0,0 +1,5 @@ +require('./styles.css'); + +modules.export = function() { + return 'Route Homepage'; +}; diff --git a/test/cases/multiple-entries-all-async/routes/homepage/styles.css b/test/cases/multiple-entries-all-async/routes/homepage/styles.css new file mode 100644 index 00000000..1fc1fc5a --- /dev/null +++ b/test/cases/multiple-entries-all-async/routes/homepage/styles.css @@ -0,0 +1,3 @@ +.homepage { + color: black; +} diff --git a/test/cases/multiple-entries-all-async/webpack.config.js b/test/cases/multiple-entries-all-async/webpack.config.js new file mode 100644 index 00000000..d94f0093 --- /dev/null +++ b/test/cases/multiple-entries-all-async/webpack.config.js @@ -0,0 +1,23 @@ +var ExtractTextPlugin = require("../../../"); +module.exports = { + entry: { + 'homepage': "./entries/homepage.js", + 'contact': "./entries/contact.js" + }, + module: { + loaders: [ + { test: /\.css$/, use: ExtractTextPlugin.extract({ + fallback: "style-loader", + use: { loader: "css-loader", options: { + sourceMap: false + } } + }) } + ] + }, + plugins: [ + new ExtractTextPlugin({ + filename: '[name].css', + allChunks: true + }) + ] +}; diff --git a/test/cases/multiple-entries-async/default-styles.css b/test/cases/multiple-entries-async/default-styles.css new file mode 100644 index 00000000..f0d5b13b --- /dev/null +++ b/test/cases/multiple-entries-async/default-styles.css @@ -0,0 +1,3 @@ +body { + background: red; +} diff --git a/test/cases/multiple-entries-async/entries/contact.js b/test/cases/multiple-entries-async/entries/contact.js new file mode 100644 index 00000000..66b458c2 --- /dev/null +++ b/test/cases/multiple-entries-async/entries/contact.js @@ -0,0 +1,2 @@ +require('../router'); +require('../routes/contact'); diff --git a/test/cases/multiple-entries-async/entries/homepage.js b/test/cases/multiple-entries-async/entries/homepage.js new file mode 100644 index 00000000..7a8e5aea --- /dev/null +++ b/test/cases/multiple-entries-async/entries/homepage.js @@ -0,0 +1,2 @@ +require('../router'); +require('../routes/homepage'); diff --git a/test/cases/multiple-entries-async/expected/0.js b/test/cases/multiple-entries-async/expected/0.js new file mode 100644 index 00000000..0d707b04 --- /dev/null +++ b/test/cases/multiple-entries-async/expected/0.js @@ -0,0 +1,62 @@ +webpackJsonp([0],{ + +/***/ 16: +/***/ (function(module, exports, __webpack_require__) { + +// style-loader: Adds some css to the DOM by adding a