// webpack.dev.js 资源内下载即可
//
// 总结了一下需要安装的包
/**
* npm i css-loader less-loader sass-loader sass stylus-loader style-loader postcss-loader postcss-preset-env eslint-webpack-plugin html-webpack-plugin -D
*
* npm i babel-loader @babel/core babel-preset-react-app eslint-config-react-app -D
*
* npm i webpack-dev-server webpack webpack-cli -D
*
* npm i react react-dom
*
* // 启动会报错需要配置环境变量因此额外添加这个插件
* npm i --save-dev cross-env
*
* // 热更新还需要使用到插件 pmmmwh/react-refresh-webpack-plugin
* npm i @pmmmwh/react-refresh-webpack-plugin react-refresh
*
* // 使用react-router-dom路由这个包
* npm i react-router-dom
*/
/**
* 使用Antd时修改主题色包(antd 使用的是less因此使用less)
* https://3x.ant.design/docs/react/customize-theme-cn
* npm i craco-less
* @primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 链接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 错误色
@font-size-base: 14px; // 主字号
@heading-color: rgba(0, 0, 0, 0.85); // 标题色
@text-color: rgba(0, 0, 0, 0.65); // 主文本色
@text-color-secondary : rgba(0, 0, 0, .45); // 次文本色
@disabled-color : rgba(0, 0, 0, .25); // 失效色
@border-radius-base: 4px; // 组件/浮层圆角
@border-color-base: #d9d9d9; // 边框色
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // 浮层阴影
*/
const EslintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const path = require('path')
const getStyleLoaders = pre => {
return [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"]
}
}
},
pre && {
loader: pre,
options: pre === "less-loader" ? {
// Antd自定义主题色
lessOptions: {
modifyVars: {"@primary-color": "#1da57a"},
javascriptEnabled: true
}
} : {}
}
].filter(Boolean)
}
module.exports = {
entry: './src/main.js',
output: {
path: undefined,
filename: "static/js/[name].js",
chunkFilename: "static/js/[name].chunk.js",
assetModuleFilename: "static/media/[hash:10][ext][query]",
},
module: {
rules: [
// 处理css
{
test: /\.css$/,
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
// 处理图片资源
{
test: /\.(jpe?g|png|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
}
}
},
// 处理其它资源
{
test: /\.(woff2?|ttf)$/,
type: 'asset/resource'
},
// 处理js (eslint babel)
{
test: /\.jsx?$/,
include: path.resolve(__dirname, "../src"),
loader: "babel-loader",
options: {
cacheDirectory: true,
cacheCompression: false,
plugins: [
"react-refresh/babel" // 激活js的HMR功能
]
}
},
]
},
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"),
}),
new ReactRefreshWebpackPlugin(), // 激活js的HMR功能(下方HMR功能也要激活)
],
mode: "development",
devtool: "cheap-module-source-map",
optimization: {
splitChunks: {
chunks: "all"
},
runtimeChunk: {
name: entrypoint => `runtime~${entrypoint.name}.js`
}
},
// webpack解析模块加载选项
resolve: {
// 自动补全文件扩展名
extensions: [".jsx", ".js", ".json"]
},
devServer: {
host: "localhost",
port: 3000,
open: true,
hot: true,
historyApiFallback: true, // 开启后如果没找到对应路由不会出现404页面
}
}
// webpack.prod.js
// 第一步修改输出output
const EslintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 第二步css压缩
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// 第三步js压缩, 因为第二步css压缩后如果不进行js压缩会出问题
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 第四步: mode改成production devtool也改,HMR功能也删掉(ReactRefreshWebpackPlugin)
// 第五步图片压缩
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin")
// 第六步安装依赖
/**
* npm i mini-css-extract-plugin css-minimizer-webpack-plugin -D
* // 图片依赖比较难下载
* npm i image-minimizer-webpack-plugin -D
* // 图片无损压缩(下载不了下多下几次,用cnpm试试)
* npm i imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
*
*/
// 最后一步,使用webpack配置图标 npm i copy-webpack-plugin --save-dev
const CopyWebpackPlugin = require('copy-webpack-plugin')
const path = require('path')
const getStyleLoaders = pre => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"]
}
}
},
pre
].filter(Boolean)
}
module.exports = {
entry: './src/main.js',
output: {
// 第一步修改输出
path: path.resolve(__dirname, '../dist'),
filename: "static/js/[name].[contenthash:10].js",
chunkFilename: "static/js/[name].[contenthash:10].chunk.js",
assetModuleFilename: "static/media/[hash:10][ext][query]",
clean: true
},
module: {
rules: [
// 处理css
{
test: /\.css$/,
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
// 处理图片资源
{
test: /\.(jpe?g|png|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
}
}
},
// 处理其它资源
{
test: /\.(woff2?|ttf)$/,
type: 'asset/resource'
},
// 处理js (eslint babel)
{
test: /\.jsx?$/,
include: path.resolve(__dirname, "../src"),
loader: "babel-loader",
options: {
cacheDirectory: true,
cacheCompression: false,
}
},
]
},
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"),
}),
new MiniCssExtractPlugin({
filename: "static/css/[name].[contenthash:10].css",
chunkFilename: "static/css/[name].[contenthash:10].css"
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, "../public"),
to: path.resolve(__dirname, "../dist"),
globOptions: {
// 忽略index.html文件
ignore: ["**/index.html"]
}
}
]
})
],
mode: "production",
devtool: "source-map",
optimization: {
splitChunks: {
chunks: "all",
// 将体积比较大的单独打包增加速度
cacheGroups: {
// react react-dom react-router-dom一起打包成一个js文件
react: {
test: /[\\/]node_modules[\\/]react(.*)?[\\/]/,
name: "chunk-react",
priority: 40,
},
// antd单独打包
antd: {
test: /[\\/]node_modules[\\/]antd[\\/]/,
name: "chunk-antd",
priority: 30,
},
// 剩下的node_modules单独打包
libs: {
test: /[\\/]node_modules[\\/]/,
name: "chunk-libs",
priority: 20,
},
}
},
runtimeChunk: {
name: entrypoint => `runtime~${entrypoint.name}.js`
},
minimizer: [
new CssMinimizerPlugin(),
new TerserWebpackPlugin(),
// 图片压缩, 安装成功使用,不成功先注释
// new ImageMinimizerPlugin({
// implementation: ImageMinimizerPlugin.imageminGenerate,
// options: {
// plugins: [
// ["gifsicle", {interlaced: true}],
// ["jpegtran", {progressive: true}],
// ["optipng", {optimizationLevel: 5}],
// [
// "svgo",
// {
// plugins: [
// "preset-default",
// "prefixIds",
// {
// name: "sortAttrs",
// params: {
// xmlnsOrder: "alphabetical"
// }
// }
// ]
// }
// ],
// ]
// }
// }),
],
},
// webpack解析模块加载选项
resolve: {
// 自动补全文件扩展名
extensions: [".jsx", ".js", ".json"]
},
}