From ef4bd79b191ebfd52e3422657aae4a1217bb1ef1 Mon Sep 17 00:00:00 2001 From: Alexander Krasnoyarov Date: Fri, 2 Oct 2020 20:00:16 +0300 Subject: [PATCH 1/4] test: empty chunk --- package-lock.json | 6 ++-- package.json | 2 +- test/cases/split-chunks-all/a.js | 1 + test/cases/split-chunks-all/b.js | 1 + .../expected/webpack-4/styles~a~b.css | 4 +++ .../split-chunks-all/expected/webpack-5/2.css | 4 +++ test/cases/split-chunks-all/index.js | 1 + test/cases/split-chunks-all/style.css | 3 ++ test/cases/split-chunks-all/webpack.config.js | 36 +++++++++++++++++++ 9 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 test/cases/split-chunks-all/a.js create mode 100644 test/cases/split-chunks-all/b.js create mode 100644 test/cases/split-chunks-all/expected/webpack-4/styles~a~b.css create mode 100644 test/cases/split-chunks-all/expected/webpack-5/2.css create mode 100644 test/cases/split-chunks-all/index.js create mode 100644 test/cases/split-chunks-all/style.css create mode 100644 test/cases/split-chunks-all/webpack.config.js diff --git a/package-lock.json b/package-lock.json index 51232284..3b8df913 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16490,9 +16490,9 @@ "dev": true }, "webpack": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", - "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", "dev": true, "requires": { "@webassemblyjs/ast": "1.9.0", diff --git a/package.json b/package.json index c9c0662b..cf442091 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.1.1", "standard-version": "^9.0.0", - "webpack": "^4.44.1", + "webpack": "^4.44.2", "webpack-cli": "^3.3.6", "webpack-dev-server": "^3.7.2" }, diff --git a/test/cases/split-chunks-all/a.js b/test/cases/split-chunks-all/a.js new file mode 100644 index 00000000..aa3357bf --- /dev/null +++ b/test/cases/split-chunks-all/a.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/test/cases/split-chunks-all/b.js b/test/cases/split-chunks-all/b.js new file mode 100644 index 00000000..aa3357bf --- /dev/null +++ b/test/cases/split-chunks-all/b.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/test/cases/split-chunks-all/expected/webpack-4/styles~a~b.css b/test/cases/split-chunks-all/expected/webpack-4/styles~a~b.css new file mode 100644 index 00000000..cebc5c1c --- /dev/null +++ b/test/cases/split-chunks-all/expected/webpack-4/styles~a~b.css @@ -0,0 +1,4 @@ +body { + background: red; +} + diff --git a/test/cases/split-chunks-all/expected/webpack-5/2.css b/test/cases/split-chunks-all/expected/webpack-5/2.css new file mode 100644 index 00000000..cebc5c1c --- /dev/null +++ b/test/cases/split-chunks-all/expected/webpack-5/2.css @@ -0,0 +1,4 @@ +body { + background: red; +} + diff --git a/test/cases/split-chunks-all/index.js b/test/cases/split-chunks-all/index.js new file mode 100644 index 00000000..aa3357bf --- /dev/null +++ b/test/cases/split-chunks-all/index.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/test/cases/split-chunks-all/style.css b/test/cases/split-chunks-all/style.css new file mode 100644 index 00000000..67ce83e4 --- /dev/null +++ b/test/cases/split-chunks-all/style.css @@ -0,0 +1,3 @@ +body { + background: red; +} diff --git a/test/cases/split-chunks-all/webpack.config.js b/test/cases/split-chunks-all/webpack.config.js new file mode 100644 index 00000000..e9edc39b --- /dev/null +++ b/test/cases/split-chunks-all/webpack.config.js @@ -0,0 +1,36 @@ +import webpack from 'webpack'; + +import Self from '../../../src'; + +module.exports = { + entry: { + a: './a.js', + b: './b.js', + }, + module: { + rules: [ + { + test: /\.css$/, + use: [Self.loader, 'css-loader'], + }, + ], + }, + optimization: { + splitChunks: { + cacheGroups: { + styles: + webpack.version[0] === '4' + ? { + chunks: 'all', + enforce: true, + } + : { + type: 'css/mini-extract', + chunks: 'all', + enforce: true, + }, + }, + }, + }, + plugins: [new Self()], +}; From 5fafdf80322c0f501bd092683b3a829620acce65 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 7 Oct 2020 12:02:08 +0200 Subject: [PATCH 2/4] feat opt-in to transitive only side effects (webpack@5) (#599) --- src/CssDependency.js | 5 + test/TestCases.test.js | 28 ++-- .../expected/webpack-5/common.js | 45 +----- .../expected/webpack-5/entry1.js | 24 +-- .../dependOn/expected/webpack-5/common.js | 34 +---- .../dependOn/expected/webpack-5/entry1.js | 13 +- .../es-module-concatenation-modules/a.css | 3 + .../es-module-concatenation-modules/b.css | 3 + .../es-module-concatenation-modules/c.css | 3 + .../expected/webpack-4/main.css | 12 ++ .../expected/webpack-4/main.js | 141 ++++++++++++++++++ .../expected/webpack-5/main.css | 12 ++ .../expected/webpack-5/main.js | 124 +++++++++++++++ .../es-module-concatenation-modules/index.js | 11 ++ .../webpack.config.js | 41 +++++ .../expected/webpack-5/main.js | 12 -- test/cases/hmr/expected/webpack-5/main.js | 2 +- .../split-chunks-all/expected/webpack-5/2.js | 1 + test/enforce-esm.test.js | 2 +- 19 files changed, 384 insertions(+), 132 deletions(-) create mode 100644 test/cases/es-module-concatenation-modules/a.css create mode 100644 test/cases/es-module-concatenation-modules/b.css create mode 100644 test/cases/es-module-concatenation-modules/c.css create mode 100644 test/cases/es-module-concatenation-modules/expected/webpack-4/main.css create mode 100644 test/cases/es-module-concatenation-modules/expected/webpack-4/main.js create mode 100644 test/cases/es-module-concatenation-modules/expected/webpack-5/main.css create mode 100644 test/cases/es-module-concatenation-modules/expected/webpack-5/main.js create mode 100644 test/cases/es-module-concatenation-modules/index.js create mode 100644 test/cases/es-module-concatenation-modules/webpack.config.js create mode 100644 test/cases/split-chunks-all/expected/webpack-5/2.js diff --git a/src/CssDependency.js b/src/CssDependency.js index d7d302e6..8620de50 100644 --- a/src/CssDependency.js +++ b/src/CssDependency.js @@ -20,6 +20,11 @@ class CssDependency extends webpack.Dependency { return `css-module-${this.identifier}-${this.identifierIndex}`; } + // eslint-disable-next-line class-methods-use-this + getModuleEvaluationSideEffectsState() { + return webpack.ModuleGraphConnection.TRANSITIVE_ONLY; + } + serialize(context) { const { write } = context; diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 08d0233d..b428b63d 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -47,19 +47,23 @@ function compareDirectory(actual, expected) { const content = fs.readFileSync(path.resolve(expected, file), 'utf8'); let actualContent; - try { - actualContent = fs.readFileSync(path.resolve(actual, file), 'utf8'); - } catch (error) { - // eslint-disable-next-line no-console - console.log(error); + if (/^MISSING/.test(content)) { + expect(fs.existsSync(path.resolve(actual, file))).toBe(false); + } else { + try { + actualContent = fs.readFileSync(path.resolve(actual, file), 'utf8'); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); - const dir = fs.readdirSync(actual); + const dir = fs.readdirSync(actual); - // eslint-disable-next-line no-console - console.log({ [actual]: dir }); - } + // eslint-disable-next-line no-console + console.log({ [actual]: dir }); + } - expect(actualContent).toEqual(content); + expect(actualContent).toEqual(content); + } } } } @@ -119,6 +123,10 @@ describe('TestCases', () => { done(err); return; } + if (stats.hasErrors()) { + done(new Error(stats.toString())); + return; + } done(); diff --git a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js index 3e43d6d5..d3a07314 100644 --- a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js +++ b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js @@ -1,37 +1,20 @@ /******/ (() => { // webpackBootstrap +/******/ "use strict"; /******/ var __webpack_modules__ = ([ /* 0 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -"use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleC_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var _styleC_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleC_css__WEBPACK_IMPORTED_MODULE_0__); /***/ }), /* 1 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin - -/***/ }), -/* 2 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -"use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleD_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); -/* harmony import */ var _styleD_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleD_css__WEBPACK_IMPORTED_MODULE_0__); - -/***/ }), -/* 3 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin /***/ }) /******/ ]); @@ -63,30 +46,6 @@ __webpack_require__.r(__webpack_exports__); /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ -/******/ /* webpack/runtime/compat get default export */ -/******/ (() => { -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = (module) => { -/******/ var getter = module && module.__esModule ? -/******/ () => module['default'] : -/******/ () => module; -/******/ __webpack_require__.d(getter, { a: getter }); -/******/ return getter; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) @@ -116,7 +75,7 @@ __webpack_require__.r(__webpack_exports__); /******/ /******/ var deferredModules = [ /******/ [0], -/******/ [2] +/******/ [1] /******/ ]; /******/ // no chunk on demand loading /******/ diff --git a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/entry1.js b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/entry1.js index 687aa284..e574604c 100644 --- a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/entry1.js +++ b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/entry1.js @@ -1,41 +1,23 @@ (self["webpackChunk"] = self["webpackChunk"] || []).push([[1],[ /* 0 */, /* 1 */, -/* 2 */, -/* 3 */, -/* 4 */ +/* 2 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleB_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); -/* harmony import */ var _styleB_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleB_css__WEBPACK_IMPORTED_MODULE_0__); /***/ }), -/* 5 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin - -/***/ }), -/* 6 */ +/* 3 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleA_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); -/* harmony import */ var _styleA_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleA_css__WEBPACK_IMPORTED_MODULE_0__); -/***/ }), -/* 7 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin - /***/ }) ], -0,[[6,0],[4,0]]]); \ No newline at end of file +0,[[3,0],[2,0]]]); \ No newline at end of file diff --git a/test/cases/dependOn/expected/webpack-5/common.js b/test/cases/dependOn/expected/webpack-5/common.js index 0b8c0134..13e02ea6 100644 --- a/test/cases/dependOn/expected/webpack-5/common.js +++ b/test/cases/dependOn/expected/webpack-5/common.js @@ -1,21 +1,13 @@ /******/ (() => { // webpackBootstrap +/******/ "use strict"; /******/ var __webpack_modules__ = ([ /* 0 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -"use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleB_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var _styleB_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleB_css__WEBPACK_IMPORTED_MODULE_0__); -/***/ }), -/* 1 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin - /***/ }) /******/ ]); /************************************************************************/ @@ -46,30 +38,6 @@ __webpack_require__.r(__webpack_exports__); /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ -/******/ /* webpack/runtime/compat get default export */ -/******/ (() => { -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = (module) => { -/******/ var getter = module && module.__esModule ? -/******/ () => module['default'] : -/******/ () => module; -/******/ __webpack_require__.d(getter, { a: getter }); -/******/ return getter; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) diff --git a/test/cases/dependOn/expected/webpack-5/entry1.js b/test/cases/dependOn/expected/webpack-5/entry1.js index 59c1c76d..e9b46db5 100644 --- a/test/cases/dependOn/expected/webpack-5/entry1.js +++ b/test/cases/dependOn/expected/webpack-5/entry1.js @@ -1,22 +1,13 @@ (self["webpackChunk"] = self["webpackChunk"] || []).push([[1],[ /* 0 */, -/* 1 */, -/* 2 */ +/* 1 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _styleA_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); -/* harmony import */ var _styleA_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_styleA_css__WEBPACK_IMPORTED_MODULE_0__); -/***/ }), -/* 3 */ -/***/ (() => { - -// extracted by mini-css-extract-plugin - /***/ }) ], -0,[[2,0]]]); \ No newline at end of file +0,[[1,0]]]); \ No newline at end of file diff --git a/test/cases/es-module-concatenation-modules/a.css b/test/cases/es-module-concatenation-modules/a.css new file mode 100644 index 00000000..9cad053c --- /dev/null +++ b/test/cases/es-module-concatenation-modules/a.css @@ -0,0 +1,3 @@ +.a { + background: red; +} diff --git a/test/cases/es-module-concatenation-modules/b.css b/test/cases/es-module-concatenation-modules/b.css new file mode 100644 index 00000000..295b4a8f --- /dev/null +++ b/test/cases/es-module-concatenation-modules/b.css @@ -0,0 +1,3 @@ +.b { + background: green; +} diff --git a/test/cases/es-module-concatenation-modules/c.css b/test/cases/es-module-concatenation-modules/c.css new file mode 100644 index 00000000..cbdd76cc --- /dev/null +++ b/test/cases/es-module-concatenation-modules/c.css @@ -0,0 +1,3 @@ +.c { + background: blue; +} diff --git a/test/cases/es-module-concatenation-modules/expected/webpack-4/main.css b/test/cases/es-module-concatenation-modules/expected/webpack-4/main.css new file mode 100644 index 00000000..414d12e5 --- /dev/null +++ b/test/cases/es-module-concatenation-modules/expected/webpack-4/main.css @@ -0,0 +1,12 @@ +.foo__a { + background: red; +} + +.foo__b { + background: green; +} + +.foo__c { + background: blue; +} + diff --git a/test/cases/es-module-concatenation-modules/expected/webpack-4/main.js b/test/cases/es-module-concatenation-modules/expected/webpack-4/main.js new file mode 100644 index 00000000..3296fa52 --- /dev/null +++ b/test/cases/es-module-concatenation-modules/expected/webpack-4/main.js @@ -0,0 +1,141 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXPORTS +__webpack_require__.d(__webpack_exports__, "c", function() { return /* reexport */ c; }); +__webpack_require__.d(__webpack_exports__, "a", function() { return /* reexport */ a_namespaceObject; }); +__webpack_require__.d(__webpack_exports__, "b", function() { return /* reexport */ b_namespaceObject; }); + +// NAMESPACE OBJECT: ./a.css +var a_namespaceObject = {}; +__webpack_require__.r(a_namespaceObject); +__webpack_require__.d(a_namespaceObject, "a", function() { return a; }); + +// NAMESPACE OBJECT: ./b.css +var b_namespaceObject = {}; +__webpack_require__.r(b_namespaceObject); +__webpack_require__.d(b_namespaceObject, "b", function() { return b; }); + +// NAMESPACE OBJECT: ./index.js +var index_namespaceObject = {}; +__webpack_require__.r(index_namespaceObject); +__webpack_require__.d(index_namespaceObject, "c", function() { return c; }); +__webpack_require__.d(index_namespaceObject, "a", function() { return a_namespaceObject; }); +__webpack_require__.d(index_namespaceObject, "b", function() { return b_namespaceObject; }); + +// CONCATENATED MODULE: ./a.css +// extracted by mini-css-extract-plugin +const a = "foo__a"; +// CONCATENATED MODULE: ./b.css +// extracted by mini-css-extract-plugin +const b = "foo__b"; +// CONCATENATED MODULE: ./c.css +// extracted by mini-css-extract-plugin +const c = "foo__c"; +// CONCATENATED MODULE: ./index.js +/* eslint-disable import/no-namespace */ + + + + + + + + +// eslint-disable-next-line no-console +console.log(index_namespaceObject); + + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/test/cases/es-module-concatenation-modules/expected/webpack-5/main.css b/test/cases/es-module-concatenation-modules/expected/webpack-5/main.css new file mode 100644 index 00000000..414d12e5 --- /dev/null +++ b/test/cases/es-module-concatenation-modules/expected/webpack-5/main.css @@ -0,0 +1,12 @@ +.foo__a { + background: red; +} + +.foo__b { + background: green; +} + +.foo__c { + background: blue; +} + diff --git a/test/cases/es-module-concatenation-modules/expected/webpack-5/main.js b/test/cases/es-module-concatenation-modules/expected/webpack-5/main.js new file mode 100644 index 00000000..9b1ae07f --- /dev/null +++ b/test/cases/es-module-concatenation-modules/expected/webpack-5/main.js @@ -0,0 +1,124 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ([ +/* 0 */ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + "a": () => /* reexport */ a_namespaceObject, + "b": () => /* reexport */ b_namespaceObject, + "c": () => /* reexport */ c +}); + +// NAMESPACE OBJECT: ./a.css +var a_namespaceObject = {}; +__webpack_require__.r(a_namespaceObject); +__webpack_require__.d(a_namespaceObject, { + "a": () => a +}); + +// NAMESPACE OBJECT: ./b.css +var b_namespaceObject = {}; +__webpack_require__.r(b_namespaceObject); +__webpack_require__.d(b_namespaceObject, { + "b": () => b +}); + +// NAMESPACE OBJECT: ./index.js +var index_namespaceObject = {}; +__webpack_require__.r(index_namespaceObject); +__webpack_require__.d(index_namespaceObject, { + "a": () => a_namespaceObject, + "b": () => b_namespaceObject, + "c": () => c +}); + +// CONCATENATED MODULE: ./a.css +// extracted by mini-css-extract-plugin +const a = "foo__a"; +// CONCATENATED MODULE: ./b.css +// extracted by mini-css-extract-plugin +const b = "foo__b"; +// CONCATENATED MODULE: ./c.css +// extracted by mini-css-extract-plugin +const c = "foo__c"; +// CONCATENATED MODULE: ./index.js +/* eslint-disable import/no-namespace */ + + + + + + + + +// eslint-disable-next-line no-console +console.log(index_namespaceObject); + + +/***/ }) +/******/ ]); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ if(__webpack_module_cache__[moduleId]) { +/******/ return __webpack_module_cache__[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +/******/ // startup +/******/ // Load entry module +/******/ __webpack_require__(0); +/******/ // This entry module used 'exports' so it can't be inlined +/******/ })() +; \ No newline at end of file diff --git a/test/cases/es-module-concatenation-modules/index.js b/test/cases/es-module-concatenation-modules/index.js new file mode 100644 index 00000000..c0f0fe59 --- /dev/null +++ b/test/cases/es-module-concatenation-modules/index.js @@ -0,0 +1,11 @@ +/* eslint-disable import/no-namespace */ +import * as a from './a.css'; +import * as b from './b.css'; + +import * as all from './index'; + +export * from './c.css'; +export { a, b }; + +// eslint-disable-next-line no-console +console.log(all); diff --git a/test/cases/es-module-concatenation-modules/webpack.config.js b/test/cases/es-module-concatenation-modules/webpack.config.js new file mode 100644 index 00000000..1ad92dfd --- /dev/null +++ b/test/cases/es-module-concatenation-modules/webpack.config.js @@ -0,0 +1,41 @@ +import Self from '../../../src'; + +module.exports = { + entry: './index.js', + optimization: { + concatenateModules: true, + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + options: { + esModule: true, + modules: { + namedExport: true, + }, + }, + }, + { + loader: 'css-loader', + options: { + esModule: true, + modules: { + namedExport: true, + localIdentName: 'foo__[local]', + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: '[name].css', + }), + ], +}; diff --git a/test/cases/es-module-concatenation/expected/webpack-5/main.js b/test/cases/es-module-concatenation/expected/webpack-5/main.js index 370eb6c2..5de674bf 100644 --- a/test/cases/es-module-concatenation/expected/webpack-5/main.js +++ b/test/cases/es-module-concatenation/expected/webpack-5/main.js @@ -4,20 +4,8 @@ /* 0 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -// ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); -// CONCATENATED MODULE: ./a.css -// extracted by mini-css-extract-plugin - -// CONCATENATED MODULE: ./b.css -// extracted by mini-css-extract-plugin - -// CONCATENATED MODULE: ./c.css -// extracted by mini-css-extract-plugin - -// CONCATENATED MODULE: ./index.js - diff --git a/test/cases/hmr/expected/webpack-5/main.js b/test/cases/hmr/expected/webpack-5/main.js index 48dad557..109901cf 100644 --- a/test/cases/hmr/expected/webpack-5/main.js +++ b/test/cases/hmr/expected/webpack-5/main.js @@ -71,7 +71,7 @@ /******/ /******/ /* webpack/runtime/getFullHash */ /******/ (() => { -/******/ __webpack_require__.h = () => "56250388fc166692d434" +/******/ __webpack_require__.h = () => "94636610c5b7c4b91196" /******/ })(); /******/ /******/ /* webpack/runtime/global */ diff --git a/test/cases/split-chunks-all/expected/webpack-5/2.js b/test/cases/split-chunks-all/expected/webpack-5/2.js new file mode 100644 index 00000000..c8d4dd4f --- /dev/null +++ b/test/cases/split-chunks-all/expected/webpack-5/2.js @@ -0,0 +1 @@ +MISSING diff --git a/test/enforce-esm.test.js b/test/enforce-esm.test.js index 3587ffea..385c011b 100644 --- a/test/enforce-esm.test.js +++ b/test/enforce-esm.test.js @@ -40,7 +40,7 @@ it('should keep empty module without options.esModule', async (done) => { const { modules } = stats.toJson({ all: false, modules: true }); expect( modules.filter((m) => m.moduleType !== 'runtime' && !m.orphan).length - ).toBe(isWebpack4 ? 2 : 3); + ).toBe(2); expect(source('./simple.css', stats)).toMatchInlineSnapshot( `"// extracted by mini-css-extract-plugin"` ); From bc0ca2cc8e2c96c0cd492643e17b49633f6d9388 Mon Sep 17 00:00:00 2001 From: Alexander Krasnoyarov Date: Wed, 7 Oct 2020 15:16:12 +0300 Subject: [PATCH 3/4] test: improve (#601) --- package-lock.json | 6 +++--- test/TestCache.test.js | 45 +++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b8df913..831f58eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16521,9 +16521,9 @@ }, "dependencies": { "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, "eslint-scope": { diff --git a/test/TestCache.test.js b/test/TestCache.test.js index 88efc0cc..76956b64 100644 --- a/test/TestCache.test.js +++ b/test/TestCache.test.js @@ -7,13 +7,6 @@ import path from 'path'; import webpack from 'webpack'; import del from 'del'; -const fileSystemCacheDirectory = path.resolve( - __dirname, - './outputs/cache/type-filesystem' -); - -del.sync(fileSystemCacheDirectory); - describe('TestCache', () => { afterEach(() => { jest.clearAllMocks(); @@ -43,12 +36,18 @@ describe('TestCache', () => { directoryForCase, 'webpack.config.js' )); + const outputPath = path.resolve(__dirname, 'js/cache-false'); + + await del([outputPath]); const compiler1 = webpack({ ...webpackConfig, mode: 'development', context: directoryForCase, cache: false, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -59,6 +58,7 @@ describe('TestCache', () => { return; } + expect(stats.compilation.emittedAssets.size).toBe(2); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); @@ -73,6 +73,9 @@ describe('TestCache', () => { mode: 'development', context: directoryForCase, cache: false, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -83,6 +86,8 @@ describe('TestCache', () => { return; } + // Because webpack compare the source content before emitting + expect(stats.compilation.emittedAssets.size).toBe(0); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); @@ -120,6 +125,9 @@ describe('TestCache', () => { directoryForCase, 'webpack.config.js' )); + const outputPath = path.resolve(__dirname, 'js/cache-memory'); + + await del([outputPath]); const compiler1 = webpack({ ...webpackConfig, @@ -128,6 +136,9 @@ describe('TestCache', () => { cache: { type: 'memory', }, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -138,6 +149,7 @@ describe('TestCache', () => { return; } + expect(stats.compilation.emittedAssets.size).toBe(2); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); @@ -154,6 +166,9 @@ describe('TestCache', () => { cache: { type: 'memory', }, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -164,6 +179,7 @@ describe('TestCache', () => { return; } + expect(stats.compilation.emittedAssets.size).toBe(0); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); @@ -201,6 +217,13 @@ describe('TestCache', () => { directoryForCase, 'webpack.config.js' )); + const outputPath = path.resolve(__dirname, 'js/cache-filesystem'); + const fileSystemCacheDirectory = path.resolve( + __dirname, + './js/.cache/type-filesystem' + ); + + await del([outputPath, fileSystemCacheDirectory]); const compiler1 = webpack({ ...webpackConfig, @@ -212,6 +235,9 @@ describe('TestCache', () => { idleTimeout: 0, idleTimeoutForInitialStore: 0, }, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -222,6 +248,7 @@ describe('TestCache', () => { return; } + expect(stats.compilation.emittedAssets.size).toBe(2); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); @@ -241,6 +268,9 @@ describe('TestCache', () => { idleTimeout: 0, idleTimeoutForInitialStore: 0, }, + output: { + path: outputPath, + }, }); await new Promise((resolve, reject) => { @@ -251,6 +281,7 @@ describe('TestCache', () => { return; } + expect(stats.compilation.emittedAssets.size).toBe(0); expect(stats.compilation.warnings).toHaveLength(0); expect(stats.compilation.errors).toHaveLength(0); From b935f26ff9773644dc5c2da009fc7e88b6af12c2 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 7 Oct 2020 15:22:18 +0300 Subject: [PATCH 4/4] chore(release): 0.12.0 --- CHANGELOG.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4236499a..2f2a9abd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.12.0](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v0.11.3...v0.12.0) (2020-10-07) + + +### Features + +* opt-in to transitive only side effects (webpack@5), no more empty JS chunks + ### [0.11.3](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v0.11.2...v0.11.3) (2020-10-02) diff --git a/package-lock.json b/package-lock.json index 831f58eb..7721412b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mini-css-extract-plugin", - "version": "0.11.3", + "version": "0.12.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cf442091..4d300642 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mini-css-extract-plugin", - "version": "0.11.3", + "version": "0.12.0", "description": "extracts CSS into separate files", "license": "MIT", "repository": "webpack-contrib/mini-css-extract-plugin",