在现代前端工程中,CSS 的提取和打包优化对于项目性能至关重要。本节将详细介绍如何在使用 Tailwind CSS 的项目中实现 CSS 的高效提取和打包优化。
CSS 提取策略
MiniCssExtractPlugin 配置
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: process.env.NODE_ENV === 'production'
? 'css/[name].[contenthash].css'
: 'css/[name].css'
})
]
}
分层提取
css">/* styles/base.css */
@tailwind base;
/* styles/components.css */
@tailwind components;
@layer components {
.btn { /* ... */
}
.card { /* ... */
}
}
/* styles/utilities.css */
@tailwind utilities;
@layer utilities {
.custom-scroll { /* ... */
}
}
// webpack.config.js
module.exports = {
entry: {
base: './src/styles/base.css',
components: './src/styles/components.css',
utilities: './src/styles/utilities.css'
}
}
打包优化
CSS 压缩配置
// webpack.config.js
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: {removeAll: true},
normalizeWhitespace: false
}
]
},
minify: [
CssMinimizerPlugin.cssnanoMinify,
CssMinimizerPlugin.cleanCssMinify
]
})
]
}
}
分块策略
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
},
tailwindBase: {
name: 'tailwind-base',
test: /base\.css$/,
chunks: 'all',
enforce: true
},
tailwindComponents: {
name: 'tailwind-components',
test: /components\.css$/,
chunks: 'all',
enforce: true
}
}
}
}
}
条件加载
按需加载样式
// src/utils/loadStyles.js
export const loadStyles = (name) => {
return import(
/* webpackChunkName: "styles/[request]" */
`../styles/${name}.css`
)
}
// 使用示例
if (process.env.NODE_ENV === 'development') {
loadStyles('debug')
}
路由级别分割
// routes/Home.js
import {lazy} from 'react'
import loadStyles from '../utils/loadStyles'
const Home = lazy(async () => {
await loadStyles('home')
return import('./HomeComponent')
})
export default Home
缓存优化
持久化缓存
// webpack.config.js
module.exports = {
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
},
name: 'production-cache'
}
}
模块标识符
// webpack.config.js
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.ids.HashedModuleIdsPlugin({
context: __dirname,
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 8
})
]
}
生产环境优化
CSS 提取配置
// webpack.prod.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
localIdentName: '[hash:base64:8]'
}
}
},
'postcss-loader'
]
}
]
}
}
资源优化
// webpack.prod.js
module.exports = {
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1]
return `vendor.${packageName.replace('@', '')}`
}
}
}
}
}
}
开发环境优化
快速构建配置
// webpack.dev.js
module.exports = {
mode: 'development',
devtool: 'eval-cheap-module-source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]'
}
}
},
'postcss-loader'
]
}
]
}
}
热模块替换
// webpack.dev.js
module.exports = {
devServer: {
hot: true,
static: {
directory: path.join(__dirname, 'public')
},
client: {
overlay: true
}
}
}
监控与分析
包体积分析
// webpack.config.js
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer')
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'css-bundle-report.html',
openAnalyzer: false,
generateStatsFile: true,
statsFilename: 'css-bundle-stats.json'
})
]
}
性能监控
// webpack.config.js
module.exports = {
performance: {
hints: 'warning',
maxAssetSize: 250000,
maxEntrypointSize: 250000,
assetFilter: function (assetFilename) {
return assetFilename.endsWith('.css')
}
}
}
最佳实践
-
提取策略
- 合理分层
- 按需加载
- 模块化组织
-
打包优化
- 压缩配置
- 分块策略
- 缓存利用
-
环境配置
- 开发效率
- 生产性能
- 调试便利
-
监控维护
- 体积控制
- 性能指标
- 持续优化