webpack 配置

2021-09-06  本文已影响0人  A_走在冷风中

配置demo

const webpack = require('webpack')
const path = require('path')
const { cleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const InlineChunkHtmlPlugin = require('inline-chunk-html-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
// 删除 build.js 内的注释
class Myplugin {
  apply(compiler) {
    console.log('Myplugin 启动')
    // 第一个参数是方法名称
    compiler.hook.emit.tap('Myplugin', (compilation) => {
      // compilation => 可以理解为此次打包的上下文
      // compilation.assets 资源文件对象
      for (const name in compilation.assets) {
        // console.log(name) //资源文件名称
        // console.log(compilation.assets[name].source());//获取资源文件内容
        if (name.endsWith('.js')) {
          //判断是否以 .js 为结尾
          const contents = compilation.assets[name].source()
          const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
          compilation.assets.name = {
            source: () => withoutComments,
            size: () => withoutComments.length,
          }
        }
      }
    })
  }
}
module.exports = {
  entry: './src/main.css', //知道webpack打包入口路径
  output: {
    filename: 'bundle.js', //输出文件名
    path: path.join(__dirname, 'output'), //输出文件目录(要求绝对路径)
    publicPath: 'dist/', //打包后根目录文件夹
  },
  devtool: 'source-map',
  // Webpack Dev Serve 配置选项
  devServer: {
    hot: true, //开启 HMR
    contentBase: ['./public'], //静态资源路径
    proxy: {
      //代理配置
      '/api': {
        //什么开头的地址配置到 xx地址
        // http://loaclhost:8080/api/users => https://api.github.com/api/users
        target: 'https://api.github.com',
        pathRewite: {
          // http://loaclhost:8080/api/users => https://api.github.com/users
          '^/api': '',
        },
        // 不能使用 localhost:8080 作为请求 github 的主机名
        changeOrigin: true,
      },
    },
  },
  module: {
    rules: [
      {
        test: /.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
      {
        test: /.css$/, //正则表达式,用来匹配文件路径
        use: [
          'style-loader', //通过style-loader将css-loader转换为style注入
          'css-loader',
        ], //loader使用路径,从后向前执行
      },
      {
        test: /.png$/,
        use: 'file-loader',
      },
      {
        test: /.png$/,
        use: {
          loader: 'url-loader',
          options: {
            //配置项
            limit: 10 * 1024, //10kb以下文件转换为 dataurl,其他自动转换为file-loader形式
          },
        },
      },
      {
        test: /.html$/,
        use: {
          loader: 'html-loader',
          options: {
            attrs: ['img:src', 'a:href'], //针对a标签中静态资源打包处理
          },
        },
      },
      {
        test: /.md$/,
        use: {
          loader: [
            'html-loader',
            './markdown-loader', //相对路径
          ],
        },
      },
      {
        test: /\.jsx?$/,
        use: ['babel-loader'],
      },
      {
        test: /\.ts$/,
        use: ['ts-loader'],
      },
      {
        test: /\.vue$/,
        use: ['vue-loader'],
      },
    ],
  },
  optimization: {
    //代码压缩功能配置
    usedExports: true, //只导出外部使用了的成员
    // minimize:true,//压缩代码,删除未引用代码
    minimize: [
      new TerserWebpackPlugin(), //开启js压缩
      // new OptimizeCssAssetsWebpackPlugin(), //这样只有打包的时候有效,但是js压缩插件会失效,所以还需要写js压缩
      // 被弃用  可使用purgecss-webpack-plugin 插件
      new PurgeCSSPlugin(),
    ],
    concarenateModules: true, //合并模块代码
    // sideEffects: true, //没有用到的模块是否有副作用 是否可以清除
    usedExports: true, // 标记不被使用的函数
    // package.json中配置sideEffects 可添加不被删除的文件
    splitChunks: {
      chunks: 'initial', // async initial all
      minSize: 20000, //所拆分的文件最小值(默认)
      maxSize: 20000,
      minChunks: 1, //至少被引用次数
      cacheGroups: {
        //对拆包的过程进行分组
        //自定义键值对
        syVendors: {
          test: /[\\/]node_modules[\\/]/,
          filename: 'js/[id]_vendor.js',
          priority: -10, //优先级
        },
        default: {
          minChunks: 2,
          filename: 'js/syy_[id].js',
          priority: -20,
        },
      },
    },
  },
  plugins: [
    new cleanWebpackPlugin(),
    // 生成index.html
    new HtmlWebpackPlugin({
      //对html文件配置
      title: 'webpack Plugin Sample',
      meta: {
        viewport: 'width=device-width',
      },
      template: './src/index.html', //指定模板文件渲染index
    }),
    // 用于生成about.html
    new HtmlWebpackPlugin({
      filename: 'about.html',
    }),
    //将runtime中的css导入html中
    new PurgeCSSPlugin({
      paths: glob.sync(`${resolveApp('./src')}/**/*`, { nodir: true }),
      safelist: function () {
        return {
          standard: ['body', 'html', 'ef'],
        }
      },
    }),
    // 开发过程中一般不会使用,所以在 devServer 中配置
    new CopyWebpackPlugin([
      'public', //将public下所有文件输出到dist目录
    ]),
    new Myplugin(),
    new webpack.HotModuleReplacementPlugin(), //开启HMR需要的插件
    new webpack.DefinePlugin({
      API_BASE_URL: "'http://api.example/com'", //变量会挂载到 env.API_BASE_URL
    }),
    new MiniCssExtractPlugin(), //使用这个就不需要使用style-loader,会将css生成.css文件
    new OptimizeCssAssetsWebpackPlugin(), //压缩生成的.css文件,可以将他写到  optimization/minizer 数组下
    //资源压缩
    new CompressionPlugin({
      test: /\.(css|js)$/,
      minRatio: 0.8,
      threshold: 0,
      algorithm: 'gzip',
    }),
    //往当前html中注入内容,不用单发请求,根据实际情况来使用
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/]),
    new BundleAnalyzerPlugin(), //打包时间和内容分析
  ],
}

区分打包环境

paths.js

const path = require('path')

const appDir = process.cwd()

const resolveApp = (relativePath) => {
  return path.resolve(appDir, relativePath)
}

module.exports = resolveApp

webpack.common.js

const resolveApp = require('./paths')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { merge } = require('webpack-merge')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// 时间分析
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()

// 导入其它的配置
const prodConfig = require('./webpack.prod')
const devConfig = require('./webpack.dev')

// 定义对象保存 base 配置信息
const commonConfig = (isProduction) => {
  return {
    entry: './src/main.css', //知道webpack打包入口路径
    output: {
      filename: 'bundle.js', //输出文件名
      path: path.join(__dirname, 'output'), //输出文件目录(要求绝对路径)
      publicPath: 'dist/', //打包后根目录文件夹
    },
    resolve: {
      extensions: ['.js', '.json', '.ts', '.jsx', '.vue'],
      alias: {
        '@': resolveApp('./src'),
      },
    },
    optimization: {
      runtimeChunk: true,
    },
    devtool: 'source-map',
    // Webpack Dev Serve 配置选项
    module: {
      rules: [
        {
          test: /.js$/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
            },
          },
        },
        {
          test: /\.css$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            {
              loader: 'css-loader',
              options: {
                importLoaders: 1,
                esModule: false,
              },
            },
            'postcss-loader',
          ],
          sideEffects: true,
        },
        {
          test: /.png$/,
          use: 'file-loader',
        },
        {
          test: /.png$/,
          use: {
            loader: 'url-loader',
            options: {
              //配置项
              limit: 10 * 1024, //10kb以下文件转换为 dataurl,其他自动转换为file-loader形式
            },
          },
        },
        {
          test: /.html$/,
          use: {
            loader: 'html-loader',
            options: {
              attrs: ['img:src', 'a:href'], //针对a标签中静态资源打包处理
            },
          },
        },
        {
          test: /.md$/,
          use: {
            loader: [
              'html-loader',
              './markdown-loader', //相对路径
            ],
          },
        },
        {
          test: /\.jsx?$/,
          use: ['babel-loader'],
        },
        {
          test: /\.ts$/,
          use: ['ts-loader'],
        },
        {
          test: /\.vue$/,
          use: ['vue-loader'],
        },
      ],
    },
    plugins: [
      //输出文件内容
      new HtmlWebpackPlugin({
        //自定义title
        title: 'copyWebpackPlugin',
        template: './public/index.html',
      }),
    ],
  }
}
module.exports = (env) => {
  const isProduction = env.production

  process.env.NODE_ENV = isProduction ? 'production' : 'development'

  // 依据当前的打包模式来合并配置
  const config = isProduction ? prodConfig : devConfig

  const mergeConfig = merge(commonConfig(isProduction), config)

  return smp.wrap(mergeConfig)
}

webpack.dev.js

const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  mode: 'development',
  devtool: 'cheap-module-source-map',
  target: 'web',
  devServer: {
    hot: true, //开启 HMR
    contentBase: ['./public'], //静态资源路径
    proxy: {
      //代理配置
      '/api': {
        //什么开头的地址配置到 xx地址
        // http://loaclhost:8080/api/users => https://api.github.com/api/users
        target: 'https://api.github.com',
        pathRewite: {
          // http://loaclhost:8080/api/users => https://api.github.com/users
          '^/api': '',
        },
        // 不能使用 localhost:8080 作为请求 github 的主机名
        changeOrigin: true,
      },
    },
  },
  plugins: [
    new ReactRefreshWebpackPlugin(),
    new VueLoaderPlugin(), //vue 热更新
  ],
}

webpack.prod.js

const webpack = require('webpack')
const resolveApp = require('./paths')
const { cleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const InlineChunkHtmlPlugin = require('inline-chunk-html-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
// 删除 build.js 内的注释
class Myplugin {
  apply(compiler) {
    console.log('Myplugin 启动')
    // 第一个参数是方法名称
    compiler.hook.emit.tap('Myplugin', (compilation) => {
      // compilation => 可以理解为此次打包的上下文
      // compilation.assets 资源文件对象
      for (const name in compilation.assets) {
        // console.log(name) //资源文件名称
        // console.log(compilation.assets[name].source());//获取资源文件内容
        if (name.endsWith('.js')) {
          //判断是否以 .js 为结尾
          const contents = compilation.assets[name].source()
          const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
          compilation.assets.name = {
            source: () => withoutComments,
            size: () => withoutComments.length,
          }
        }
      }
    })
  }
}
module.exports = {
  optimization: {
    //代码压缩功能配置
    usedExports: true, //只导出外部使用了的成员
    // minimize:true,//压缩代码,删除未引用代码
    minimize: [
      new TerserWebpackPlugin(), //开启js压缩
      // new OptimizeCssAssetsWebpackPlugin(), //这样只有打包的时候有效,但是js压缩插件会失效,所以还需要写js压缩
      // 被弃用  可使用purgecss-webpack-plugin 插件
      new PurgeCSSPlugin(),
    ],
    concarenateModules: true, //合并模块代码
    // sideEffects: true, //没有用到的模块是否有副作用 是否可以清除
    usedExports: true, // 标记不被使用的函数
    // package.json中配置sideEffects 可添加不被删除的文件
    splitChunks: {
      chunks: 'initial', // async initial all
      minSize: 20000, //所拆分的文件最小值(默认)
      maxSize: 20000,
      minChunks: 1, //至少被引用次数
      cacheGroups: {
        //对拆包的过程进行分组
        //自定义键值对
        syVendors: {
          test: /[\\/]node_modules[\\/]/,
          filename: 'js/[id]_vendor.js',
          priority: -10, //优先级
        },
        default: {
          minChunks: 2,
          filename: 'js/syy_[id].js',
          priority: -20,
        },
      },
    },
  },
  plugins: [
    new cleanWebpackPlugin(),
    // 生成index.html
    new HtmlWebpackPlugin({
      //对html文件配置
      title: 'webpack Plugin Sample',
      meta: {
        viewport: 'width=device-width',
      },
      template: './src/index.html', //指定模板文件渲染index
    }),
    // 用于生成about.html
    new HtmlWebpackPlugin({
      filename: 'about.html',
    }),
    //将runtime中的css导入html中
    new PurgeCSSPlugin({
      paths: glob.sync(`${resolveApp('./src')}/**/*`, { nodir: true }),
      safelist: function () {
        return {
          standard: ['body', 'html', 'ef'],
        }
      },
    }),
    // 开发过程中一般不会使用,所以在 devServer 中配置
    new CopyWebpackPlugin([
      'public', //将public下所有文件输出到dist目录
    ]),
    new Myplugin(),
    new webpack.HotModuleReplacementPlugin(), //开启HMR需要的插件
    new webpack.DefinePlugin({
      API_BASE_URL: "'http://api.example/com'", //变量会挂载到 env.API_BASE_URL
    }),
    new MiniCssExtractPlugin(), //使用这个就不需要使用style-loader,会将css生成.css文件
    new OptimizeCssAssetsWebpackPlugin(), //压缩生成的.css文件,可以将他写到  optimization/minizer 数组下
    //资源压缩
    new CompressionPlugin({
      test: /\.(css|js)$/,
      minRatio: 0.8,
      threshold: 0,
      algorithm: 'gzip',
    }),
    //往当前html中注入内容,不用单发请求,根据实际情况来使用
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/]),
    new BundleAnalyzerPlugin(), //打包时间和内容分析
  ],
}
上一篇下一篇

猜你喜欢

热点阅读