From 583918a188a1e3012fcb8db8f6ca1e189bea2b0f Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Thu, 29 Nov 2018 12:23:32 -0800 Subject: [PATCH 01/16] feat(options.filename): add ability to transform filename --- src/index.js | 31 +++- test/TestCases.test.js | 150 +++++++++++------- .../cases/filename/expected/main.be12b629.css | 2 + .../cases/filename/expected/main.ccd36095.css | 2 + test/cases/filename/index.js | 1 + test/cases/filename/style1.css | 1 + test/cases/filename/style2.css | 1 + test/cases/filename/webpack.config.js | 31 ++++ 8 files changed, 152 insertions(+), 67 deletions(-) create mode 100644 test/cases/filename/expected/main.be12b629.css create mode 100644 test/cases/filename/expected/main.ccd36095.css create mode 100644 test/cases/filename/index.js create mode 100644 test/cases/filename/style1.css create mode 100644 test/cases/filename/style2.css create mode 100644 test/cases/filename/webpack.config.js diff --git a/src/index.js b/src/index.js index 3e2a9001..a48a558b 100644 --- a/src/index.js +++ b/src/index.js @@ -14,6 +14,8 @@ const pluginName = 'mini-css-extract-plugin'; const REGEXP_CHUNKHASH = /\[chunkhash(?::(\d+))?\]/i; const REGEXP_CONTENTHASH = /\[contenthash(?::(\d+))?\]/i; const REGEXP_NAME = /\[name\]/i; +const REGEXP_PLACEHOLDERS = /\[(name|id|chunkhash)\]/g; +const DEFAULT_FILENAME = '[name].css'; class CssDependency extends webpack.Dependency { constructor( @@ -112,21 +114,18 @@ class MiniCssExtractPlugin { constructor(options) { this.options = Object.assign( { - filename: '[name].css', + filename: DEFAULT_FILENAME, }, options ); if (!this.options.chunkFilename) { const { filename } = this.options; - const hasName = filename.includes('[name]'); - const hasId = filename.includes('[id]'); - const hasChunkHash = filename.includes('[chunkhash]'); // Anything changing depending on chunk is fine - if (hasChunkHash || hasName || hasId) { + if (typeof filename === 'string' && REGEXP_PLACEHOLDERS.test(filename)) { this.options.chunkFilename = filename; } else { // Elsewise prefix '[id].' in front of the basename to make it changing - this.options.chunkFilename = filename.replace( + this.options.chunkFilename = DEFAULT_FILENAME.replace( /(^|\/)([^/]*(?:\?|$))/, '$1[id].$2' ); @@ -170,6 +169,24 @@ class MiniCssExtractPlugin { const renderedModules = Array.from(chunk.modulesIterable).filter( (module) => module.type === MODULE_TYPE ); + const { filename } = this.options; + let filenameTemplate = filename; + if (typeof filename === 'function') { + const { + hash: chunkhash, + contentHash: contenthash, + name, + id, + } = chunk; + + filenameTemplate = filename({ + chunkhash, + contenthash, + name, + id, + }); + } + if (renderedModules.length > 0) { result.push({ render: () => @@ -179,7 +196,7 @@ class MiniCssExtractPlugin { renderedModules, compilation.runtimeTemplate.requestShortener ), - filenameTemplate: this.options.filename, + filenameTemplate, pathOptions: { chunk, contentHashType: MODULE_TYPE, diff --git a/test/TestCases.test.js b/test/TestCases.test.js index ee4cd52c..6b9b1899 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -9,71 +9,101 @@ describe('TestCases', () => { for (const directory of fs.readdirSync(casesDirectory)) { if (!/^(\.|_)/.test(directory)) { // eslint-disable-next-line no-loop-func - it(`${directory} should compile to the expected result`, (done) => { - const directoryForCase = path.resolve(casesDirectory, directory); - const outputDirectoryForCase = path.resolve(outputDirectory, directory); - // eslint-disable-next-line import/no-dynamic-require, global-require - const webpackConfig = require(path.resolve( - directoryForCase, - 'webpack.config.js' - )); - for (const config of [].concat(webpackConfig)) { - Object.assign( - config, - { - mode: 'none', - context: directoryForCase, - output: Object.assign( - { - path: outputDirectoryForCase, - }, - config.output - ), - }, - config + it( + `${directory} should compile to the expected result`, + (done) => { + const directoryForCase = path.resolve(casesDirectory, directory); + const outputDirectoryForCase = path.resolve( + outputDirectory, + directory ); - } - webpack(webpackConfig, (err, stats) => { - if (err) { - done(err); - return; - } - done(); - // eslint-disable-next-line no-console - console.log( - stats.toString({ - context: path.resolve(__dirname, '..'), - chunks: true, - chunkModules: true, - modules: false, - }) - ); - if (stats.hasErrors()) { - done( - new Error( - stats.toString({ - context: path.resolve(__dirname, '..'), - errorDetails: true, - }) - ) + // eslint-disable-next-line import/no-dynamic-require, global-require + const webpackConfig = require(path.resolve( + directoryForCase, + 'webpack.config.js' + )); + for (const config of [].concat(webpackConfig)) { + Object.assign( + config, + { + mode: 'none', + context: directoryForCase, + output: Object.assign( + { + path: outputDirectoryForCase, + }, + config.output + ), + }, + config ); - return; } - const expectedDirectory = path.resolve(directoryForCase, 'expected'); - for (const file of fs.readdirSync(expectedDirectory)) { - const content = fs.readFileSync( - path.resolve(expectedDirectory, file), - 'utf-8' + webpack(webpackConfig, (err, stats) => { + if (err) { + done(err); + return; + } + done(); + // eslint-disable-next-line no-console + console.log( + stats.toString({ + context: path.resolve(__dirname, '..'), + chunks: true, + chunkModules: true, + modules: false, + }) ); - const actualContent = fs.readFileSync( - path.resolve(outputDirectoryForCase, file), - 'utf-8' + if (stats.hasErrors()) { + done( + new Error( + stats.toString({ + context: path.resolve(__dirname, '..'), + errorDetails: true, + }) + ) + ); + return; + } + const expectedDirectory = path.resolve( + directoryForCase, + 'expected' ); - expect(actualContent).toEqual(content); - } - done(); - }); - }, 10000); + + for (const file of walkSync(expectedDirectory)) { + const expectedContent = fs.readFileSync( + path.resolve(expectedDirectory, path.basename(file)), + 'utf-8' + ); + + const actualContent = fs.readFileSync( + path.resolve(outputDirectoryForCase, file), + 'utf-8' + ); + + expect(actualContent).toEqual(expectedContent); + } + done(); + }); + }, + 10000 + ); } } }); + +/** + * Synchronously traverse directory of files + * @param {String} dir + * @returns {String} // path to file or directory + */ +function* walkSync(dir) { + for (const file of fs.readdirSync(dir)) { + const pathToFile = path.join(dir, file); + const isDirectory = fs.statSync(pathToFile).isDirectory(); + if (isDirectory) { + yield* walkSync(pathToFile); + } else { + yield pathToFile; + } + } +} diff --git a/test/cases/filename/expected/main.be12b629.css b/test/cases/filename/expected/main.be12b629.css new file mode 100644 index 00000000..aea53e43 --- /dev/null +++ b/test/cases/filename/expected/main.be12b629.css @@ -0,0 +1,2 @@ +body { background: red; } + diff --git a/test/cases/filename/expected/main.ccd36095.css b/test/cases/filename/expected/main.ccd36095.css new file mode 100644 index 00000000..1a6052d7 --- /dev/null +++ b/test/cases/filename/expected/main.ccd36095.css @@ -0,0 +1,2 @@ +body { background: green; } + diff --git a/test/cases/filename/index.js b/test/cases/filename/index.js new file mode 100644 index 00000000..aa3357bf --- /dev/null +++ b/test/cases/filename/index.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/test/cases/filename/style1.css b/test/cases/filename/style1.css new file mode 100644 index 00000000..31fc5b8a --- /dev/null +++ b/test/cases/filename/style1.css @@ -0,0 +1 @@ +body { background: red; } diff --git a/test/cases/filename/style2.css b/test/cases/filename/style2.css new file mode 100644 index 00000000..56af6df5 --- /dev/null +++ b/test/cases/filename/style2.css @@ -0,0 +1 @@ +body { background: green; } diff --git a/test/cases/filename/webpack.config.js b/test/cases/filename/webpack.config.js new file mode 100644 index 00000000..fd282704 --- /dev/null +++ b/test/cases/filename/webpack.config.js @@ -0,0 +1,31 @@ +const Self = require('../../../'); + +module.exports = [1, 2].map((n) => { + return { + entry: { + 'demo/js/main': './index.js', + }, + module: { + rules: [ + { + test: /\.css$/, + use: [Self.loader, 'css-loader'], + }, + ], + }, + output: { + filename: '[name].[chunkhash:8].js', + }, + resolve: { + alias: { + './style.css': `./style${n}.css`, + }, + }, + plugins: [ + new Self({ + filename: ({ name, chunkhash }) => + `${name.replace('/js/', '/css/')}.${chunkhash.substring(0, 8)}.css`, + }), + ], + }; +}); From 3d12c5acdef833abe825528e513a43ad7aea571b Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Thu, 6 Dec 2018 02:35:15 -0800 Subject: [PATCH 02/16] fix(tests): test generated paths and filename --- test/TestCases.test.js | 13 ++--- .../expected/{1.css => 1.1.css} | 0 .../expected/{2.css => 2.2.css} | 0 .../expected/demo/css/main.f67bc35c.css | 2 + .../cases/filename/expected/main.be12b629.css | 2 - .../cases/filename/expected/main.ccd36095.css | 2 - test/cases/filename/style.css | 1 + test/cases/filename/style1.css | 1 - test/cases/filename/style2.css | 1 - test/cases/filename/webpack.config.js | 47 ++++++++----------- .../{async-one.css => 2.async-one.css} | 0 .../{async-two.css => 3.async-two.css} | 0 .../shared-import/expected/{1.css => 1.1.css} | 0 .../{async-one.css => 1.async-one.css} | 0 .../{async-two.css => 2.async-two.css} | 0 .../simple-async/expected/{1.css => 1.1.css} | 0 .../simple-async/expected/{2.css => 2.2.css} | 0 .../{vendors~main.css => 1.vendors~main.css} | 0 18 files changed, 28 insertions(+), 41 deletions(-) rename test/cases/composes-async/expected/{1.css => 1.1.css} (100%) rename test/cases/composes-async/expected/{2.css => 2.2.css} (100%) create mode 100644 test/cases/filename/expected/demo/css/main.f67bc35c.css delete mode 100644 test/cases/filename/expected/main.be12b629.css delete mode 100644 test/cases/filename/expected/main.ccd36095.css create mode 100644 test/cases/filename/style.css delete mode 100644 test/cases/filename/style1.css delete mode 100644 test/cases/filename/style2.css rename test/cases/multiple-entry/expected/{async-one.css => 2.async-one.css} (100%) rename test/cases/multiple-entry/expected/{async-two.css => 3.async-two.css} (100%) rename test/cases/shared-import/expected/{1.css => 1.1.css} (100%) rename test/cases/simple-async-load-css-fallback/expected/{async-one.css => 1.async-one.css} (100%) rename test/cases/simple-async-load-css-fallback/expected/{async-two.css => 2.async-two.css} (100%) rename test/cases/simple-async/expected/{1.css => 1.1.css} (100%) rename test/cases/simple-async/expected/{2.css => 2.2.css} (100%) rename test/cases/split-chunks/expected/{vendors~main.css => 1.vendors~main.css} (100%) diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 6b9b1899..97a2ee63 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -70,15 +70,12 @@ describe('TestCases', () => { ); for (const file of walkSync(expectedDirectory)) { - const expectedContent = fs.readFileSync( - path.resolve(expectedDirectory, path.basename(file)), - 'utf-8' - ); - - const actualContent = fs.readFileSync( - path.resolve(outputDirectoryForCase, file), - 'utf-8' + const actualFilePath = file.replace( + new RegExp(`/cases/${directory}/expected/`), + `/js/${directory}/` ); + const expectedContent = fs.readFileSync(file, 'utf-8'); + const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); expect(actualContent).toEqual(expectedContent); } diff --git a/test/cases/composes-async/expected/1.css b/test/cases/composes-async/expected/1.1.css similarity index 100% rename from test/cases/composes-async/expected/1.css rename to test/cases/composes-async/expected/1.1.css diff --git a/test/cases/composes-async/expected/2.css b/test/cases/composes-async/expected/2.2.css similarity index 100% rename from test/cases/composes-async/expected/2.css rename to test/cases/composes-async/expected/2.2.css diff --git a/test/cases/filename/expected/demo/css/main.f67bc35c.css b/test/cases/filename/expected/demo/css/main.f67bc35c.css new file mode 100644 index 00000000..d2743ef5 --- /dev/null +++ b/test/cases/filename/expected/demo/css/main.f67bc35c.css @@ -0,0 +1,2 @@ +body { background: purple; } + diff --git a/test/cases/filename/expected/main.be12b629.css b/test/cases/filename/expected/main.be12b629.css deleted file mode 100644 index aea53e43..00000000 --- a/test/cases/filename/expected/main.be12b629.css +++ /dev/null @@ -1,2 +0,0 @@ -body { background: red; } - diff --git a/test/cases/filename/expected/main.ccd36095.css b/test/cases/filename/expected/main.ccd36095.css deleted file mode 100644 index 1a6052d7..00000000 --- a/test/cases/filename/expected/main.ccd36095.css +++ /dev/null @@ -1,2 +0,0 @@ -body { background: green; } - diff --git a/test/cases/filename/style.css b/test/cases/filename/style.css new file mode 100644 index 00000000..484aaf18 --- /dev/null +++ b/test/cases/filename/style.css @@ -0,0 +1 @@ +body { background: purple; } diff --git a/test/cases/filename/style1.css b/test/cases/filename/style1.css deleted file mode 100644 index 31fc5b8a..00000000 --- a/test/cases/filename/style1.css +++ /dev/null @@ -1 +0,0 @@ -body { background: red; } diff --git a/test/cases/filename/style2.css b/test/cases/filename/style2.css deleted file mode 100644 index 56af6df5..00000000 --- a/test/cases/filename/style2.css +++ /dev/null @@ -1 +0,0 @@ -body { background: green; } diff --git a/test/cases/filename/webpack.config.js b/test/cases/filename/webpack.config.js index fd282704..bbb605ea 100644 --- a/test/cases/filename/webpack.config.js +++ b/test/cases/filename/webpack.config.js @@ -1,31 +1,24 @@ const Self = require('../../../'); -module.exports = [1, 2].map((n) => { - return { - entry: { - 'demo/js/main': './index.js', - }, - module: { - rules: [ - { - test: /\.css$/, - use: [Self.loader, 'css-loader'], - }, - ], - }, - output: { - filename: '[name].[chunkhash:8].js', - }, - resolve: { - alias: { - './style.css': `./style${n}.css`, +module.exports = { + entry: { + 'demo/js/main': './index.js', + }, + module: { + rules: [ + { + test: /\.css$/, + use: [Self.loader, 'css-loader'], }, - }, - plugins: [ - new Self({ - filename: ({ name, chunkhash }) => - `${name.replace('/js/', '/css/')}.${chunkhash.substring(0, 8)}.css`, - }), ], - }; -}); + }, + output: { + filename: '[name].[chunkhash:8].js', + }, + plugins: [ + new Self({ + filename: ({ name, chunkhash }) => + `${name.replace('/js/', '/css/')}.${chunkhash.substring(0, 8)}.css`, + }), + ], +}; diff --git a/test/cases/multiple-entry/expected/async-one.css b/test/cases/multiple-entry/expected/2.async-one.css similarity index 100% rename from test/cases/multiple-entry/expected/async-one.css rename to test/cases/multiple-entry/expected/2.async-one.css diff --git a/test/cases/multiple-entry/expected/async-two.css b/test/cases/multiple-entry/expected/3.async-two.css similarity index 100% rename from test/cases/multiple-entry/expected/async-two.css rename to test/cases/multiple-entry/expected/3.async-two.css diff --git a/test/cases/shared-import/expected/1.css b/test/cases/shared-import/expected/1.1.css similarity index 100% rename from test/cases/shared-import/expected/1.css rename to test/cases/shared-import/expected/1.1.css diff --git a/test/cases/simple-async-load-css-fallback/expected/async-one.css b/test/cases/simple-async-load-css-fallback/expected/1.async-one.css similarity index 100% rename from test/cases/simple-async-load-css-fallback/expected/async-one.css rename to test/cases/simple-async-load-css-fallback/expected/1.async-one.css diff --git a/test/cases/simple-async-load-css-fallback/expected/async-two.css b/test/cases/simple-async-load-css-fallback/expected/2.async-two.css similarity index 100% rename from test/cases/simple-async-load-css-fallback/expected/async-two.css rename to test/cases/simple-async-load-css-fallback/expected/2.async-two.css diff --git a/test/cases/simple-async/expected/1.css b/test/cases/simple-async/expected/1.1.css similarity index 100% rename from test/cases/simple-async/expected/1.css rename to test/cases/simple-async/expected/1.1.css diff --git a/test/cases/simple-async/expected/2.css b/test/cases/simple-async/expected/2.2.css similarity index 100% rename from test/cases/simple-async/expected/2.css rename to test/cases/simple-async/expected/2.2.css diff --git a/test/cases/split-chunks/expected/vendors~main.css b/test/cases/split-chunks/expected/1.vendors~main.css similarity index 100% rename from test/cases/split-chunks/expected/vendors~main.css rename to test/cases/split-chunks/expected/1.vendors~main.css From 1f06b990cae7d417217f3a61313ba48b7c0b7645 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Sat, 8 Dec 2018 19:00:17 -0800 Subject: [PATCH 03/16] feat: fix failing test, remove typo --- test/TestCases.test.js | 132 ++++++++---------- .../{main.f67bc35c.css => main.c4eb4321.css} | 0 2 files changed, 61 insertions(+), 71 deletions(-) rename test/cases/filename/expected/demo/css/{main.f67bc35c.css => main.c4eb4321.css} (100%) diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 97a2ee63..2f363183 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -9,81 +9,71 @@ describe('TestCases', () => { for (const directory of fs.readdirSync(casesDirectory)) { if (!/^(\.|_)/.test(directory)) { // eslint-disable-next-line no-loop-func - it( - `${directory} should compile to the expected result`, - (done) => { - const directoryForCase = path.resolve(casesDirectory, directory); - const outputDirectoryForCase = path.resolve( - outputDirectory, - directory + it(`${directory} should compile to the expected result`, (done) => { + const directoryForCase = path.resolve(casesDirectory, directory); + const outputDirectoryForCase = path.resolve(outputDirectory, directory); + // eslint-disable-next-line import/no-dynamic-require, global-require + const webpackConfig = require(path.resolve( + directoryForCase, + 'webpack.config.js' + )); + for (const config of [].concat(webpackConfig)) { + Object.assign( + config, + { + mode: 'none', + context: directoryForCase, + output: Object.assign( + { + path: outputDirectoryForCase, + }, + config.output + ), + }, + config ); - // eslint-disable-next-line import/no-dynamic-require, global-require - const webpackConfig = require(path.resolve( - directoryForCase, - 'webpack.config.js' - )); - for (const config of [].concat(webpackConfig)) { - Object.assign( - config, - { - mode: 'none', - context: directoryForCase, - output: Object.assign( - { - path: outputDirectoryForCase, - }, - config.output - ), - }, - config - ); + } + webpack(webpackConfig, (err, stats) => { + if (err) { + done(err); + return; } - webpack(webpackConfig, (err, stats) => { - if (err) { - done(err); - return; - } - done(); - // eslint-disable-next-line no-console - console.log( - stats.toString({ - context: path.resolve(__dirname, '..'), - chunks: true, - chunkModules: true, - modules: false, - }) - ); - if (stats.hasErrors()) { - done( - new Error( - stats.toString({ - context: path.resolve(__dirname, '..'), - errorDetails: true, - }) - ) - ); - return; - } - const expectedDirectory = path.resolve( - directoryForCase, - 'expected' + done(); + // eslint-disable-next-line no-console + console.log( + stats.toString({ + context: path.resolve(__dirname, '..'), + chunks: true, + chunkModules: true, + modules: false, + }) + ); + if (stats.hasErrors()) { + done( + new Error( + stats.toString({ + context: path.resolve(__dirname, '..'), + errorDetails: true, + }) + ) ); + return; + } + const expectedDirectory = path.resolve(directoryForCase, 'expected'); - for (const file of walkSync(expectedDirectory)) { - const actualFilePath = file.replace( - new RegExp(`/cases/${directory}/expected/`), - `/js/${directory}/` - ); - const expectedContent = fs.readFileSync(file, 'utf-8'); - const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); + for (const file of walkSync(expectedDirectory)) { + const actualFilePath = file.replace( + new RegExp(`/cases/${directory}/expected/`), + `/js/${directory}/` + ); + const expectedContent = fs.readFileSync(file, 'utf-8'); + const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); - expect(actualContent).toEqual(expectedContent); - } - done(); - }); - }, - 10000 - ); + expect(actualContent).toEqual(expectedContent); + } + done(); + }); + }, 10000); } } }); @@ -91,7 +81,7 @@ describe('TestCases', () => { /** * Synchronously traverse directory of files * @param {String} dir - * @returns {String} // path to file or directory + * @returns {String} path to file or directory */ function* walkSync(dir) { for (const file of fs.readdirSync(dir)) { diff --git a/test/cases/filename/expected/demo/css/main.f67bc35c.css b/test/cases/filename/expected/demo/css/main.c4eb4321.css similarity index 100% rename from test/cases/filename/expected/demo/css/main.f67bc35c.css rename to test/cases/filename/expected/demo/css/main.c4eb4321.css From 702b23e984d23750a1972ee457e7658da76d8a14 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Sat, 8 Dec 2018 20:20:03 -0800 Subject: [PATCH 04/16] feat: pass whole chunk to filename function add example to README.md --- README.md | 11 +++++++++++ src/index.js | 18 ++---------------- test/cases/filename/webpack.config.js | 4 ++-- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 072cb1ff..9c98ce96 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,17 @@ module.exports = { } ``` +#### Filename as function instead of string + +By using a function instead of a string, you can use chunk data to customize the filename. This is particularly useful when dealing with multiple entry points and wanting to get more control out of the filename for a given entry point/chunk. In the example below, the we'll change the filename to output the css to a different directory. + +```javascript +const miniCssExtractPlugin = new MiniCssExtractPlugin({ + filename: ({ name, chunkhash }) => + `${name.replace('/js/', '/css/')}.[chunkhash:8].css` +}) +``` + #### Long Term Caching For long term caching use `filename: "[contenthash].css"`. Optionally add `[name]`. diff --git a/src/index.js b/src/index.js index a48a558b..e3cc6041 100644 --- a/src/index.js +++ b/src/index.js @@ -170,22 +170,8 @@ class MiniCssExtractPlugin { (module) => module.type === MODULE_TYPE ); const { filename } = this.options; - let filenameTemplate = filename; - if (typeof filename === 'function') { - const { - hash: chunkhash, - contentHash: contenthash, - name, - id, - } = chunk; - - filenameTemplate = filename({ - chunkhash, - contenthash, - name, - id, - }); - } + const filenameTemplate = + typeof filename === 'function' ? filename(chunk) : filename; if (renderedModules.length > 0) { result.push({ diff --git a/test/cases/filename/webpack.config.js b/test/cases/filename/webpack.config.js index bbb605ea..e26a451d 100644 --- a/test/cases/filename/webpack.config.js +++ b/test/cases/filename/webpack.config.js @@ -17,8 +17,8 @@ module.exports = { }, plugins: [ new Self({ - filename: ({ name, chunkhash }) => - `${name.replace('/js/', '/css/')}.${chunkhash.substring(0, 8)}.css`, + filename: ({ name }) => + `${name.replace('/js/', '/css/')}.css`, }), ], }; From ddd1134c2cc24e53b3966a39e3fa007942675402 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Sat, 8 Dec 2018 20:33:50 -0800 Subject: [PATCH 05/16] fix: code formatting --- test/TestCases.test.js | 130 ++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 2f363183..674b13fc 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -9,71 +9,81 @@ describe('TestCases', () => { for (const directory of fs.readdirSync(casesDirectory)) { if (!/^(\.|_)/.test(directory)) { // eslint-disable-next-line no-loop-func - it(`${directory} should compile to the expected result`, (done) => { - const directoryForCase = path.resolve(casesDirectory, directory); - const outputDirectoryForCase = path.resolve(outputDirectory, directory); - // eslint-disable-next-line import/no-dynamic-require, global-require - const webpackConfig = require(path.resolve( - directoryForCase, - 'webpack.config.js' - )); - for (const config of [].concat(webpackConfig)) { - Object.assign( - config, - { - mode: 'none', - context: directoryForCase, - output: Object.assign( - { - path: outputDirectoryForCase, - }, - config.output - ), - }, - config + it( + `${directory} should compile to the expected result`, + (done) => { + const directoryForCase = path.resolve(casesDirectory, directory); + const outputDirectoryForCase = path.resolve( + outputDirectory, + directory ); - } - webpack(webpackConfig, (err, stats) => { - if (err) { - done(err); - return; - } - done(); - // eslint-disable-next-line no-console - console.log( - stats.toString({ - context: path.resolve(__dirname, '..'), - chunks: true, - chunkModules: true, - modules: false, - }) - ); - if (stats.hasErrors()) { - done( - new Error( - stats.toString({ - context: path.resolve(__dirname, '..'), - errorDetails: true, - }) - ) + // eslint-disable-next-line import/no-dynamic-require, global-require + const webpackConfig = require(path.resolve( + directoryForCase, + 'webpack.config.js' + )); + for (const config of [].concat(webpackConfig)) { + Object.assign( + config, + { + mode: 'none', + context: directoryForCase, + output: Object.assign( + { + path: outputDirectoryForCase, + }, + config.output + ), + }, + config ); - return; } - const expectedDirectory = path.resolve(directoryForCase, 'expected'); - - for (const file of walkSync(expectedDirectory)) { - const actualFilePath = file.replace( - new RegExp(`/cases/${directory}/expected/`), - `/js/${directory}/` + webpack(webpackConfig, (err, stats) => { + if (err) { + done(err); + return; + } + done(); + // eslint-disable-next-line no-console + console.log( + stats.toString({ + context: path.resolve(__dirname, '..'), + chunks: true, + chunkModules: true, + modules: false, + }) + ); + if (stats.hasErrors()) { + done( + new Error( + stats.toString({ + context: path.resolve(__dirname, '..'), + errorDetails: true, + }) + ) + ); + return; + } + const expectedDirectory = path.resolve( + directoryForCase, + 'expected' ); - const expectedContent = fs.readFileSync(file, 'utf-8'); - const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); - expect(actualContent).toEqual(expectedContent); - } - done(); - }); - }, 10000); + for (const file of walkSync(expectedDirectory)) { + const actualFilePath = file.replace( + new RegExp(`/cases/${directory}/expected/`), + `/js/${directory}/` + ); + const expectedContent = fs.readFileSync(file, 'utf-8'); + const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); + + expect(actualContent).toEqual(expectedContent); + } + done(); + }); + }, + 10000 + ); } } }); From c875e0c526ea181d958fdea5866d2fe243a93500 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Sat, 8 Dec 2018 20:40:17 -0800 Subject: [PATCH 06/16] fix: rename expected file to match actual file hash --- .../expected/demo/css/{main.c4eb4321.css => main.f67bc35c.css} | 0 test/cases/filename/webpack.config.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename test/cases/filename/expected/demo/css/{main.c4eb4321.css => main.f67bc35c.css} (100%) diff --git a/test/cases/filename/expected/demo/css/main.c4eb4321.css b/test/cases/filename/expected/demo/css/main.f67bc35c.css similarity index 100% rename from test/cases/filename/expected/demo/css/main.c4eb4321.css rename to test/cases/filename/expected/demo/css/main.f67bc35c.css diff --git a/test/cases/filename/webpack.config.js b/test/cases/filename/webpack.config.js index e26a451d..c8566f88 100644 --- a/test/cases/filename/webpack.config.js +++ b/test/cases/filename/webpack.config.js @@ -18,7 +18,7 @@ module.exports = { plugins: [ new Self({ filename: ({ name }) => - `${name.replace('/js/', '/css/')}.css`, + `${name.replace('/js/', '/css/')}.[chunkhash:8].css`, }), ], }; From 3a03fc4c5c9fa1706477bd02a3565e6984bce386 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Sat, 8 Dec 2018 22:42:08 -0800 Subject: [PATCH 07/16] fix: filename test by removing hash from output --- .../expected/demo/css/{main.f67bc35c.css => main.css} | 0 test/cases/filename/webpack.config.js | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename test/cases/filename/expected/demo/css/{main.f67bc35c.css => main.css} (100%) diff --git a/test/cases/filename/expected/demo/css/main.f67bc35c.css b/test/cases/filename/expected/demo/css/main.css similarity index 100% rename from test/cases/filename/expected/demo/css/main.f67bc35c.css rename to test/cases/filename/expected/demo/css/main.css diff --git a/test/cases/filename/webpack.config.js b/test/cases/filename/webpack.config.js index c8566f88..7f572970 100644 --- a/test/cases/filename/webpack.config.js +++ b/test/cases/filename/webpack.config.js @@ -13,12 +13,12 @@ module.exports = { ], }, output: { - filename: '[name].[chunkhash:8].js', + filename: '[name].js', }, plugins: [ new Self({ filename: ({ name }) => - `${name.replace('/js/', '/css/')}.[chunkhash:8].css`, + `${name.replace('/js/', '/css/')}.css`, }), ], }; From 8cc2553735898a8a5ac34985effdf95b2b854bf0 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 12:41:29 +0000 Subject: [PATCH 08/16] fix(test): expected filenames were incorrect --- package-lock.json | 28 ++++++++++++++----- .../expected/{styles.css => 1.styles.css} | 0 .../{1.vendors~main.css => vendors~main.css} | 0 3 files changed, 21 insertions(+), 7 deletions(-) rename test/cases/split-chunks-single/expected/{styles.css => 1.styles.css} (100%) rename test/cases/split-chunks/expected/{1.vendors~main.css => vendors~main.css} (100%) diff --git a/package-lock.json b/package-lock.json index d3a4647e..8ee7caa0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5832,12 +5832,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5852,17 +5854,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5979,7 +5984,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5991,6 +5997,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6005,6 +6012,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6012,12 +6020,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -6036,6 +6046,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6116,7 +6127,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6128,6 +6140,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6249,6 +6262,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/test/cases/split-chunks-single/expected/styles.css b/test/cases/split-chunks-single/expected/1.styles.css similarity index 100% rename from test/cases/split-chunks-single/expected/styles.css rename to test/cases/split-chunks-single/expected/1.styles.css diff --git a/test/cases/split-chunks/expected/1.vendors~main.css b/test/cases/split-chunks/expected/vendors~main.css similarity index 100% rename from test/cases/split-chunks/expected/1.vendors~main.css rename to test/cases/split-chunks/expected/vendors~main.css From 596f93794a87c9ede301ab754d55eafc0d7096bc Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 13:06:09 +0000 Subject: [PATCH 09/16] chore(code-formatting): fix code formatting --- test/TestCases.test.js | 130 +++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 70 deletions(-) diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 674b13fc..2f363183 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -9,81 +9,71 @@ describe('TestCases', () => { for (const directory of fs.readdirSync(casesDirectory)) { if (!/^(\.|_)/.test(directory)) { // eslint-disable-next-line no-loop-func - it( - `${directory} should compile to the expected result`, - (done) => { - const directoryForCase = path.resolve(casesDirectory, directory); - const outputDirectoryForCase = path.resolve( - outputDirectory, - directory + it(`${directory} should compile to the expected result`, (done) => { + const directoryForCase = path.resolve(casesDirectory, directory); + const outputDirectoryForCase = path.resolve(outputDirectory, directory); + // eslint-disable-next-line import/no-dynamic-require, global-require + const webpackConfig = require(path.resolve( + directoryForCase, + 'webpack.config.js' + )); + for (const config of [].concat(webpackConfig)) { + Object.assign( + config, + { + mode: 'none', + context: directoryForCase, + output: Object.assign( + { + path: outputDirectoryForCase, + }, + config.output + ), + }, + config ); - // eslint-disable-next-line import/no-dynamic-require, global-require - const webpackConfig = require(path.resolve( - directoryForCase, - 'webpack.config.js' - )); - for (const config of [].concat(webpackConfig)) { - Object.assign( - config, - { - mode: 'none', - context: directoryForCase, - output: Object.assign( - { - path: outputDirectoryForCase, - }, - config.output - ), - }, - config - ); + } + webpack(webpackConfig, (err, stats) => { + if (err) { + done(err); + return; } - webpack(webpackConfig, (err, stats) => { - if (err) { - done(err); - return; - } - done(); - // eslint-disable-next-line no-console - console.log( - stats.toString({ - context: path.resolve(__dirname, '..'), - chunks: true, - chunkModules: true, - modules: false, - }) - ); - if (stats.hasErrors()) { - done( - new Error( - stats.toString({ - context: path.resolve(__dirname, '..'), - errorDetails: true, - }) - ) - ); - return; - } - const expectedDirectory = path.resolve( - directoryForCase, - 'expected' + done(); + // eslint-disable-next-line no-console + console.log( + stats.toString({ + context: path.resolve(__dirname, '..'), + chunks: true, + chunkModules: true, + modules: false, + }) + ); + if (stats.hasErrors()) { + done( + new Error( + stats.toString({ + context: path.resolve(__dirname, '..'), + errorDetails: true, + }) + ) ); + return; + } + const expectedDirectory = path.resolve(directoryForCase, 'expected'); - for (const file of walkSync(expectedDirectory)) { - const actualFilePath = file.replace( - new RegExp(`/cases/${directory}/expected/`), - `/js/${directory}/` - ); - const expectedContent = fs.readFileSync(file, 'utf-8'); - const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); + for (const file of walkSync(expectedDirectory)) { + const actualFilePath = file.replace( + new RegExp(`/cases/${directory}/expected/`), + `/js/${directory}/` + ); + const expectedContent = fs.readFileSync(file, 'utf-8'); + const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); - expect(actualContent).toEqual(expectedContent); - } - done(); - }); - }, - 10000 - ); + expect(actualContent).toEqual(expectedContent); + } + done(); + }); + }, 10000); } } }); From cea188cc971dc2454f4d8cf86b27bd7752eae24e Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 13:59:14 +0000 Subject: [PATCH 10/16] fix(tests): use path.resolve to generate outputFile path update readme to reflect webpack's output.filename --- README.md | 4 ++-- src/index.js | 2 +- test/TestCases.test.js | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9c98ce96..7e89e61f 100644 --- a/README.md +++ b/README.md @@ -274,8 +274,8 @@ By using a function instead of a string, you can use chunk data to customize the ```javascript const miniCssExtractPlugin = new MiniCssExtractPlugin({ - filename: ({ name, chunkhash }) => - `${name.replace('/js/', '/css/')}.[chunkhash:8].css` + filename: (chunkData) => + `${chunkData.name.replace('/js/', '/css/')}.[chunkhash:8].css` }) ``` diff --git a/src/index.js b/src/index.js index e3cc6041..d5460b0b 100644 --- a/src/index.js +++ b/src/index.js @@ -125,7 +125,7 @@ class MiniCssExtractPlugin { this.options.chunkFilename = filename; } else { // Elsewise prefix '[id].' in front of the basename to make it changing - this.options.chunkFilename = DEFAULT_FILENAME.replace( + this.options.chunkFilename = filename.replace( /(^|\/)([^/]*(?:\?|$))/, '$1[id].$2' ); diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 2f363183..ced36d12 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -62,10 +62,7 @@ describe('TestCases', () => { const expectedDirectory = path.resolve(directoryForCase, 'expected'); for (const file of walkSync(expectedDirectory)) { - const actualFilePath = file.replace( - new RegExp(`/cases/${directory}/expected/`), - `/js/${directory}/` - ); + const actualFilePath = path.resolve(outputDirectory, file); const expectedContent = fs.readFileSync(file, 'utf-8'); const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); From b88096f542815db481e2ed14360f2551bb1acd13 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 14:05:14 +0000 Subject: [PATCH 11/16] fix(chunkfilename): use DEFAULT_FILENAME use DEFAULT_FILENAME for options.chunkFilename when options.filename is a function --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index d5460b0b..e3cc6041 100644 --- a/src/index.js +++ b/src/index.js @@ -125,7 +125,7 @@ class MiniCssExtractPlugin { this.options.chunkFilename = filename; } else { // Elsewise prefix '[id].' in front of the basename to make it changing - this.options.chunkFilename = filename.replace( + this.options.chunkFilename = DEFAULT_FILENAME.replace( /(^|\/)([^/]*(?:\?|$))/, '$1[id].$2' ); From 2ad36c61ade5a8bb3f075182caf05c9aa2bda83a Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 16:00:43 +0000 Subject: [PATCH 12/16] fix(tests): actualFilepath should to point to generated file --- test/TestCases.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/TestCases.test.js b/test/TestCases.test.js index ced36d12..c0f16be3 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -62,7 +62,10 @@ describe('TestCases', () => { const expectedDirectory = path.resolve(directoryForCase, 'expected'); for (const file of walkSync(expectedDirectory)) { - const actualFilePath = path.resolve(outputDirectory, file); + const actualFilePath = file.replace( + expectedDirectory, + path.join(outputDirectory, directory) + ); const expectedContent = fs.readFileSync(file, 'utf-8'); const actualContent = fs.readFileSync(actualFilePath, 'utf-8'); From cdb066a6e4594a4b00059d2ea4445f018c65c60f Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 19 Dec 2018 16:33:01 +0000 Subject: [PATCH 13/16] fix(options): chunkFilename chunkFilename should handle string and function options.filename --- src/index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index e3cc6041..6bdecf1d 100644 --- a/src/index.js +++ b/src/index.js @@ -121,14 +121,18 @@ class MiniCssExtractPlugin { if (!this.options.chunkFilename) { const { filename } = this.options; // Anything changing depending on chunk is fine - if (typeof filename === 'string' && REGEXP_PLACEHOLDERS.test(filename)) { - this.options.chunkFilename = filename; + if (typeof filename === 'string') { + if (REGEXP_PLACEHOLDERS.test(filename)) { + this.options.chunkFilename = filename; + } else { + // Elsewise prefix '[id].' in front of the basename to make it changing + this.options.chunkFilename = filename.replace( + /(^|\/)([^/]*(?:\?|$))/, + '$1[id].$2' + ); + } } else { - // Elsewise prefix '[id].' in front of the basename to make it changing - this.options.chunkFilename = DEFAULT_FILENAME.replace( - /(^|\/)([^/]*(?:\?|$))/, - '$1[id].$2' - ); + this.options.chunkFilename = `[id].${DEFAULT_FILENAME}`; } } } From 9389a57a82f2672d731fd85a46c0ef62a3f31de8 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 23 Jan 2019 19:50:49 -0800 Subject: [PATCH 14/16] chore(filenametemplate): pass filename function directly --- package-lock.json | 13 +++++++++---- src/index.js | 4 +--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ee7caa0..2d1dcb5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5811,7 +5811,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6226,7 +6227,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6282,6 +6284,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6325,12 +6328,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/src/index.js b/src/index.js index 6bdecf1d..0caa4f72 100644 --- a/src/index.js +++ b/src/index.js @@ -173,9 +173,7 @@ class MiniCssExtractPlugin { const renderedModules = Array.from(chunk.modulesIterable).filter( (module) => module.type === MODULE_TYPE ); - const { filename } = this.options; - const filenameTemplate = - typeof filename === 'function' ? filename(chunk) : filename; + const { filename: filenameTemplate } = this.options; if (renderedModules.length > 0) { result.push({ From f0743f9a708659064ec76319ecedcfb45bf132c7 Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 23 Jan 2019 20:00:09 -0800 Subject: [PATCH 15/16] fix(vulnerability): resolve vulnerability found in npm audit https://circleci.com/gh/webpack-contrib/mini-css-extract-plugin/866?utm_campaign=workflow-failedutm_source=notification --- package-lock.json | 193 ++++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 118 insertions(+), 77 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2d1dcb5c..b783bb82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2907,9 +2907,9 @@ } }, "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, "console-browserify": { @@ -5019,7 +5019,7 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true } @@ -5528,7 +5528,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { @@ -5665,9 +5665,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "dev": true, "requires": { "debug": "=3.1.0" @@ -5811,8 +5811,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -5833,14 +5832,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5855,20 +5852,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5985,8 +5979,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5998,7 +5991,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6013,7 +6005,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6021,14 +6012,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -6047,7 +6036,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6128,8 +6116,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6141,7 +6128,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6227,8 +6213,7 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6264,7 +6249,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6284,7 +6268,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6328,14 +6311,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -6821,9 +6802,9 @@ "dev": true }, "handle-thing": { - "version": "1.2.5", - "resolved": "http://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", "dev": true }, "handlebars": { @@ -7068,7 +7049,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -7097,7 +7078,7 @@ }, "http-proxy-middleware": { "version": "0.18.0", - "resolved": "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", "dev": true, "requires": { @@ -9556,7 +9537,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -10883,7 +10864,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true } @@ -13364,32 +13345,75 @@ "dev": true }, "spdy": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", - "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", "dev": true, "requires": { - "debug": "^2.6.8", - "handle-thing": "^1.2.5", + "debug": "^4.1.0", + "handle-thing": "^2.0.0", "http-deceiver": "^1.2.7", - "safe-buffer": "^5.0.1", "select-hose": "^2.0.0", - "spdy-transport": "^2.0.18" + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, "spdy-transport": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz", - "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "requires": { - "debug": "^2.6.8", - "detect-node": "^2.0.3", + "debug": "^4.1.0", + "detect-node": "^2.0.4", "hpack.js": "^2.1.6", - "obuf": "^1.1.1", - "readable-stream": "^2.2.9", - "safe-buffer": "^5.0.1", - "wbuf": "^1.7.2" + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "split": { @@ -15926,9 +15950,9 @@ } }, "webpack-dev-server": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz", - "integrity": "sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", + "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -15950,12 +15974,14 @@ "portfinder": "^1.0.9", "schema-utils": "^1.0.0", "selfsigned": "^1.9.1", + "semver": "^5.6.0", "serve-index": "^1.7.2", "sockjs": "0.3.19", "sockjs-client": "1.3.0", - "spdy": "^3.4.1", + "spdy": "^4.0.0", "strip-ansi": "^3.0.0", "supports-color": "^5.1.0", + "url": "^0.11.0", "webpack-dev-middleware": "3.4.0", "webpack-log": "^2.0.0", "yargs": "12.0.2" @@ -16060,13 +16086,13 @@ } }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -16243,6 +16269,15 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -16408,20 +16443,20 @@ } }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -16451,6 +16486,12 @@ "find-up": "^3.0.0" } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "yargs": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", diff --git a/package.json b/package.json index 0d4f3dac..7d6db645 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "webpack": "^4.14.0", "webpack-cli": "^2.0.13", "webpack-defaults": "^2.3.0", - "webpack-dev-server": "^3.1.1" + "webpack-dev-server": "^3.1.14" }, "keywords": [ "webpack" From 63d98f3680b4b26ebfb4271359281581ddddd01e Mon Sep 17 00:00:00 2001 From: Kevin Chappell Date: Wed, 23 Jan 2019 20:10:38 -0800 Subject: [PATCH 16/16] fix(filename): ensure chunk is passed to filename template function --- package-lock.json | 12 ++++++------ src/index.js | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index b783bb82..205b5be4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5019,7 +5019,7 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true } @@ -5528,7 +5528,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { @@ -7049,7 +7049,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -7078,7 +7078,7 @@ }, "http-proxy-middleware": { "version": "0.18.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "resolved": "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", "dev": true, "requires": { @@ -9537,7 +9537,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -10864,7 +10864,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true } diff --git a/src/index.js b/src/index.js index 0caa4f72..6bdecf1d 100644 --- a/src/index.js +++ b/src/index.js @@ -173,7 +173,9 @@ class MiniCssExtractPlugin { const renderedModules = Array.from(chunk.modulesIterable).filter( (module) => module.type === MODULE_TYPE ); - const { filename: filenameTemplate } = this.options; + const { filename } = this.options; + const filenameTemplate = + typeof filename === 'function' ? filename(chunk) : filename; if (renderedModules.length > 0) { result.push({