From d47113f798c813a3d3b6092a45204940ffc25d40 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Tue, 29 Nov 2022 14:11:11 +1300 Subject: [PATCH] ENH Update css webpack config --- configMeta/cssWebpackConfig.js | 27 ++++++++++++++++++++ css/modules.js | 46 ++++++++++++++++------------------ css/plugins.js | 8 ++++-- index.js | 1 + package.json | 8 ++---- 5 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 configMeta/cssWebpackConfig.js diff --git a/configMeta/cssWebpackConfig.js b/configMeta/cssWebpackConfig.js new file mode 100644 index 0000000..5b45a48 --- /dev/null +++ b/configMeta/cssWebpackConfig.js @@ -0,0 +1,27 @@ +const BaseWebpackConfig = require('./baseWebpackConfig'); +const moduleCSS = require('../css/modules'); +const pluginCSS = require('../css/plugins'); + +/** + * Dynamically generates webpack config for transpiling sass to css using Silverstripe default settings. + * + * IMPORTANT: Instead of setting the output name in the output key, add it as the filename in this constructor. + * Otherwise you will get errors because webpack wants to create a js file for each css file. The js files + * aren't emitted thanks to the IgnoreEmitPlugin, but this happens after chunk validation. + */ +module.exports = class CssWebpackConfig extends BaseWebpackConfig { + constructor(name, ENV, PATHS, filename = 'styles/[name].css') { + super(); + this.config = { + name, + output: { + path: PATHS.DIST, + }, + devtool: (ENV !== 'production') ? 'source-map' : '', + module: moduleCSS(ENV, PATHS), + plugins: [ + ...pluginCSS(filename, ENV, PATHS), + ], + }; + } +} diff --git a/css/modules.js b/css/modules.js index 6214f0a..d4fdcfb 100644 --- a/css/modules.js +++ b/css/modules.js @@ -1,27 +1,20 @@ -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const Path = require('path'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); /** * Exports the settings for css modules in webpack.config * * @param {string} ENV Environment to build for, expects 'production' for production and * anything else for non-production - * @param {string} FILES_PATH The relative path from dist-css file to dist-images/dist-fonts * @param {string} SRC The path to the source scss files * @param {string} ROOT The path to the root of the project, this is so we can scope for - * silverstripe-admin variables.scss + * importing silverstripe-admin sass from other modules * @returns {{rules: [*,*,*,*]}} */ -module.exports = (ENV, { FILES_PATH, SRC, ROOT }) => { +module.exports = (ENV, { SRC, ROOT }) => { const useSourceMap = ENV !== 'production'; const cssLoaders = [ - { - loader: 'style-loader', - options: { - sourceMap: useSourceMap, - }, - }, { loader: MiniCssExtractPlugin.loader, }, @@ -29,8 +22,6 @@ module.exports = (ENV, { FILES_PATH, SRC, ROOT }) => { loader: 'css-loader', options: { sourceMap: useSourceMap, - minimize: true, - discardComments: true, }, }, { @@ -39,13 +30,14 @@ module.exports = (ENV, { FILES_PATH, SRC, ROOT }) => { sourceMap: useSourceMap, postcssOptions: { plugins: [ - require('autoprefixer'), - require('postcss-custom-properties'), + 'autoprefixer', + 'postcss-custom-properties', ], }, }, }, - ].filter(loader => loader); + ]; + const scssLoaders = [ ...cssLoaders, { @@ -65,8 +57,7 @@ module.exports = (ENV, { FILES_PATH, SRC, ROOT }) => { Path.resolve(ROOT, '../../silverstripe/admin/client/src/styles'), ], }, - implementation: require('sass'), - sourceMap: useSourceMap, + sourceMap: true, // required for resolve-url-loader to be happy }, }, ]; @@ -84,17 +75,22 @@ module.exports = (ENV, { FILES_PATH, SRC, ROOT }) => { { test: /\.(png|gif|jpe?g|svg)$/, exclude: /fonts[\/\\]([\w_-]+)\.svg$/, - loader: 'url-loader', - options: { - limit: 10000, - name: 'images/[name].[ext]', + type: 'asset', + parser: { + dataUrlCondition: { + maxSize: 10 * 1024 // 10kb + } + }, + generator: { + filename: 'images/[name][ext]', }, }, { - test: /fonts[\/\\]([\w_-]+)\.(woff2?|eot|ttf|svg)$/, - loader: 'file-loader', - options: { - name: 'fonts/[name].[ext]?h=[contenthash]', + // Any .woff, woff2, eot, ttf, or otf file - or svgs specifically in a fonts folder. + test: /(\.(woff2?|eot|ttf|otf)|fonts[\/\\]([\w_-]+)\.svg)$/, + type: 'asset/resource', + generator: { + filename: 'fonts/[name][ext]?h=[contenthash]', }, }, ], diff --git a/css/plugins.js b/css/plugins.js index 1179ee8..cb003c8 100644 --- a/css/plugins.js +++ b/css/plugins.js @@ -1,10 +1,14 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin'); /** * Exports the settings for plugins in webpack.config + * @param {string} filename determines the name of each output CSS file. + * See https://webpack.js.org/plugins/mini-css-extract-plugin/#filename */ -module.exports = () => ([ +module.exports = (filename) => ([ new MiniCssExtractPlugin({ - filename: 'styles/[name].css', + filename, }), + new IgnoreEmitPlugin(/\.js$/), ]); diff --git a/index.js b/index.js index 4fe0356..e55d6cc 100644 --- a/index.js +++ b/index.js @@ -8,4 +8,5 @@ module.exports = { resolveJS: require('./js/resolve'), JavascriptWebpackConfig: require('./configMeta/javascriptWebpackConfig'), + CssWebpackConfig: require('./configMeta/cssWebpackConfig'), }; diff --git a/package.json b/package.json index c530224..24f2346 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,10 @@ "@sect/modernizr-loader": "^1.0.3", "autoprefixer": "^10.4.13", "babel-loader": "^9.0.1", + "core-js": "^3.26.0", "css-loader": "^6.7.1", - "core-js": "^3.26.0", "expose-loader": "^4.0.0", - "extract-loader": "^5.1.0", - "file-loader": "^6.2.0", + "ignore-emit-webpack-plugin": "^2.0.6", "imports-loader": "^4.0.1", "json-loader": "^0.5.7", "lodash": "^4.17.21", @@ -45,13 +44,10 @@ "postcss-custom-properties": "^12.1.10", "postcss-load-config": "^4.0.1", "postcss-loader": "^7.0.1", - "raw-loader": "^4.0.2", "resolve-url-loader": "^5.0.0", "sass": "^1.55.0", "sass-loader": "^13.1.0", - "style-loader": "3.3.1", "stylelint": "^14.14.0", - "url-loader": "^4.1.1", "webpack": "^5.74.0", "webpack-bundle-analyzer": "^4.7.0" },