【webpack4】不依赖cli,从零开始构建webpack配置

在年轻的时候选择站在巨人的肩膀上(感谢巨人们的cli服务,配置从简)。
在不断的学习中,向着巨人方向前进。
本次搭建并未引入其他前端框架loader,可自行引入配置需要运用的框架loader.
webpack-cli-demo

webpack.base.config.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const package = require('../package.json');
const config = require('./config');
const utils = require('./utils')


module.exports = (env, argv) => {
  // 是否为开发环境
  const IS_NODE_PROD = argv.mode === "production";
  // BASE_CONFIG 公用配置
  const BASE_CONFIG = {
    entry: {
      app: "./src/main.js"
    },
    output: {
      filename: IS_NODE_PROD ? utils.assetsPath("js/[name].[chunkhash:8].js") : utils.assetsPath("js/[name].js"),
      chunkFilename: IS_NODE_PROD ? utils.assetsPath("js/[name].[chunkhash:8].js") : utils.assetsPath("js/[id].js"),
      path: config.outputPath
    },
    optimization: {
      // 提取runtimeChunk
      runtimeChunk: 'single',
      splitChunks: {
        cacheGroups: {
          // 提取vendor长效缓存
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            filename: utils.assetsPath("js/vendors.[contenthash:8].js"),
            chunks: 'all'
          }
        }
      }
    },
    module: {
      rules: [{
          test: /\.js(x)?$/,
          loader: 'babel-loader',
          exclude: /node_modules/
        },
        {
          test: /\.css$/,
          use: [{
              loader: IS_NODE_PROD ? MiniCssExtractPlugin.loader + '?publicPath=' + config.minicssPublicPath : "style-loader"
            },
            {
              loader: "css-loader"
            },
            {
              loader: "postcss-loader",
              options: {
                plugins: [
                  require('autoprefixer')(package.postcss.plugins.autoprefixer), // 自动添加浏览器前缀
                  require('cssnano')(), // 合并相同css
                ]
              }
            }
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [{
              loader: "url-loader",
              options: {
                limit: 50000, //表示低于50000字节(50K)的图片会以 base64编码
                outputPath: utils.assetsPath("img"), // 输出的路径
                name: IS_NODE_PROD ? "[name].[hash:8].[ext]" : "[name].[ext]", // 输出的文件名
              }
            },
            { // 图片压缩(保真) https://www.npmjs.com/package/image-webpack-loader#libpng-issues
              loader: 'image-webpack-loader',
              options: {
                bypassOnDebug: true, // webpack@1.x
                disable: true, // webpack@2.x and newer
              }
            },
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [{
            loader: "file-loader",
            options: {
              outputPath: utils.assetsPath("fonts"), // 输出的路径
              name: IS_NODE_PROD ? "[name].[hash:8].[ext]" : "[name].[ext]" // 输出的文件名
            }
          }]
        }
      ]
    },
    resolve: {
      alias: {
        "@": path.resolve(__dirname, '../src')
      }
    }
  }

  return BASE_CONFIG;
}

webpack.dev.config.js

const path = require("path");
// 合并插件
const merge = require('webpack-merge');
// 构建文件index输出插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 处理webpack提示信息输出
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// 控制台错误提示处理
const notifier = require('node-notifier');
// 控制台颜色输出
const colors = require('colors');
// 配置参数
const config = require('./config');
// webpack构建方法
const utils = require('./utils')
// 公用配置文件
const BASE_CONFIG = require('./webpack.base.config');

module.exports = (env, argv) => {

  const DEVELOPMENT_CONFIG = {
    mode: "development",
    optimization: {
      nodeEnv: 'development', // 设置process.env.NODE_ENV
    },
    plugins: [
      // 输出index.html配置
      new HtmlWebpackPlugin({
        filename: "index.html",
        template: "./public/index.html",
        inject: true
      }),
      // 处理webpack提示信息输出
      new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [
            `You application is running here ${colors.cyan('http://localhost:'+ (config.devServer.port || 8080))}`
          ],
          notes: [`Or use the network to run ${colors.cyan('http://'+utils.getIPAdress()+':'+(config.devServer.port || 8080))}`]
        },
        onErrors: (severity, errors) => {
          if (severity !== 'error') {
            return;
          }
          const error = errors[0];
          notifier.notify({
            title: "Webpack error",
            message: severity + ': ' + error.name,
            subtitle: error.file || '',
            icon: ICON
          });
        }
      })
    ],
    devServer: Object.assign({
      open: true,
      historyApiFallback: true,
      hot: true,
      port: 8080,
      useLocalIp: true,
      clientLogLevel: 'warning',
      overlay: {
        warnings: true,
        errors: true
      },
      // 显示 webpack 构建进度
      progress: true,
      quiet: true,
    }, config.devServer, {
      host: '0.0.0.0' // 保持两种运行方法
    })
  };

  return merge(BASE_CONFIG(env, argv), DEVELOPMENT_CONFIG)
}

webpack.prod.config.js

const path = require('path');
// 合并插件
const merge = require('webpack-merge');
// 构建文件index输出插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 清除原文件插件
const CleanWebpackPlugin = require("clean-webpack-plugin");
// css分离插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// copy插件
const CopyPlugin = require('copy-webpack-plugin');
// serviceWorker插件
const WorkboxPlugin = require('workbox-webpack-plugin');
// 配置参数
const config = require('./config')
// webpack构建方法
const utils = require('./utils')
//  公用配置文件
const BASE_CONFIG = require('./webpack.base.config');

module.exports = (env, argv) => {

  const PRODUCTION_CONFIG = {
    mode: "production",
    optimization: {
      nodeEnv: 'production', // 设置process.env.NODE_ENV
    },
    plugins: [
      // 清除构建文件
      new CleanWebpackPlugin(),
      // 拷贝public静态文件
      new CopyPlugin([{
        from: './public',
        to: './'
      }]),
      // 输出index.html配置
      new HtmlWebpackPlugin({
        title: "webpack-app", // title(只有在使用默认模板时有效)
        filename: "index.html", // 模板名字
        template: "./public/index.html", // 模板路径(title无效)
        templateParameters: true, // 允许覆盖模板中使用的参数
        inject: 'head', // script插入位置
        favicon: "./public/favicon.ico", // 图标icon
        // chunks: ["index.js"], // script标签引入列表
        // excludeChunks: ["test.js"], // script标签不引入列表
        chunksSortMode: "auto", // script排序方式
        hash: false, // 给文件添加hash
        showErrors: false, // 错误详细信息
        cache: true, // 默认是true的,表示内容变化的时候生成一个新的文件。
        minify: { // 将html-minifier的选项作为对象来缩小输出
          removeAttributeQuotes: true, // 是否移除属性的引号
          removeComments: true, // 是否清理html的注释
          collapseWhitespace: true, // 是否清理html的空格、换行符
          minifyCSS: false, // 是否压缩html内的样式
          minifyJS: false, // 是否压缩js内的样式
          removeEmptyElements: false, // 是否清理内容为空的元素
          caseSensitive: false, // 是否区分大小写的方式处理自定义标签内的属性。
          removeRedundantAttributes: true,
          useShortDoctype: true,
          removeScriptTypeAttributes: true, // 是否去除script标签中的type属性
          removeStyleLinkTypeAttributes: true, // 是否去掉style和link标签的type属性。
        },
        xhtml: true, // 如果true将link标记渲染为自闭(兼容XHTML)
        // 插入meta标签
        meta: {
          Author: "Anles"
        },
      }),
      new MiniCssExtractPlugin({
        // 分离css
        filename: utils.assetsPath("css/[name].[contenthash:8].css"),
        chunkFilename: utils.assetsPath("css/[name].[contenthash:8].css"),
      }),
      // 添加serviceworker
      new WorkboxPlugin.GenerateSW({
        clientsClaim: true,
        skipWaiting: true
      })
    ],
    stats: {
      children: false // 关闭错误提示信息
    }
    // Entrypoint undefined = index.html https://github.com/jantimon/html-webpack-plugin/issues/895
  };
  // 合并输出
  return merge(BASE_CONFIG(env, argv), PRODUCTION_CONFIG)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值