- const path = require('path')
- const EslintWebpackPlugin = require('eslint-webpack-plugin')
- const HtmlWebpackPlugin = require('html-webpack-plugin')
- const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
- //封装处理样式配置
- const getStyleloaders = (pre)=>{
- return [
- 'style-loader',
- 'css-loader',
- // 处理 css 兼容性问题
- //需要配合 package.json 中的browserslist 来指定兼容性做到什么程度
- {
- loader: 'postcss-loader',
- options: {
- postcssOptions: {
- plugins: 'postcss-preset-env'
- }
- }
- },
- pre
- ].filter(Boolean)
- };
- //要用 commonjs的方式以对象的模式暴露出去
- 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][etx][query]'
- },
- // 配置loader
- 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
- {
- test:/\.jsx?$/,
- include:path.resolve(__dirname,'../src'),
- loader:'babel-loader',//babel 也需要有一个 babel 的配置文件
- options:{
- catchDirectory:true,
- catchCompression:false,
- plugins:[
- 'react-refresh/babel',//用来解决react脚手架下 js不能热更新的问题
- ]
- }
- }
- ]
- },
- // 配置plugin
- // 处理html
- plugin:[
- //eslint 插件也是需要有自己的配置文件
- new EslintWebpackPlugin({
- context:path.resolve(__dirname,'../src'),
- exclude:'node_modules',
- cache:true,
- cacheLocation:path.resolve(__dirname,'../node_modules/.catch/.eslintcache'),
- }),
- new HtmlWebpackPlugin({
- template:path.resolve(__dirname,'../public/index.html'),
- }),
- new ReactRefreshWebpackPlugin()//用来解决react脚手架下 js不能热更新的问题
- ],
- // 环境设置
- mode:'development',
- devtool:'cheap-module-source-map',
- optimization:{
- splitChunks:{
- chunks:'all'
- },
- runtimeChunk:{
- name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
- }
- },
- //webpack 解析模块加载选项
- // 解决运行react项目时报错 Module not found:Error:can't resolve './App' in 'xx/xxx/xxx/x'
- resolve:{
- //自动补全文件扩展名
- extentions:['.jsx','.js','json']
- },
- devServer:{
- host:'localhost',
- port:3000,
- open:true,
- hot:true,
- historyApiFallback:true,//解决前端路由刷新404问题
- }
- }
- const path = require('path')
- const EslintWebpackPlugin = require('eslint-webpack-plugin')
- const HtmlWebpackPlugin = require('html-webpack-plugin')
- // 生产模式下不需要激活热更新
- // const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
- // CSS提取为单独文件
- const MiniCssExtractPlugin = require('mini-css-extract-plugin')
- // css 压缩文件
- const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
- // js 压缩,使用css压缩后必须使用的插件
- const TerserWebpackPlugin = require('terser-webpack-plugin')
- // 图片 压缩插件
- const ImageMinimizerWebpackPlugin = require('image-minimizer-webpack-plugin')
- // 如果出现 网站图标 需要用该复制插件将其复制到dist目录下
- const CopyPlugin = require("copy-webpack-plugin");
-
-
- const getStyleloaders = (pre) => {
- return [
- // 'style-loader',
- MiniCssExtractPlugin.loader,//将style-loader替换为插件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][etx][query]',
- clean: true,//将上次打包内容清空
- },
- module: {
- rules: [
- {
- 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'
- },
- {
- test: /\.jsx?$/,
- include: path.resolve(__dirname, '../src'),
- loader: 'babel-loader',
- options: {
- catchDirectory: true,
- catchCompression: false,
-
- // 生产模式下不需要激活热更新
- // plugins:[
- // 'react-refresh/babel',
- // ]
- }
- }
- ]
- },
- plugin: [
- new EslintWebpackPlugin({
- context: path.resolve(__dirname, '../src'),
- exclude: 'node_modules',
- cache: true,
- cacheLocation: path.resolve(__dirname, '../node_modules/.catch/.eslintcache'),
- }),
- new HtmlWebpackPlugin({
- template: path.resolve(__dirname, '../public/index.html'),
- }),
- // new ReactRefreshWebpackPlugin(),// 生产模式下不需要激活热更新
- // css 打包为单独文件插件
- new MiniCssExtractPlugin({
- filename: 'static/css/name.[contenthash:10].css',
- chunkFilename: 'static/css/name.[contenthash:10].chunk.css'
- }),
- // 复制插件 处理public下其他资源 如网站图标
- new CopyPlugin({
- patterns: [
- // 设置从何处复制到何处
- {
- from: path.resolve(__dirname,'../public'),
- to: path.resolve(__dirname,'../dist')
- },
- ],
- globOptions: {
- //设置忽略 index.html 文件
- ignore: ['**/index.html']
- }
- }),
- ],
- mode: 'production', // 改为生产模式
- devtool: 'source-map',//使用 source-map
- optimization: {
- splitChunks: {
- chunks: 'all'
- },
- runtimeChunk: {
- name: (entrypoint) => `runtime~${entrypoint.name}.js`,
- },
- // 压缩插件放在 optimization 对象内
- minimizer: [
- new CssMinimizerWebpackPlugin(),//压缩 css 插件,
- new TerserWebpackPlugin(),//压缩 js 插件,
- //压缩图片插件,
- new ImageMinimizerWebpackPlugin({
- minimizerOptions: {
- plugins: [
- ["gifsicle", { interlaced: true }],
- ["jpegtran", { progressive: true }],
- ["optipng", { optimizationLevel: 5 }],
- [
- "svgo",
- {
- plugins: extendDefaultPlugins([
- {
- name: "removeViewBox",
- active: false,
- },
- {
- name: "addAttributesToSVGElement",
- params: {
- attributes: [{ xmlns: "http://www.w3.org/2000/svg" }],
- },
- },
- ]),
- },
- ],
- ],
- },
- }),
- ]
- },
- resolve: {
- extentions: ['.jsx', '.js', 'json']
- },
-
- //生产模式不需要devsever
- // devServer:{
- // host:'localhost',
- // port:3000,
- // open:true,
- // hot:true,
- // historyApiFallback:true,
- // }
- }
将生产模式和开发模式的配置进行合并,通过 process.env.NODE_ENV 的值来判断当前为生产环境还是开发环境。
- const isProd = process.env.NODE_ENV ==='production'
-
-
- //三元判断 加载哪一个插件
- isProd ? MiniCssExtractPlugin.loader : 'style-loader',
-
-
- //根据是否为生产模式来决定是否加载插件
- plugins:[
- !isProd && 'react-refresh/babel',//用来解决react脚手架下 js不能热更新的问题
- ].filter(Boolean)