zoukankan      html  css  js  c++  java
  • 前端开发 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",
    
  • 相关阅读:
    NYOJ 10 skiing DFS+DP
    51nod 1270 数组的最大代价
    HDU 4635 Strongly connected
    HDU 4612 Warm up
    POJ 3177 Redundant Paths
    HDU 1629 迷宫城堡
    uva 796
    uva 315
    POJ 3180 The Cow Prom
    POJ 1236 Network of Schools
  • 原文地址:https://www.cnblogs.com/ssaylo/p/13710172.html
Copyright © 2011-2022 走看看