From 451e9c996dcb13953c388021510abab839637759 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Sun, 29 Apr 2018 15:01:14 -0400 Subject: [PATCH 1/4] Fix CS --- webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 7433baf..599521e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -53,7 +53,7 @@ module.exports = { new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[name].css" - }) + }), ], optimization: { From 2604eb0a4e37a0b5ef54bb0d4804c7fcdbf0192e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Sun, 29 Apr 2018 15:02:38 -0400 Subject: [PATCH 2/4] Work on plugins to remove unnecessary JS chunks --- .vscode/launch.json | 16 ++++++++ build/Array.js | 19 +++++++++ build/RemoveStyleScriptChunksPlugin.js | 53 ++++++++++++++++++++++++++ build/index.js | 1 + package.json | 3 +- webpack.config.js | 7 +++- 6 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 build/Array.js create mode 100644 build/RemoveStyleScriptChunksPlugin.js create mode 100644 build/index.js diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..89b4d64 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch via NPM", + "runtimeExecutable": "npm", + "runtimeArgs": ["run-script", "debug"], + "port": 9229 + } + ] +} diff --git a/build/Array.js b/build/Array.js new file mode 100644 index 0000000..925c244 --- /dev/null +++ b/build/Array.js @@ -0,0 +1,19 @@ +Array.prototype.rejectInPlace = function(callback) { + return this.filterInPlace((...args) => { + return !callback(...args); + }); +}; + +Array.prototype.filterInPlace = function(callback) { + let i = 0, + j = 0; + + while (i < this.length) { + const val = this[i]; + if (callback(val, i, this)) this[j++] = val; + i++; + } + + this.length = j; + return this; +}; diff --git a/build/RemoveStyleScriptChunksPlugin.js b/build/RemoveStyleScriptChunksPlugin.js new file mode 100644 index 0000000..f0a67ee --- /dev/null +++ b/build/RemoveStyleScriptChunksPlugin.js @@ -0,0 +1,53 @@ +require("./Array"); + +const pluginName = "RemoveStyleScriptChunksPlugin"; + +module.exports = class RemoveStyleScriptChunksPlugin { + hasCSSChunks(results) { + return results.some(r => { + return r.identifier.includes("mini-css-extract-plugin"); + }); + } + + isJavascriptChunk(result) { + return result.pathOptions.contentHashType === "javascript"; + } + + removeExtraChunksInPlace(results) { + if (!this.hasCSSChunks(results)) { + return; + } + + results.rejectInPlace(this.isJavascriptChunk); + } + + listenForAssets(template) { + template.hooks.renderManifest.tap( + pluginName, + this.removeExtraChunksInPlace.bind(this) + ); + } + + listenForEntires(template) { + template.hooks.startup.tap(pluginName, (source, chunk, hash) => { + if (chunk.hasEntryModule()) { + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.chunks.length > 1) { + console.log(chunkGroup, chunk); + } + } + } + }); + } + + apply(compiler) { + compiler.hooks.thisCompilation.tap(pluginName, compilation => { + // We can't register the tap until beforeChunkAssets + // If we register it before then it won't be last + compilation.hooks.beforeChunkAssets.tap(pluginName, () => { + [compilation.mainTemplate].forEach(this.listenForEntires.bind(this)); + [compilation.chunkTemplate].forEach(this.listenForAssets.bind(this)); + }); + }); + } +}; diff --git a/build/index.js b/build/index.js new file mode 100644 index 0000000..7fff67a --- /dev/null +++ b/build/index.js @@ -0,0 +1 @@ +module.exports.RemoveStyleScriptChunksPlugin = require("./RemoveStyleScriptChunksPlugin"); diff --git a/package.json b/package.json index c4eb4b0..358bece 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "main": "index.js", "license": "MIT", "scripts": { - "test": "node ./node_modules/.bin/webpack --progress --display verbose" + "test": "node ./node_modules/.bin/webpack --progress --display verbose", + "debug": "node --inspect-brk ./node_modules/.bin/webpack --progress --display verbose" }, "dependencies": { "css-loader": "^0.28.11", diff --git a/webpack.config.js b/webpack.config.js index 599521e..fa8c8c2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ const path = require("path"); const webpack = require("webpack"); const { VueLoaderPlugin } = require("vue-loader"); +const { RemoveStyleScriptChunksPlugin } = require("./build"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { @@ -54,6 +55,8 @@ module.exports = { filename: "[name].css", chunkFilename: "[name].css" }), + + new RemoveStyleScriptChunksPlugin() ], optimization: { @@ -69,7 +72,7 @@ module.exports = { // enforce: false // results in no vue-styles chunk // Only a bundle.css file - enforce: false + enforce: true }, extractOtherStyles: { @@ -82,7 +85,7 @@ module.exports = { // Only a bundle.css file name: "other-styles", chunks: "all", - enforce: false + enforce: true } } } From fcbf4389cc0011550eae3296860c4dc2b1cab1d0 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Sun, 29 Apr 2018 15:03:29 -0400 Subject: [PATCH 3/4] Add plugin to trim CSS files --- build/TrimCSSPlugin.js | 26 +++++++++++++++++ build/TrimmedSource.js | 66 ++++++++++++++++++++++++++++++++++++++++++ build/index.js | 1 + webpack.config.js | 3 +- 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 build/TrimCSSPlugin.js create mode 100644 build/TrimmedSource.js diff --git a/build/TrimCSSPlugin.js b/build/TrimCSSPlugin.js new file mode 100644 index 0000000..8868dc0 --- /dev/null +++ b/build/TrimCSSPlugin.js @@ -0,0 +1,26 @@ +const pluginName = "TrimCSSPlugin"; +const TrimmedSource = require("./TrimmedSource"); + +module.exports = class TrimCSSPlugin { + isCSSChunk(chunk) { + return chunk.ids.includes("mini-css-extract-plugin"); + } + + apply(compiler) { + compiler.hooks.compilation.tap(pluginName, compilation => { + compilation.hooks.optimizeChunkAssets.tap(pluginName, chunks => { + for (const chunk of chunks) { + // if (!this.isCSSChunk(chunk)) { + // continue; + // } + + for (const file of chunk.files) { + compilation.assets[file] = new TrimmedSource( + compilation.assets[file] + ); + } + } + }); + }); + } +}; diff --git a/build/TrimmedSource.js b/build/TrimmedSource.js new file mode 100644 index 0000000..783ab26 --- /dev/null +++ b/build/TrimmedSource.js @@ -0,0 +1,66 @@ +const Source = require("webpack-sources/lib/Source"); + +class TrimmedSource extends Source { + constructor(source) { + super(); + + this._source = source; + } + + source() { + const src = + typeof this._source === "string" ? this._source : this._source.source(); + + if (src.indexOf(".red[data-v-") !== -1) { + // debugger; + } + + return trimStr(src); + } + + node(options) { + return new SourceNode(null, null, null, [ + cloneAndTrim(this._source.node(options)) + ]); + } + + listMap(options) { + return this._source.listMap(options).mapGeneratedCode(trimStr); + } + + updateHash(hash) { + if (typeof this._source === "string") { + hash.update(this._source); + } else { + this._source.updateHash(hash); + } + } +} + +const whitespacePattern = /(^\s+|\s+$)/g; + +function trimStr(str) { + return str.replace(whitespacePattern, ""); +} + +function cloneAndTrim(node) { + if (typeof node === "string") { + return trimStr(node); + } + + const newNode = new SourceNode( + node.line, + node.column, + node.source, + node.children.map(cloneAndTrim), + node.name + ); + + newNode.sourceContents = node.sourceContents; + + return newNode; +} + +require("webpack-sources/lib/SourceAndMapMixin")(TrimmedSource.prototype); + +module.exports = TrimmedSource; diff --git a/build/index.js b/build/index.js index 7fff67a..b3bbae8 100644 --- a/build/index.js +++ b/build/index.js @@ -1 +1,2 @@ +module.exports.TrimCSSPlugin = require("./TrimCSSPlugin"); module.exports.RemoveStyleScriptChunksPlugin = require("./RemoveStyleScriptChunksPlugin"); diff --git a/webpack.config.js b/webpack.config.js index fa8c8c2..5e7c8c2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,7 @@ const path = require("path"); const webpack = require("webpack"); const { VueLoaderPlugin } = require("vue-loader"); -const { RemoveStyleScriptChunksPlugin } = require("./build"); +const { TrimCSSPlugin, RemoveStyleScriptChunksPlugin } = require("./build"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { @@ -57,6 +57,7 @@ module.exports = { }), new RemoveStyleScriptChunksPlugin() + // new TrimCSSPlugin(), ], optimization: { From d7330e1599472049accaf28b14696706dd035312 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Sun, 29 Apr 2018 15:04:07 -0400 Subject: [PATCH 4/4] Recompile --- dist/bundle.js | 102 ++++++++++++++++++++++++++++++------------ dist/other-styles.css | 3 ++ dist/vue-styles.css | 7 +++ 3 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 dist/other-styles.css create mode 100644 dist/vue-styles.css diff --git a/dist/bundle.js b/dist/bundle.js index 7382ffe..510a720 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -1,7 +1,69 @@ /******/ (function(modules) { // webpackBootstrap +/******/ // install a JSONP callback for chunk loading +/******/ function webpackJsonpCallback(data) { +/******/ var chunkIds = data[0]; +/******/ var moreModules = data[1]; +/******/ var executeModules = data[2]; +/******/ // add "moreModules" to the modules object, +/******/ // then flag all "chunkIds" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0, resolves = []; +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(installedChunks[chunkId]) { +/******/ resolves.push(installedChunks[chunkId][0]); +/******/ } +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ for(moduleId in moreModules) { +/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { +/******/ modules[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(parentJsonpFunction) parentJsonpFunction(data); +/******/ while(resolves.length) { +/******/ resolves.shift()(); +/******/ } +/******/ +/******/ // add entry modules from loaded chunk to deferred list +/******/ deferredModules.push.apply(deferredModules, executeModules || []); +/******/ +/******/ // run deferred modules when all chunks ready +/******/ return checkDeferredModules(); +/******/ }; +/******/ function checkDeferredModules() { +/******/ var result; +/******/ for(var i = 0; i < deferredModules.length; i++) { +/******/ var deferredModule = deferredModules[i]; +/******/ var fulfilled = true; +/******/ for(var j = 1; j < deferredModule.length; j++) { +/******/ var depId = deferredModule[j]; +/******/ if(installedChunks[depId] !== 0) fulfilled = false; +/******/ } +/******/ if(fulfilled) { +/******/ deferredModules.splice(i--, 1); +/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]); +/******/ } +/******/ } +/******/ return result; +/******/ } +/******/ /******/ // The module cache /******/ var installedModules = {}; /******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // Promise = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ "bundle": 0 +/******/ }; +/******/ +/******/ // script path function +/******/ function jsonpScriptSrc(chunkId) { +/******/ return __webpack_require__.p + "" + chunkId + ".js" +/******/ } +/******/ +/******/ var deferredModules = []; +/******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ @@ -64,24 +126,22 @@ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ +/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; +/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); +/******/ jsonpArray.push = webpackJsonpCallback; +/******/ jsonpArray = jsonpArray.slice(); +/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); +/******/ var parentJsonpFunction = oldJsonpFunction; +/******/ /******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); +/******/ // add entry module to deferred list +/******/ deferredModules.push(["./src/index.js","vue-styles","other-styles"]); +/******/ // run deferred modules when ready +/******/ return checkDeferredModules(); /******/ }) /************************************************************************/ /******/ ({ -/***/ "./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/index.js!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/lib/loader.js!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true": -/*!*******************************************************************************************************************************************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/lib/loader.js!./node_modules/vue-loader/lib??vue-loader-options!./src/test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true ***! - \*******************************************************************************************************************************************************************************************************************************************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// extracted by mini-css-extract-plugin - -/***/ }), - /***/ "./node_modules/process/browser.js": /*!*****************************************!*\ !*** ./node_modules/process/browser.js ***! @@ -8820,22 +8880,6 @@ component.options.__file = "src/test.vue" /***/ }), -/***/ "./src/test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true": -/*!*******************************************************************************!*\ - !*** ./src/test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true ***! - \*******************************************************************************/ -/*! no static exports found */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../node_modules/mini-css-extract-plugin/dist/loader.js!../node_modules/css-loader!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/sass-loader/lib/loader.js!../node_modules/vue-loader/lib??vue-loader-options!./test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true */ "./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/index.js!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/lib/loader.js!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/test.vue?vue&type=style&index=0&id=0f72a62a&lang=scss&scoped=true"); -/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0__); -/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== 'default') (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__)); - /* harmony default export */ __webpack_exports__["default"] = (_node_modules_mini_css_extract_plugin_dist_loader_js_node_modules_css_loader_index_js_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_sass_loader_lib_loader_js_node_modules_vue_loader_lib_index_js_vue_loader_options_test_vue_vue_type_style_index_0_id_0f72a62a_lang_scss_scoped_true__WEBPACK_IMPORTED_MODULE_0___default.a); - -/***/ }), - /***/ "./src/test.vue?vue&type=template&id=0f72a62a&scoped=true": /*!****************************************************************!*\ !*** ./src/test.vue?vue&type=template&id=0f72a62a&scoped=true ***! diff --git a/dist/other-styles.css b/dist/other-styles.css new file mode 100644 index 0000000..d29f4a7 --- /dev/null +++ b/dist/other-styles.css @@ -0,0 +1,3 @@ +body { + background: blue; } + diff --git a/dist/vue-styles.css b/dist/vue-styles.css new file mode 100644 index 0000000..e5e6baa --- /dev/null +++ b/dist/vue-styles.css @@ -0,0 +1,7 @@ + +.red[data-v-0f72a62a] { + background: red; + width: 300px; + height: 300px; +} +