webpack试练05之学以致用

329 阅读2分钟

webpack基础的配置及进阶也学了一个大概了,怎样设计自己的构建配置呢,来简单聊聊

1、目录结构

image.png

  • lib
  • test
    • smoke
    • unit
  • .eslint
  • .gitignore
  • package.json

2、lib webpack配置文件

最为重要的无疑是这四个文件

  1. webpack.base.js
const CleanWebpackPlugin  = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const FriendlyPlugin = require('friendly-errors-webpack-plugin');
// const webpack = require("webpack");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const Autoprefixer = require('autoprefixer');
const path = require('path');
const glob = require('glob');


const projectRoot = process.cwd()

const setMPA = () => {
  // 多页面打包
  const entry = {};
  const htmlWebpackPlugin = [];
  const entryFiles = glob.sync(path.join(projectRoot, './src/*/index.js'));

  Object.keys(entryFiles).map((index) => {
    const entryFile = entryFiles[index];
    // 正则匹配
    const match = entryFile.match(/src\/(.*)\/index\.js/);
    const pageName = match && match[1];
    entry[pageName] = entryFile;
    return htmlWebpackPlugin.push(
      new HtmlWebpackPlugin({
        template: path.join(projectRoot, `src/${pageName}/index.html`),
        filename: `${pageName}.html`,
        inject: true,
        chunks: ['common', 'vendors', pageName],
        minify: {
          html5: true,
          collapseWhitespace: true,
          preserveLineBreaks: false,
          minifyCSS: true,
          minifyJS: true,
          removeComments: false,
        },
        // process,
      }),
    );
  });
  return {
    entry,
    htmlWebpackPlugin,
  };
};
const { entry, htmlWebpackPlugin } = setMPA();

module.exports = {
  entry,
  module: {
    rules: [
      {
        test: /.js$/,
        use: [
          'babel-loader',
          // "eslint-loader"
        ],
      },
      {
        test: /.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: () => [
                Autoprefixer({
                  browsers: ['last 2 versions', '>1%', 'ios 7'],
                }),
              ],
            },
          },
          {
            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|wof2|eot|ttf|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash:8][ext]',
            },
          },
        ],
      },
    ],
  },

  plugins: [
    // new webpack.ProvidePlugin({
    //   // 添加process对象
    //   process: "process/browser",
    // }),
    new MiniCssExtractPlugin({
      // 单独提取css文件
      filename: '[name]_[contenthash:8].css',
    }),
    new CleanWebpackPlugin(), // 打包前清理目录
    new FriendlyPlugin(), // 命令行显示优化
    function errorPlugin() {
      // 错误捕获
      this.hooks.done.tap('done', (status) => {
        if (
          status.compilation.errors
          && status.compilation.errors.length
          && process.argv.indexOf('--watch' === -1)
        ) {
          console.log('build error');//eslint-disable-line
          // process.exit(1);
        }
      });
    },
  ].concat(htmlWebpackPlugin),
  stats: 'errors-only',
};

  1. webpack.dev.js
const merge = require('webpack-merge');
const webpack = require('webpack');
const baseConfig = require('./webpack.base');


const devConfig = {
  mode: 'development',
  plugins: [new webpack.HotModuleReplacementPlugin()],
  devServer: {
    contentBase: './dist',
    hot: true,
    stats: 'errors-only',
  },
  devtool: 'cheap-source-map',
};

module.exports = merge(baseConfig, devConfig);

  1. webpack.prod.js
const merge = require('webpack-merge');

const OptimizeCss = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackExternalPlugin = require('html-webpack-externals-plugin');
const cssnano = require('cssnano');
const baseConfig = require('./webpack.base');

const prodConfig = {
  mode: 'production',
  plugins: [
    new OptimizeCss({
      // 代码压缩
      assetNameRegExp: /\.css$/g,
      cssProcessor: cssnano,
    }),
    new HtmlWebpackExternalPlugin({
      // 提取公告资源包
      externals: [
        {
          module: 'react',
          entry: 'https://unpkg.com/react@16/umd/react.production.min.js',
          global: 'React',
        },
        {
          module: 'react-dom',
          entry:
            'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
          global: 'ReactDOM',
        },
      ],
    }),
  ],
  optimization: {
    // 提取公共包
    splitChunks: {
      minSize: 0,
      cacheGroups: {
        commons: {
          // test: /(react|react-dom)/,
          // name: "vendors",
          // chunks: "all",
          name: 'commons',
          chunks: 'all',
          minChunks: 2,
        },
      },
    },
  },
};

module.exports = merge(baseConfig, prodConfig);

  1. webpack.ssr.js
const merge = require('webpack-merge');

const OptimizeCss = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackExternalPlugin = require('html-webpack-externals-plugin');
const cssnano = require('cssnano');
const baseConfig = require('./webpack.base');

const prodConfig = {
  mode: 'production',
  module: {
    rules: [
      // 服务端样式不做处理
      {
        test: /\.css$/,
        use: 'ignore-loader',
      },
      {
        test: /\.less$/,
        use: 'ignore-loader',
      },
    ],
  },
  plugins: [
    new OptimizeCss({
      // 代码压缩
      assetNameRegExp: /\.css$/g,
      cssProcessor: cssnano,
    }),
    new HtmlWebpackExternalPlugin({
      // 提取公告资源包
      externals: [
        {
          module: 'react',
          entry: 'https://unpkg.com/react@16/umd/react.production.min.js',
          global: 'React',
        },
        {
          module: 'react-dom',
          entry:
            'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
          global: 'ReactDOM',
        },
      ],
    }),
  ],
  optimization: {
    // 提取公共包
    splitChunks: {
      minSize: 0,
      cacheGroups: {
        commons: {
          // test: /(react|react-dom)/,
          // name: "vendors",
          // chunks: "all",
          name: 'commons',
          chunks: 'all',
          minChunks: 2,
        },
      },
    },
  },
};

module.exports = merge(baseConfig, prodConfig);

这里使用到的 merge 做合并使用;

详情可了解:www.npmjs.com/package/web…

3、测试用例

  • test 冒烟测试

    我也是第一次接触这个东西,感觉还挺有意识地

// 使用node 执行这个文件 会展示出相应的结果
// 个人也只是了解 不过多解释有想深入了解请下载源码
// 使用到的工具 mocha: https://mochajs.cn/
const path = require("path");
const webpack = require("webpack");
const rimraf = require("rimraf");

const Mocha = require("mocha");

const mocha = new Mocha();

process.chdir(path.join(__dirname, "template"));

rimraf("./dist", () => {
  const prodConfig = require("../../lib/webpack.prod.js");

  webpack(prodConfig, (err, stats) => {
    if (err) {
      console.error(err);
      process.exit(2);
    }
    console.log(
      stats.toString({
        colors: true,
        modules: false,
        children: false,
      })
    );
    mocha.addFile(path.join(__dirname, "html-test.js"));
    mocha.addFile(path.join(__dirname, "css-js-test.js"));

    mocha.run();
  });
});

  • unit单元测试
const assert =require('assert');

describe('webpack.base.js test case', ()=>{
    const baseConfig =require('../../lib/webpack.base')
    console.log(baseConfig)
    it('entry',()=>{
      assert.equal(baseConfig.entry.index,'E:/webpackStudy/webpack02/build-webpack/test/smoke/template/src/index/index.js')
      assert.equal(baseConfig.entry.search,'E:/webpackStudy/webpack02/build-webpack/test/smoke/template/src/search/index.js')
    })
})

4、eslint

module.exports = {
  "parser": "babel-eslint",
  "extends": "airbnb-base",
  // "rules": {
  //     "semi": "error"
  // },
  "env": {
    "browser": true,
    "node": true
  }
}

根据上述webpack配置,运行eslint时可抛出相应的错误,对照一一修改即可。 对于这些内容我也是练手,有想讨论的欢迎评论,希望大家多多支持!!!

github地址:github.com/838216870/w…