Skip to content

Commit

Permalink
feat: add plugin to bundle CSS files
Browse files Browse the repository at this point in the history
  • Loading branch information
ivomurrell committed Jan 23, 2025
1 parent 2f6aac2 commit 2a7dd2f
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
49 changes: 49 additions & 0 deletions packages/dotcom-build-css/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# @financial-times/dotcom-build-css

This package exports a Webpack plugin to configure it with a way to load CSS source files.

## Getting started

This package is compatible with Node 18+ and is distributed on npm.

```sh
npm install --save-dev @financial-times/dotcom-build-css
```

After installing the package you must add it to the list of plugins in your project's `webpack.config.js` configuration file:

```diff
+ const { PageKitCssPlugin } = require('@financial-times/dotcom-build-css')

module.exports = {
plugins: [
+ new PageKitCssPlugin()
]
}
```

Once setup, this plugin will enable you to use CSS files (`.css`) as entry points into your source code.

```js
const { PageKitCssPlugin } = require('@financial-times/dotcom-build-css')

module.exports = {
entry: {
styles: path/to/styles.css
},
plugins: [new PageKitCssPlugin()]
}
```

## Scope

This plugin adds a [rule] to the Webpack configuration to handle `.css` files. It calls the [css-loader] package to load and parse the source files. The CSS is optimised using [css-minimizer-webpack-plugin], which runs [cssnano] under the hood. The [mini-css-extract-plugin] is added to generate `.css` files and the [webpack-fix-style-only-entries] to clean up any empty JavaScript bundles.

The CSS loader has `url()` resolution disabled as we don't use, nor recommend, the function currently.

[rule]: https://webpack.js.org/configuration/module/#rule
[css-loader]: https://github.com/webpack-contrib/css-loader
[css-minimizer-webpack-plugin]: https://github.com/webpack-contrib/css-minimizer-webpack-plugin
[mini-css-extract-plugin]: https://github.com/webpack-contrib/mini-css-extract-plugin
[webpack-fix-style-only-entries]: https://github.com/fqborges/webpack-fix-style-only-entries
[cssnano]: https://cssnano.co/
44 changes: 44 additions & 0 deletions packages/dotcom-build-css/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@financial-times/dotcom-build-css",
"version": "0.0.0",
"description": "",
"main": "dist/node/index.js",
"types": "dist/node/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"clean": "npm run clean:dist && npm run clean:node_modules",
"clean:dist": "rm -rf dist",
"clean:node_modules": "rm -rf node_modules",
"build:node": "tsc",
"build": "npm run build:node",
"dev": "npm run build:node -- --watch"
},
"keywords": [],
"author": "",
"license": "MIT",
"peerDependencies": {
"webpack": "5.x"
},
"dependencies": {
"css-loader": "^6.8.1",
"css-minimizer-webpack-plugin": "^7.0.0",
"mini-css-extract-plugin": "^2.9.1",
"webpack-remove-empty-scripts": "^1.0.4"
},
"engines": {
"node": "18.x || 20.x || 22.x"
},
"files": [
"dist/",
"src/"
],
"repository": {
"type": "git",
"repository": "https://github.com/Financial-Times/dotcom-page-kit.git",
"directory": "packages/dotcom-build-css"
},
"homepage": "https://github.com/Financial-Times/dotcom-page-kit/tree/HEAD/packages/dotcom-build-css",
"volta": {
"extends": "../../package.json"
}
}
46 changes: 46 additions & 0 deletions packages/dotcom-build-css/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import CSSMinimizerPlugin from 'css-minimizer-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import RemoveEmptyScriptsPlugin from 'webpack-remove-empty-scripts'
import type webpack from 'webpack'

export class PageKitCssPlugin {
apply(compiler: webpack.Compiler) {
const cssLoaderOptions = {
// Disable Webpack from resolving url() because we do not
// currently use this functionality.
url: false
}

const miniCssExtractPluginOptions = {
// only include content hash in filename when compiling production assets
filename: compiler.options.mode === 'development' ? '[name].css' : '[name].[contenthash:12].css',
// we load CSS files ourselves in `dotcom-ui-shell` so don't need the runtime
runtime: false
}

compiler.options.module.rules.push({
test: [/\.css$/],
use: [
// Extracts CSS into separate, non-JS files
// https://github.com/webpack-contrib/mini-css-extract-plugin
{
loader: MiniCssExtractPlugin.loader
},
// Add support for handling .css files
// https://github.com/webpack-contrib/css-loader
{
loader: require.resolve('css-loader'),
options: cssLoaderOptions
}
]
})

compiler.options.optimization.minimizer = ['...', new CSSMinimizerPlugin()]

// 2024 and this is still an issue :/ mini-css-extract-plugin leaves
// behind empty .js bundles after extracting the CSS.
// https://github.com/webpack/webpack/issues/11671
new RemoveEmptyScriptsPlugin().apply(compiler)
new MiniCssExtractPlugin(miniCssExtractPluginOptions).apply(compiler)
}
}
10 changes: 10 additions & 0 deletions packages/dotcom-build-css/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"rootDir": "src",
"outDir": "dist/node",

"strict": true,
}
}
3 changes: 3 additions & 0 deletions tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
{
"path": "packages/dotcom-build-code-splitting"
},
{
"path": "packages/dotcom-build-css"
},
{
"path": "packages/dotcom-build-images"
},
Expand Down

0 comments on commit 2a7dd2f

Please sign in to comment.