Optimize CSS processing
There are still many areas that can be optimized for CSS processing. The following will introduce extracting CSS into separate files, CSS compatibility processing, CSS compression, etc.
Extract CSS into separate files
CSS files are currently packaged into js files. When js files are loaded, a style tag will be created to generate styles.
This will cause screen flashing for websites, which is not a good user experience.
We should have separate CSS files and load them through link tags for better performance.
Install dependencies
- npm
- Yarn
- pnpm
npm i mini-css-extract-plugin -D
yarn add mini-css-extract-plugin --dev
pnpm add mini-css-extract-plugin -D
Configuration
const path = require('path');
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'), // Output required for production mode
filename: 'static/js/main.js', // Output js files to the static/js directory
clean: true,
},
module: {
rules: [
{
// Used to match files ending with .css
test: /\.css$/,
// The order of loader execution in the use array is from right to left
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
{
test: /\.styl$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader'],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // Images smaller than 10kb will be processed with base64
},
},
generator: {
// Output the image file to the static/imgs directory
// Name the image file [hash:8][ext][query]
// [hash:8]: The hash value is 8 bits
// [ext]: Use the previous file extension
// [query]: Add the previous query parameter
filename: 'static/imgs/[hash:8][ext][query]',
},
},
{
test: /\.(ttf|woff2?)$/,
type: 'asset/resource',
generator: {
filename: 'static/media/[hash:8][ext][query]',
},
},
{
test: /\.js$/,
exclude: /node_modules/, // exclude node_modules code from compilation
loader: 'babel-loader',
},
],
},
plugins: [
new ESLintWebpackPlugin({
// Specify the root directory of the check file
context: path.resolve(__dirname, '../src'),
}),
new HtmlWebpackPlugin({
// Create a file with public/index.html as the template
// The new html file has two characteristics: 1. The content is consistent with the source file 2. Automatically introduce the generated js and other resources
template: path.resolve(__dirname, '../public/index.html'),
}),
// Extract CSS into a separate file
new MiniCssExtractPlugin({
// Define output file name and directory
filename: 'static/css/main.css',
}),
],
// devServer: {
// host: "localhost", // Start server domain name
// port: "3000", // Start server port number
// open: true, // Whether to automatically open the browser
// },
mode: 'production',
};
Run command
- npm
- Yarn
- pnpm
npm run build
yarn build
pnpm run build
Effect
- Before configuration
- After configuration
CSS compatibility processing
Not only JS has style compatibility issues, but CSS also has compatibility issues. Here we use the current mainstream solution PostCSS
to solve it.
Install dependencies
- npm
- Yarn
- pnpm
npm i postcss-loader postcss postcss-preset-env -D
yarn add postcss-loader postcss postcss-preset-env --dev
pnpm add postcss-loader postcss postcss-preset-env -D
Configuration
const path = require('path');
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'), // Output required for production mode
filename: 'static/js/main.js', // Output js files to the static/js directory
clean: true,
},
module: {
rules: [
{
// Used to match files ending with .css
test: /\.css$/,
// The order of loader execution in the use array is from right to left
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // Can solve most style compatibility issues
],
},
},
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // can solve most style compatibility issues
],
},
},
},
'less-loader',
],
},
{
test: /\.s[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // Can solve most style compatibility issues
],
},
},
},
'sass-loader',
],
},
{
test: /\.styl$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // Can solve most style compatibility issues
],
},
},
},
'stylus-loader',
],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // Images smaller than 10kb will be processed with base64
},
},
generator: {
// Output the image file to the static/imgs directory
// Name the image file [hash:8][ext][query]
// [hash:8]: The hash value is 8 bits
// [ext]: Use the previous file extension
// [query]: Add the previous query parameter
filename: 'static/imgs/[hash:8][ext][query]',
},
},
{
test: /\.(ttf|woff2?)$/,
type: 'asset/resource',
generator: {
filename: 'static/media/[hash:8][ext][query]',
},
},
{
test: /\.js$/,
exclude: /node_modules/, // exclude node_modules code from compilation
loader: 'babel-loader',
},
],
},
plugins: [
new ESLintWebpackPlugin({
// Specify the root directory of the check file
context: path.resolve(__dirname, '../src'),
}),
new HtmlWebpackPlugin({
// Create a file with public/index.html as the template
// The new html file has two characteristics: 1. The content is consistent with the source file 2. Automatically introduce the packaged generated js and other resources
template: path.resolve(__dirname, '../public/index.html'),
}),
// Extract css into a separate file
new MiniCssExtractPlugin({
// Define the output file name and directory
filename: 'static/css/main.css',
}),
],
// devServer: {
// host: "localhost", // Start server domain name
// port: "3000", // Start server port number
// open: true, // Whether to automatically open the browser
// },
mode: 'production',
};
Control compatibility
We can add browserslist
to the package.json
file to control the degree of style compatibility.
{
// Others omitted
"browserslist": ["ie >= 8"]
}
To know more about browserslist
configuration, check out the browserslist document
The above is set to compatible browsers ie8 and above in order to test compatibility.
In actual development, we generally do not consider old versions of browsers, so we can set it like this:
{
// Other omissions
"browserslist": ["last 2 version", "> 1%", "not dead"]
}
Merge configuration
const path = require('path');
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// Get Loaders for processing styles
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // Can solve most style compatibility issues
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'), // Production mode requires output
filename: 'static/js/main.js', // Output js files to the static/js directory
clean: true,
},
module: {
rules: [
{
// Used to match files ending with .css
test: /\.css$/,
// The order of loader execution in the use array is from right to left
use: getStyleLoaders(),
},
{
test: /\.less$/,
// highligt-next-line
use: getStyleLoaders('less-loader'),
},
{
test: /\.s[ac]ss$/,
// highligt-next-line
use: getStyleLoaders('sass-loader'),
},
{
test: /\.styl$/,
// highligt-next-line
use: getStyleLoaders('stylus-loader'),
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // Images less than 10kb will be processed by base64
},
},
generator: {
// Output the image file to static/imgs directory
// Name the image file [hash:8][ext][query]
// [hash:8]: The hash value is 8 digits
// [ext]: Use the previous file extension
// [query]: Add the previous query parameter
filename: 'static/imgs/[hash:8][ext][query]',
},
},
{
test: /\.(ttf|woff2?)$/,
type: 'asset/resource',
generator: {
filename: 'static/media/[hash:8][ext][query]',
},
},
{
test: /\.js$/,
exclude: /node_modules/, // Exclude node_modules code from compilation
loader: 'babel-loader',
},
],
},
plugins: [
new ESLintWebpackPlugin({
// Specify the root directory of the check file
context: path.resolve(__dirname, '../src'),
}),
new HtmlWebpackPlugin({
// Create a file with public/index.html as the template
// The new html file has two features: 1. The content is consistent with the source file 2. Automatically import the packaged js and other resources
template: path.resolve(__dirname, '../public/index.html'),
}),
// Extract CSS into a separate file
new MiniCssExtractPlugin({
// Define output file name and directory
filename: 'static/css/main.css',
}),
],
// devServer: {
// host: "localhost", // Start server domain name
// port: "3000", // Start server port number
// open: true, // Whether to automatically open the browser
// },
mode: 'production',
};
Run command
- npm
- Yarn
- pnpm
npm run build
yarn build
pnpm run build
CSS compression
CSS compression can reduce file size and increase website loading speed.
Install dependencies
- npm
- Yarn
- pnpm
npm i css-minimizer-webpack-plugin -D
yarn add css-minimizer-webpack-plugin --dev
pnpm add css-minimizer-webpack-plugin -D
Configuration
const path = require('path');
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// Get Loaders for processing styles
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env', // Can solve most style compatibility issues
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'), // Production mode requires output
filename: 'static/js/main.js', // Output js files to the static/js directory
clean: true,
},
module: {
rules: [
{
// Used to match files ending with .css
test: /\.css$/,
// The order of Loader execution in the use array is from right to left
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders('less-loader'),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders('sass-loader'),
},
{
test: /\.styl$/,
use: getStyleLoaders('stylus-loader'),
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // Images less than 10kb will be processed by base64
},
},
generator: {
// Output the image file to the static/imgs directory
// Name the image file [hash:8][ext][query]
// [hash:8]: The hash value is 8 digits
// [ext]: Use the previous file extension
// [query]: Add the previous query parameter
filename: 'static/imgs/[hash:8][ext][query]',
},
},
{
test: /\.(ttf|woff2?)$/,
type: 'asset/resource',
generator: {
filename: 'static/media/[hash:8][ext][query]',
},
},
{
test: /\.js$/,
exclude: /node_modules/, // Exclude node_modules code from compilation
loader: 'babel-loader',
},
],
},
plugins: [
new ESLintWebpackPlugin({
// Specify the root directory of the check file
context: path.resolve(__dirname, '../src'),
}),
new HtmlWebpackPlugin({
// Create a file with public/index.html as the template
// The new html file has two characteristics: 1. The content is consistent with the source file 2. Automatically introduce the generated js and other resources
template: path.resolve(__dirname, '../public/index.html'),
}),
// Extract CSS into a separate file
new MiniCssExtractPlugin({
// Define the output file name and directory
filename: 'static/css/main.css',
}),
// CSS compression
new CssMinimizerPlugin(),
],
// devServer: {
// host: "localhost", // Start server domain name
// port: "3000", // Start server port number
// open: true, // Whether to automatically open the browser
// },
mode: 'production',
};
Run command
- npm
- Yarn
- pnpm
npm run build
yarn build
pnpm run build
Effect
-
Before configuration
-
After configuration