diff --git a/package.json b/package.json index ad8a527e49..54e81cc469 100644 --- a/package.json +++ b/package.json @@ -149,9 +149,11 @@ "jsonfile": "^4.0.0", "lerna": "^3.14.1", "lint-staged": "^8.2.1", + "mini-css-extract-plugin": "^1.3.5", "mkdirp": "^0.5.1", "node-sass": "^4.12.0", "npm-run-all": "^4.1.5", + "null-loader": "^4.0.1", "phantomjs-prebuilt": "^2.1.10", "postcss-flexbugs-fixes": "^4.1.0", "postcss-loader": "^3.0.0", @@ -166,7 +168,7 @@ "url-parse": "^1.4.4", "vue-eslint-parser": "^2.0.3", "vue-jest": "^3.0.5", - "vue-loader": "^15.4.2", + "vue-loader": "^15.9.4", "vue-ssr-webpack-plugin": "^3.0.0", "vue-template-compiler": "^2.6.11", "webpack": "^4.25.1", diff --git a/src/themes/icmaa-imp/webpack.config.js b/src/themes/icmaa-imp/webpack.config.js index 4032ffb626..c3148d1f1b 100644 --- a/src/themes/icmaa-imp/webpack.config.js +++ b/src/themes/icmaa-imp/webpack.config.js @@ -5,6 +5,7 @@ const path = require('path') const i18nHelpers = require('@vue-storefront/i18n/helpers') +const MiniCssExtractPlugin = require('mini-css-extract-plugin') const SpritesmithPlugin = require('webpack-spritesmith') /** @@ -69,13 +70,29 @@ module.exports = function (config, { isClient, isDev }) { }) ] } - }; + } + + const extractCSS = !isDev && vsfConfig.has('icmaa_config.extractCSS') && vsfConfig.get('icmaa_config.extractCSS') === true const rewriteMapping = (rule) => { if (/(css|scss|sass)/.exec(rule.test)) { - rule.use = rule.use.map( - plugin => (plugin.loader && plugin.loader === 'postcss-loader') ? postcssConfig : plugin - ) + rule.use = rule.use + /** + * Replace original `postcss-loader` + */ + .map(plugin => (plugin.loader && plugin.loader === 'postcss-loader') ? postcssConfig : plugin) + /** + * Add `mini-css-extract-plugin.loader` to extract CSS into seperate files in production. + * This loader isn't SSR compatible, so we need to use the `null-loader` to load the CSS files into manifest but don't resolve them. + * This loader replaces the `vue-style-loader` in production-mode. + * @see https://github.com/webpack-contrib/mini-css-extract-plugin/issues/90 + */ + .map(plugin => { + if (extractCSS && plugin === 'vue-style-loader') { + return isClient ? { loader: MiniCssExtractPlugin.loader } : 'null-loader' + } + return plugin + }) } return rule @@ -83,6 +100,16 @@ module.exports = function (config, { isClient, isDev }) { config.module.rules.map(rewriteMapping) + /** + * Add `mini-css-extract-plugin` to extract CSS into files in production + */ + if (extractCSS) { + config.plugins.push(new MiniCssExtractPlugin({ + filename: isDev ? '[name].css' : '[name].[contenthash].css', + chunkFilename: isDev ? '[name]-[id].css' : '[name]-[id].[contenthash].css' + })) + } + /** * Remove `data-test-id` attributes from DOM for production mode * @see https://forum.vuejs.org/t/how-to-remove-attributes-from-tags-inside-vue-components/24138/9 diff --git a/yarn.lock b/yarn.lock index ba5c1a66dc..6a981242fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3481,6 +3481,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/json-schema@^7.0.6": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + "@types/lodash@4.14.149": version "4.14.149" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440" @@ -4290,6 +4295,11 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" @@ -4310,6 +4320,16 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + algoliasearch@^3.24.5: version "3.35.1" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.35.1.tgz#297d15f534a3507cab2f5dfb996019cac7568f0c" @@ -12331,6 +12351,15 @@ loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2 emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + localforage@^1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.7.3.tgz#0082b3ca9734679e1bd534995bdd3b24cf10f204" @@ -13076,6 +13105,15 @@ mini-css-extract-plugin@0.6.0: schema-utils "^1.0.0" webpack-sources "^1.1.0" +mini-css-extract-plugin@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.5.tgz#252166e78879c106e0130f229d44e0cbdfcebed3" + integrity sha512-tvmzcwqJJXau4OQE5vT72pRT18o2zF+tQJp8CWchqvfQnTlflkzS+dANYcRdyPRWUWRkfmeNTKltx0NZI/b5dQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + webpack-sources "^1.1.0" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -13786,6 +13824,14 @@ nth-check@^1.0.2, nth-check@~1.0.1: dependencies: boolbase "~1.0.0" +null-loader@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-4.0.1.tgz#8e63bd3a2dd3c64236a4679428632edd0a6dbc6a" + integrity sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -16436,6 +16482,15 @@ schema-utils@^2.6.5: ajv "^6.12.0" ajv-keywords "^3.4.1" +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== + dependencies: + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -18713,7 +18768,7 @@ vue-lazy-hydration@^1.0.0-beta.9: resolved "https://registry.yarnpkg.com/vue-lazy-hydration/-/vue-lazy-hydration-1.0.0-beta.12.tgz#d578dc86059eb0a147e6e553585dd22c41dfbae2" integrity sha512-0innXtjaqNodh0aw1/3dgGdEfL76eqDzo3CETSKolyjm3Z++hqBS7GQkrAAfp4JYBE12mb5yP2YnJxK6tJSGIA== -vue-loader@^15.4.2, vue-loader@^15.5.1, vue-loader@^15.7.1: +vue-loader@^15.5.1, vue-loader@^15.7.1: version "15.9.0" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.0.tgz#5d4b0378a4606188fc83e587ed23c94bc3a10998" integrity sha512-FeDHvTSpwyLeF7LIV1PYkvqUQgTJ8UmOxhSlCyRSxaXCKk+M6NF4tDQsLsPPNeDPyR7TfRQ8MLg6v+8PsDV9xQ== @@ -18724,6 +18779,17 @@ vue-loader@^15.4.2, vue-loader@^15.5.1, vue-loader@^15.7.1: vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" +vue-loader@^15.9.4: + version "15.9.6" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b" + integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg== + dependencies: + "@vue/component-compiler-utils" "^3.1.0" + hash-sum "^1.0.2" + loader-utils "^1.1.0" + vue-hot-reload-api "^2.3.0" + vue-style-loader "^4.1.0" + vue-meta@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/vue-meta/-/vue-meta-2.3.3.tgz#2a097f62817204b0da78be4d62aee0cb566eaee0"