react-cli 脚手架配置
运行命令:
"dev": "cross-env MODE_ENV=deveploment webpack serve --config ./config/webpack.config.js"
"build": "cross-env MODE_ENV=production webpack --config ./config/webpack.config.js"
在webpack.config.js文件中进行配置
const path = require('path')
const EslintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minizer-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') // 解决html问题
// 判断环境变量 是否为生产模式
const isPro = process.env.MODE_ENV === 'production'
// 处理样式loader函数
const getStyleLoader = (pre) => {
return [
// 提取css样式文件
isPro ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions:{ plugins: ['postcss-preset-env']}
}
},
pre && {
loader: pre,
options : pre ==='less-loader'
? {
// antd 自定义主题颜色配置
// 在main.js文件中引入为.less文件
lessOptions: {
modifyVars: { '@primary-color': '#1da57a'},
javascriptEnabled: true
}
}
: {}
},
].filter(Boolean)
}
module.exports = {
entry: './src/main.js',
output: {
// 输出目录,生产环境下使用绝对路径,开发模式下不需要 undefined
path: isPro ? path.resolve(__dirname,'../dist') : undefined,
filename: isPro ? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].js' ,
chunkFilename: isPro ? 'static/js/[name].[contenthash:10].chunk.js' : 'static/js/[name].chunk.js' ,
assetModuleFilename: 'static/media/[hash:10].chunk.js',
// 清空上一次打包内容
clean: true
},
module: {
rules: [
{
test: /\.css$/,
use: getStyleLoader(),
},
{
test: /\.less$/,
use: getStyleLoader('less-loader')
},
{
test: /\.s[ac]ss/,
use: getStyleLoader('sass-loader')
},
// 处理图片
{
test: /\.(jpe?g|png|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: { maxSize: 10*1024 }
},
},
// 处理其他资源
{
test: /\.(woff2?|ttf)$/,
type: 'asset/resoure',
}
// 处理js
{
test: /\.jsx?$/,
include: path.resolve(__dirname,'./src'),
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false,
plugins: [
!isPro && 'react-refresh/babel', // 激活js的HMR
].filter(Boolean)
}
}
]
},
// 插件处理
plugins: [
new EslintWebpackPlugin({
context: path.resolve(__dirname,'../src'),
exclude: 'node_modules',
cache: true,
cacheLocation: path.resolve(__dirname,'./node_modules/.cache/.eslintcache'),
}),
new HtmlWebpackPlugin({ template: path.resolve(__dirname,'../public/index.html')}),
isPro && new MiniCssExtractPlugin({
filename: 'static/css/[name].[contenthash:10].css',
chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
}),
// 复制图标
isPro && new CopyWebpackPlugin({
patterns: [
from: path.resolve(__dirname,'../public'),
to: path.resolve(__dirname,'../dist'),
globOptions:{ ignore: ['**/index.html'] } // 忽略html文件
]
}),
!isPro && new ReactRefreshWebpackPlugin()
].filter(Boolean),
mode: isPro ? 'production' : 'development',
devtool: isPro ? 'source-map' : 'cleap-module-source-map',
optimization: {
splitChunks:{
chunks: 'all',
cacheGroups: {
// 减小文件打包体积
react: {
test: /[\\/]node_modules[\\/]react(.*)?[\\/]/, // 打包相关react文件
name: 'chunk-react', // 打包到哪个文件
priority: 40, // 打包权重
},
antd: {
test: /[\\/]node_modules[\\/]antd[\\/]/, // 打包相关antd文件
name: 'chunk-antd', // 打包到哪个文件
priority: 30, // 打包权重
},
libs: {
test: /[\\/]node_modules[\\/]/, // 打包剩余文件
name: 'chunk-libs', // 打包到哪个文件
priority: 20, // 打包权重
}
}
},
runtimeChunk: { name: (entrypoint)=> `runtime~${entrypoint.name}.js` },
// 是否需要进行压缩
minimize: isPro,
minimizer: [
new CssMinimizerWebpackPlugin(),
new TerserWebpackPlugin(),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
['gifsicle',{ interlaced: true}],
['jpegtran',{ progreessive: true}],
['optipng',{ optimizationLevel: 5}],
['svgo',{ plugins: [
'preset-default',
'prefixIds',
{
name: 'sortAttrs',
params: { xmInsOrder: 'alphabetical'}
}
]}]
]
}
}
})
]
},
// webpack 解析模版加载选项
resolve: {
// 自动补全文件扩展名
extensions: ['.jsx','.js','.json']
},
devServer: {
host: 'localhost',
port: 3000,
open: true,
hot: true,
historyApiFallback: true, // 解决前端路由刷新404问题
}
}