Webpack入门:常用loader和plugin配置

环境准备

node -v
v16.14.0
# 初始化项目
npm init -y
# 安装依赖 npm cnpm yarn pnpm 均可
npm i -D webpack webpack-cli

使用默认配置打包

输入 src/index.js

console.log('Hello World!')

使用默认配置打包

npx webpack

输出 dist/main.js

console.log("Hello World!");

使用配置文件 webpack.config.js

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
};

css样式文件处理

依赖

npm i -D style-loader css-loader

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  // 增加以下配置
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

css预处理-less

依赖

npm install -D less less-loader

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      // 处理css
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      // 处理less
      {
        test: /\.less$/i,
        loader: ["style-loader", "css-loader", "less-loader"],
      },
    ],
  },
};

css兼容性处理

依赖

npm install -D postcss-loader postcss postcss-preset-env

webpack.config.js

const path = require("path");
// css处理公共loader
const commonCssLoaders = [
  "style-loader",
  "css-loader",
  {
    loader: "postcss-loader",
    options: {
      postcssOptions: {
        plugins: [["postcss-preset-env"]],
      },
    },
  },
];
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      // 处理css
      {
        test: /\.css$/i,
        use: commonCssLoaders,
      },
      // 处理less
      {
        test: /\.less$/i,
        use: [...commonCssLoaders, "less-loader"],
      },
    ],
  },
};

css代码提取

依赖

npm install --save-dev mini-css-extract-plugin

webpack.config.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// css处理公共loader
const commonCssLoaders = [
  // "style-loader",
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    loader: "postcss-loader",
    options: {
      postcssOptions: {
        plugins: [["postcss-preset-env"]],
      },
    },
  },
];
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  plugins: [
    // 将 CSS 提取到单独的文件中
    new MiniCssExtractPlugin(),
  ],
  module: {
    rules: [
      // 处理css
      {
        test: /\.css$/i,
        use: commonCssLoaders,
      },
      // 处理less
      {
        test: /\.less$/i,
        use: [...commonCssLoaders, "less-loader"],
      },
    ],
  },
};

css代码压缩

依赖

npm install css-minimizer-webpack-plugin --save-dev

webpack.config.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// css处理公共loader
const commonCssLoaders = [
  // "style-loader",
  MiniCssExtractPlugin.loader,
  "css-loader",
  // css兼容性处理
  {
    loader: "postcss-loader",
    options: {
      postcssOptions: {
        plugins: [["postcss-preset-env"]],
      },
    },
  },
];
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  plugins: [
    // 将 CSS 提取到单独的文件中
    new MiniCssExtractPlugin(),
  ],
  module: {
    rules: [
      // 处理css
      {
        test: /\.css$/i,
        use: commonCssLoaders,
      },
      // 处理less
      {
        test: /\.less$/i,
        use: [...commonCssLoaders, "less-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // 使用 cssnano 优化和压缩 CSS
      new CssMinimizerPlugin(),
    ],
  },
};

js代码转译 babel

依赖

npm install -D babel-loader @babel/core @babel/preset-env

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
};

js代码压缩

npm install --save-dev terser-webpack-plugin

webpack.config.js

const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
  optimization: {
    minimize: true,
    minimizer: [
        // 使用 terser 来压缩 JavaScript
        new TerserPlugin()
    ],
  },
};

html模板

依赖

npm install --save-dev html-webpack-plugin

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "./dist"),
  },
  plugins: [
    // 生成一个 HTML5 文件, 引入所有 webpack 生成的 bundle
    new HtmlWebpackPlugin(),
  ],
};

开发服务器

依赖

pnpm i -D webpack-dev-server

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "./dist"),
  },
  devServer: {
    // 打开浏览器
    open: true,
    // 提供静态文件
    static: "./public",
  },
};

运行开发服务器

浏览器缓存

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "[name].[contenthash:6].js",
    path: path.resolve(__dirname, "./dist"),
    clean: true, // 在生成文件之前清空 output 目录
  },
};

路径别名

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "[name].[contenthash:6].js",
    path: path.resolve(__dirname, "./dist"),
    clean: true, // 在生成文件之前清空 output 目录
  },
  // 设置路径别名
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
};

打包分析

依赖

webpack.config.js

const path = require("path");
const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "[name].[contenthash:6].js",
    path: path.resolve(__dirname, "./dist"),
    clean: true, // 在生成文件之前清空 output 目录
  },
  plugins: [new BundleAnalyzerPlugin()],
};

使用CDN

webpack.config.js

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "[name].[contenthash:6].js",
    path: path.resolve(__dirname, "./dist"),
    clean: true, // 在生成文件之前清空 output 目录
  },
  // 外部加载
  externals: {
    vue: "Vue",
  },
};

输出 manifest

依赖

webpack.config.js

const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
module.exports = {
  ...
  plugins: [
    new WebpackManifestPlugin()
  ]
};

完整配置

package.json
{
  "scripts": {
    "build": "cross-env NODE_ENV=production  webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.js"
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "babel-loader": "^8.2.5",
    "cross-env": "^7.0.3",
    "css-loader": "^6.7.1",
    "css-minimizer-webpack-plugin": "^4.0.0",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.3",
    "less-loader": "^11.0.0",
    "mini-css-extract-plugin": "^2.6.1",
    "postcss": "^8.4.16",
    "postcss-loader": "^7.0.1",
    "postcss-preset-env": "^7.8.0",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.5",
    "webpack": "^5.74.0",
    "webpack-bundle-analyzer": "^4.6.0",
    "webpack-cli": "^4.10.0",
    "webpack-manifest-plugin": "^5.0.0",
    "webpack-nano": "^1.1.1"
  }
}

webpack.config.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
// css处理公共loader
const commonCssLoaders = [
  // "style-loader",
  MiniCssExtractPlugin.loader,
  "css-loader",
  // css兼容性处理
  {
    loader: "postcss-loader",
    options: {
      postcssOptions: {
        plugins: [["postcss-preset-env"]],
      },
    },
  },
];
module.exports = {
  mode: process.env.NODE_ENV,
  entry: "./src/index.js",
  output: {
    filename: "[name].[contenthash:6].js",
    path: path.resolve(__dirname, "dist"),
    clean: true, // 在生成文件之前清空 output 目录
  },
  devServer: {
    // 打开浏览器
    open: true,
    // 提供静态文件
    static: "./public",
  },
  // 设置路径别名
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
  // 外部加载
  externals: {
    vue: "Vue",
  },
  module: {
    rules: [
      // 处理css
      {
        test: /\.css$/i,
        use: commonCssLoaders,
      },
      // 处理less
      {
        test: /\.less$/i,
        use: [...commonCssLoaders, "less-loader"],
      },
      // 处理图片资源
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset/resource",
      },
      // 处理js
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
  optimization: {
    minimize: true,
    minimizer: [
      // 使用 cssnano 优化和压缩 CSS
      new CssMinimizerPlugin(),
      // 使用 terser 来压缩 JavaScript
      new TerserPlugin(),
    ],
  },
  plugins: [
    // 生成一个 HTML5 文件, 引入所有 webpack 生成的 bundle
    new HtmlWebpackPlugin(),
    // 将 CSS 提取到单独的文件中
    new MiniCssExtractPlugin(),
    // 依赖分析
    // new BundleAnalyzerPlugin(),
    // manifest
    new WebpackManifestPlugin(),
  ],
};