webpack学习---解析项目中使用的webpac配置

一、文件目录:

二、webpack.config.js

// 随着项目需求的增长,我们必须要找到更有效地管理配置文件的方法。
// 分离配置文件:
// webpack.base.config.js 公共环境的配置文件
// webpack.dev.config.js 开发环境下的配置文件
// webpack.prod.config.js 生产环境下的配置文件

const merge = require('webpack-merge');
// webpack-merge: 如果配置文件被分成了许多不同的部分,那么必须以某种方式来组合他们,
// 通常就是合并数组和对象,webpack-merge就是用来合并配置文件的

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// webpack Bundle Analyzer是一个可视化的工具,能够分析和生成打包输出后文件大小互动缩放树形图。

const devConfig = require('./build/webpack.dev.config.js'); // 开发环境下的配置文件
const prodConfig = require('./build/webpack.prod.config.js'); // 生产环境下的配置文件

const ip = require('ip').address();
// 获取局域网IP
const portFinder = require('portfinder');
// 获取port
const isDev = process.env.NODE_ENV === 'development';
const devWebpackConfig = merge(devConfig,
  {
    devServer: {
      host: ip, // 指定使用一个 host。默认是 localhost
      proxy: {
        '/api': {
          target: 'http://192.168.2.90:8080',
          changeOrigin: true,
          pathRewrite: { // 不传递/api
            '^/api': ''
          }
        }
      }
    }
  }
);
if (isDev) {
  module.exports = new Promise((resolve, reject) => {
    portFinder.getPort({ port: 9000, stopPort: 9999 }, function (err, port) {
      if (err) {
        reject(err);
      } else {
        devWebpackConfig.devServer.port = port;
        resolve(devWebpackConfig);
      }
    });
  });
} else {
  if (process.env.BUILD_REPORT) {
    module.exports = merge(prodConfig, {
      plugins: [
        new BundleAnalyzerPlugin()
      ]
    })
  } else {
    module.exports = prodConfig;
  }
}

二、webpack.base.config.js

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
 //打包后自动生成index.html文件,并把打包生成的js自动引入到这个html文件中

const CleanWebpackPlugin = require('clean-webpack-plugin');
//每次打包之前都会自动将dist文件中的内容删除

const appConfig = require('./app.config.js');
const srcPath = '../assets/';
const staticPrefix = process.env.NODE_ENV=='development'?'':appConfig.relativePrefix

module.exports = {
  entry: { // 要打包的文件
    app: [
      'react-hot-loader/patch', // webpack-dev-server 的热加载是开发人员修改了代码,代码经过打包,重新刷新了整个页面。而 react-hot-loader 不会刷新整个页面,
                                //它只替换了修改的代码,做到了页面的局部刷新。但它需要依赖 webpack 的 HotModuleReplacement 热加载插件。
      path.join(__dirname, srcPath, 'index.js')
    ]
  },
  resolve: { // 配置模块如何解析
    extensions: ['.js', '.jsx'], // 自动解析确定的扩展,引入的文件可以不加.js或者.jsx后缀
    alias: { // 创建 import 或 require 的别名,来确保模块引入变得更简单
             // 例如:import A from '../../components/A' === import A from 'components/A'
      components: path.join(__dirname, srcPath, 'components'),
      router: path.join(__dirname, srcPath, 'router'),
      store: path.join(__dirname, srcPath, 'store'),
      pages: path.join(__dirname, srcPath, 'pages'),
      api: path.join(__dirname, srcPath, 'api'),
    }
  },
  module: { // 如何处理项目中的不同类型的模块
    rules: [ // 创建模块时,匹配请求的规则数组。这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。
      {
        enforce: 'pre', // 通常rules是按照从下往上执行的,在对象中添加了enforce: 'pre'表示优先处理这个loader
        test: /.(js|jsx)$/, // 匹配以.js或者.jsx结尾的文件
        loader: 'eslint-loader', // 语法规则和代码风格的检查工具
        exclude: [ // 排除node_modules文件下的.js/.jsx文件
          path.resolve(__dirname, '../node_modules')
        ],
        options: {
          fix: true // 如果存在很浅显的不规范代码,eslint会自动帮你修复掉
        }
      },
      {
        test: /.(js|jsx)$/,
        loader: 'babel-loader', // Babel是一个JavaScript编译器,能够让我们放心的使用新一代JS语法。
        exclude: [
          path.join(__dirname, '../node_modules')
        ],
        options: {
          cacheDirectory: true // 通过使用 cacheDirectory 选项,将 babel-loader 提速至少两倍。 这会将转译的结果缓存到文件系统中。
        }
      },
      {
        test: /\.(png|jpg|gif|svg|pdf)$/,
        use: {
          loader: 'url-loader', // 为了减少请求,我们可以通过base64编码的方法来展示图片,url-loader就是用来处理这个的
          options: {
            name: staticPrefix + 'imgs/[name].[contenthash:8].[ext]',
            limit: 10240 // 图片大小小于10240才会处理成base64编码的方式
          }
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: {
          loader: 'file-loader', // 处理文件
          options: {
            name: staticPrefix + 'fonts/[name].[contenthash:8].[ext]'
          }
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: staticPrefix + 'media/[name].[contenthash:8].[ext]'
          }
        }
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({ // DefinePlugin插件使得前端项目更加工程化,说清晰点就是如何使用这个插件,在编译阶段根据NODE_ENV自动切换配置文件,提升前端开发效率。
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.APP_PREFIX': JSON.stringify(appConfig.absolutePrefix)
    }),
    new HtmlWebpackPlugin({ // //打包后自动生成index.html文件,并把打包生成的js自动引入到这个html文件中
      template: 'assets/index.html',
      templateParameters: {
        appPrefix: process.env.NODE_ENV=='development'?'/':appConfig.absolutePrefix
      }
    }),
    new CleanWebpackPlugin() // //每次打包之前都会自动将dist文件中的内容删除
  ],
  performance: false, // 配置如何展示性能提示,false不显示提示
  output: { // 打包后文件的存放地址等信息
    path: path.resolve(__dirname, '../dist') // 打包后文件所存放的位置
  }
}

三、webpack.dev.config.js

const webpack = require('webpack');
const merge = require('webpack-merge');
// webpack-merge: 如果配置文件被分成了许多不同的部分,
// 那么必须以某种方式来组合他们,通常就是合并数组和对象,webpack-merge就是用来合并配置文件的

const commonConfig = require('./webpack.base.config.js');
const appConfig = require('./app.config.js');
const devConfig = {
  mode: 'development', // 配置是开发环境还是生产环境
  devtool: 'cheap-module-eval-source-map', // 用作调试,原始源代码
  devServer: {
    historyApiFallback: {
      index: appConfig.absolutePrefix + 'index.html'
    },
    open: true,
    openPage: appConfig.relativePrefix,
    port: 9000,
    hot: true,
    overlay: {
      errors: true
    }
  },
  resolve: { // 配置模块如何解析
    alias: { // 别名
      'react-dom': '@hot-loader/react-dom'
    }
  },
  module: {
    rules: [{
      test: /\.less$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 2 // 用postcss-loaders和less-loader加载器
          }
        },
        'postcss-loader',
        'less-loader'
      ]
    }, {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        'postcss-loader' 
// 使用postcss-import插件,遵循@import规则,你可以将reset.css样式
// 合并到你的主样式表中,减少http请求。
      ]
    }]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 热更新
  ],
  output: {
    filename: '[name].[hash:8].js',
    publicPath: appConfig.absolutePrefix
  },
}

module.exports = merge(commonConfig, devConfig);

四、webpack.prod.config.js

const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 可以把css文件从打包后的js文件中剥离出来。减少了主bundle的页面文件大小,加快加载速度。

const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
// 压缩单独的css文件

const TerserJSPlugin = require('terser-webpack-plugin');
// 压缩js

const CopyWebpackPlugin = require('copy-webpack-plugin')
// 拷贝和压缩文件

const merge = require('webpack-merge');
const appConfig = require('./app.config.js');
const commonConfig = require('./webpack.base.config.js');
const prodConfig = module.exports = {
  mode: 'production',
  devtool: 'cheap-module-source-map', // 用作调试
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader, // 可以把css文件从打包后的js文件中剥离出来
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2
            }
          },
          'postcss-loader',
          'less-loader'
        ]
      }, {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader, // 可以把css文件从打包后的js文件中剥离出来
          'css-loader',
          'postcss-loader'
        ]
      }
    ]
  },
  optimization: { // 优化
    minimizer: [ // 是否进行代码压缩
      new OptimizeCSSAssetsPlugin({}), // 压缩单独的css文件
      new TerserJSPlugin({ // 压缩js
        cache: true,
        sourceMap: true,
        parallel: 4
      })
    ],
    usedExports: true,
    splitChunks: { // 进行代码的拆分
      chunks: 'all',
      automaticNameDelimiter: '.',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2, //  //模块出现2次就会被抽离到公共模块
          priority: -20,
          reuseExistingChunk: true
        }
      }
    },
    runtimeChunk: { // 提取webpack的runtime代码
      name: 'runtime'
    }
  },
  plugins: [
    new MiniCssExtractPlugin({ // 可以把css文件从打包后的js文件中剥离出来
      filename: appConfig.relativePrefix + 'css/[name].[contenthash:8].css'
    }),
    new CopyWebpackPlugin([ // 拷贝和压缩文件
      {
        from: path.resolve(__dirname, '../static'),
        to: appConfig.relativePrefix + 'static',
        ignore: ['.*']
      },
      {
        from: path.resolve(__dirname, '../styles'),
        to: appConfig.relativePrefix + 'styles',
        ignore: ['.*']
      }
    ])
  ],
  output: {
    filename: appConfig.relativePrefix + 'js/[name].[chunkhash:8].js',
    chunkFilename: appConfig.relativePrefix + 'js/[name].[chunkhash:8].js',
    publicPath: '/'
  }
};
module.exports = merge(commonConfig, prodConfig);

五、app.config.js

const absolutePrefix = '/app/demo/';

module.exports = {
  absolutePrefix : absolutePrefix,
  relativePrefix: absolutePrefix.substring(1)
}
发布了35 篇原创文章 · 获赞 1 · 访问量 6718

猜你喜欢

转载自blog.csdn.net/qq_36162529/article/details/104041737