前端开发 webpack 通用配置

以后公司前端新项目 webpack 可以选择使用这一套通用配置,该配置满足了一下诸多功能。

使用者可以自己定义一些 loader 以及 plugin 以满足日常开发需要,在下面给出详细的注释以便理解与使用。(开发时可以把注释删掉)

- webpack.base.js

// webpack.base.js用于通用的 webpack 配置

// 自动适配浏览器前缀
const autoprefixer = require('autoprefixer');
// 用于多页面入口打包,
const glob = require('glob');
// 获取路径
const path = require('path');
// 自动清除输出目录插件
const CleanWebpackPlugin = require('clean-webpack-plugin');
// webpack 打包出错 terminal log 插件
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
// 引入外部资源,申生成入口插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 CSS 提取为独立的文件的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 获取项目根目录
const projectRoot = process.cwd();

// 多页面应用入口程序,通过匹配获取对应页面入口,单页面可以直接定义 entry 就行
const setMPA = () => {
  const entry = {};
  const htmlWebpackPlugins = [];
  const entryFiles = glob.sync(path.join(projectRoot, './src/*/index.js'));

  Object.keys(entryFiles)
    .map((index) => {
      const entryFile = entryFiles[index];
      // '/Users/buzhuo/my-project/src/index/index.js'
      const match = entryFile.match(/src\/(.*)\/index\.js/);
      const pageName = match && match[1];
      entry[pageName] = entryFile;
      return htmlWebpackPlugins.push(
        new HtmlWebpackPlugin({
          inlineSource: '.css$',
          template: path.join(projectRoot, `./src/${pageName}/index.html`),
          filename: `${pageName}.html`,
          chunks: ['vendors', pageName],
          inject: true,
          minify: {
            html5: true,
            collapseWhitespace: true,
            preserveLineBreaks: false,
            minifyCSS: true,
            minifyJS: true,
            removeComments: false,
          },
        })
      );
    });
// 返回入口以及入口对应的 htmlWebpackPlugins
  return {
    entry,
    htmlWebpackPlugins,
  };
};

const { entry, htmlWebpackPlugins } = setMPA();

module.exports = {
  entry: entry,
  output: {
    path: path.join(projectRoot, 'dist'),
    filename: '[name]_[chunkhash:8].js'
  },
  module: {
    rules: [
      {
        test: /.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ],
      },
      {
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
          {
            // CSS预处理
            loader: 'postcss-loader',
            options: {
              plugins: () => [
                autoprefixer({
                  browsers: ['last 2 version', '>1%', 'ios 7'],
                }),
              ],
            },
          },
          {
            // px 自动转换为 rem 移动端,若无移动端需求该 loader 可删去
            loader: 'px2rem-loader',
            options: {
              remUnit: 75,
              remPrecision: 8,
            },
          },
        ],
      },
      {
        test: /.(png|jpg|gif|jpeg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
            },
          },
        ],
      },
      {
        test: /.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash:8][ext]',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name]_[contenthash:8].css',
    }),
    new CleanWebpackPlugin(),
    new FriendlyErrorsWebpackPlugin(),
    function errorPlugin() {
      this.hooks.done.tap('done', (stats) => {
      if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') === -1) {
          process.exit(1);
      }
      });
    },
  ].concat(htmlWebpackPlugins),
  // webpack 在打包时仅出错才会输出到 terminal,具体参数可到https://webpack.js.org/查看
  stats: 'errors-only',
};

- webpack.dev.js

// merge 用来合并 webpack.base.js 与 webpack.dev.js
const merge = require('webpack-merge');
const webpack = require('webpack');
const baseConfig = require('./webpack.base');

const devConfig = {
  mode: 'production',
  plugins: [
    // 生产环境下开启热加载插件
    new webpack.HotModuleReplacementPlugin(),
  ],
devServer: {
    // 指定 devServer 相关,在此可以指定 port 等配置
  contentBase: './dist',
    hot: true,
    stats: 'errors-only',
  },
  // 该参数见下图
  devtool: 'cheap-source-map',
};

module.exports = merge(baseConfig, devConfig);

- webpack.prod.js

webpack 4.0 以上将 uglifyjs 与 treeshaking 设为 webpack 默认,只要设置mode = production 就默认开启

// css 压缩插件
const cssnano = require('cssnano');
  // merge webpack.dev.js 与 webpack.prod.js
const merge = require('webpack-merge');
  // 用于 cdn 加速 react,引用外部资源
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
  // 提取 css 到单独文件并且压缩 css
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  // 前面提到的基本配置
const baseConfig = require('./webpack.base');

const prodConfig = {
  mode: 'production',
  plugins: [
    new OptimizeCSSAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: cssnano,
    }),
    new HtmlWebpackExternalsPlugin({
      externals: [
        {
          module: 'react',
          entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js',
          global: 'React',
        },
        {
          module: 'react-dom',
          entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js',
          global: 'ReactDOM',
        },
      ],
    }),
  ],
  // code split
  optimization: {
    splitChunks: {
    minSize: 0,
      cacheGroups: {
        commons: {
          name: 'vendors',
          chunks: 'all',
          minChunks: 2,
        },
      },
    },
  },
};

module.exports = merge(baseConfig, prodConfig);

所需依赖

autoprefixer
babel-loader
clean-webpack-plugin
css-loader
cssnano
eslint-loader
file-loader
friendly-errors-webpack-plugin
glob
html-inline-css-webpack-plugin
html-loader
html-webpack-externals-plugin
html-webpack-inline-source-plugin
html-webpack-plugin
less
less-loader
mini-css-extract-plugin
node-notifier
optimize-css-assets-webpack-plugin
postcss-loader
postcss-preset-env
px2rem-loader
raw-loader
react
react-dom
style-loader
uglifyjs-webpack-plugin
url-loader
webpack
webpack-cli
webpack-merge

执行命令

在项目根目录下的 package.json 的 scripts 里新增脚本:

开发环境 && 生产环境

"dev": "webpack-dev-server --config webpack.dev.js --open",
"build": "webpack --config webpack.prod.js",
posted @ 2020-09-22 09:18  jaiodfjiaodf  阅读(683)  评论(2编辑  收藏  举报