Webpack

Webpack

_

一、Webpack是什么?

Webpack 是一个静态模块打包工具,它把项目中的所有资源(JS、CSS、图片、字体等)都当成 "模块",然后根据依赖关系打包成浏览器能运行的静态文件。

二、Webpack解决了什么问题?

2.1 原始时代的痛点

<!-- 手动管理多个脚本 -->
<script src="jquery.js"></script>
<script src="utils.js"></script>
<script src="app.js"></script>

痛点:

  • 多个JS文件,HTTP请求多,加载慢
  • 依赖顺序必须手动控制
  • 浏览器不认识ES Module、TypeScript、Sass
  • 代码没有压缩、混淆,暴露源码

2.2 Webpack的解决方案

开发时(多个文件) → Webpack打包 → 生产环境(少量文件)

src/
├── index.js
├── utils.js
├── style.css
└── logo.png
        ↓
  Webpack打包
        ↓
dist/
├── bundle.js        # 所有JS合并、压缩
├── bundle.css       # CSS提取、压缩
└── logo.[hash].png  # 图片重命名、优化

好处:

  • 所有资源统一管理
  • 自动处理依赖关系
  • 代码压缩、混淆、Tree Shaking
  • 支持各种预处理器(TypeScript、Sass、Less)
  • 开发时热更新(HMR)

三、Webpack的核心概念

Webpack 有5 个核心概念,搞懂它们就搞懂了 Webpack。

3.1 Entry(入口)

打包的起点,Webpack 从这个文件开始分析所有依赖。

// webpack.config.js
module.exports = {
  // 单入口(SPA应用)
  entry: './src/index.js',
  
  // 多入口(多页面应用)
  entry: {
    home: './src/home.js',
    about: './src/about.js'
  }
};

3.2 Output(输出)

打包后的文件输出位置和文件名。

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),    // 输出目录
    filename: 'bundle.[contenthash].js',      // 文件名(带hash缓存)
    clean: true                               // 打包前清空dist
  }
};

3.3 Loader(加载器)

将非 JS 文件转换为 JS 能识别的模块。Webpack 默认只认识 JS 和 JSON,其他文件需要用 Loader 处理。

module.exports = {
  module: {
    rules: [
      // CSS Loader
      {
        test: /\.css$/,                        // 匹配.css文件
        use: ['style-loader', 'css-loader']   // 从右到左执行
      },
      
      // TypeScript Loader
      {
        test: /\.ts$/,
        use: 'ts-loader'
      },
      
      // 图片Loader
      {
        test: /\.(png|jpg|gif)$/,
        type: 'asset/resource'                 // Webpack5内置
      }
    ]
  }
};

Loader 执行顺序:从右到左,从下到上

use: ['style-loader', 'css-loader', 'sass-loader']
// 执行顺序:sass-loader → css-loader → style-loader
// 1. sass-loader:Sass → CSS
// 2. css-loader:CSS → JS模块
// 3. style-loader:JS模块 → style标签插入HTML

3.4 Plugin(插件)

扩展 Webpack 功能,在打包的各个阶段做一些事情。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    // 自动生成HTML,并引入打包后的JS
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    
    // 提取CSS为单独文件(代替style-loader)
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css'
    })
  ]
};

3.5 Mode(模式)

module.exports = {
  mode: 'development',   // 开发模式:快,不压缩,有source-map
  // mode: 'production'  // 生产模式:慢,压缩,优化
};

四、完整的Webpack配置

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // 1. 入口
  entry: './src/index.js',
  
  // 2. 输出
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/[name].[contenthash].js',
    clean: true
  },
  
  // 3. 模式
  mode: 'development',
  
  // 4. 开发服务器
  devServer: {
    port: 3000,
    hot: true,
    open: true
  },
  
  // 5. Loaders
  module: {
    rules: [
      // CSS处理
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,  // 提取为CSS文件
          'css-loader'                  // CSS转JS
        ]
      },
      
      // Sass处理
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader'
        ]
      },
      
      // Babel处理(JS/JSX)
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      },
      
      // 图片处理
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name].[hash:8][ext]'
        }
      },
      
      // 字体处理
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash:8][ext]'
        }
      }
    ]
  },
  
  // 6. Plugins
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: 'index.html'
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css'
    })
  ],
  
  // 7. 解析配置
  resolve: {
    extensions: ['.js', '.jsx', '.json'],  // 导入时可省略扩展名
    alias: {
      '@': path.resolve(__dirname, 'src')  // 路径别名
    }
  },
  
  // 8. 优化(生产模式启用)
  optimization: {
    splitChunks: {
      chunks: 'all',  // 提取公共依赖
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
};

五、开发 vs 生产环境配置

实际项目中通常区分开发和生产配置。

// webpack.common.js(公共配置)
module.exports = {
  entry: './src/index.js',
  output: { /* ... */ },
  module: { /* 基础loaders */ },
  plugins: { /* 基础plugins */ }
};

// webpack.dev.js(开发配置)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',  // 快速source-map
  devServer: {
    hot: true,
    port: 3000
  }
});

// webpack.prod.js(生产配置)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map',  // 完整source-map
  optimization: {
    minimize: true,       // 压缩代码
    splitChunks: { /* 分割代码 */ }
  }
});
// package.json
{
  "scripts": {
    "dev": "webpack serve --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  }
}

六、Webpack的核心工作流程

1. 读取配置(webpack.config.js)
   ↓
2. 从 Entry 开始解析
   ↓
3. 遇到 import/require,递归分析所有依赖
   ↓
4. 根据文件的扩展名,匹配 Loader
   ↓
5. Loader 转换文件内容(Sass → CSS,TS → JS)
   ↓
6. 应用 Plugin 做额外处理(压缩、提取、生成HTML)
   ↓
7. 输出打包结果到 Output 目录

七、常用Loader和Plugin速查

7.1 常用Loader

Loader作用
babel-loader转换ES6+、JSX
css-loader处理CSS中的@import和url()
style-loader把CSS注入HTML的<style>标签
sass-loaderSass → CSS
less-loaderLess → CSS
postcss-loaderCSS后处理(autoprefixer等)
ts-loaderTypeScript → JavaScript
vue-loader解析.vue文件
file-loader处理文件,输出到目录
url-loader小文件转Base64

7.2 常用Plugin

Plugin作用
HtmlWebpackPlugin生成HTML,自动注入JS/CSS
MiniCssExtractPlugin提取CSS为单独文件
CleanWebpackPlugin打包前清空输出目录
DefinePlugin定义全局常量(环境变量)
CopyWebpackPlugin复制静态文件
CompressionWebpackPluginGzip压缩
BundleAnalyzerPlugin分析打包体积

八、工程化中的最佳实践

8.1 Tree Shaking(去掉无用代码)

// package.json
{
  "sideEffects": false  // 所有代码无副作用,可安全Tree Shaking
}

// 或指定文件有副作用
{
  "sideEffects": ["*.css", "*.scss"]
}

8.2 代码分割(Code Splitting)

// 动态导入(按需加载)
import('./module.js').then(module => {
  // 使用模块
});

// 提取第三方库
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        priority: 10
      }
    }
  }
}

8.3 缓存优化

output: {
  filename: '[name].[contenthash].js'  // 内容变化时hash变化
}

8.4 环境变量注入

// webpack.config.js
const webpack = require('webpack');

plugins: [
  new webpack.DefinePlugin({
    'process.env.API_URL': JSON.stringify('https://api.example.com'),
    'process.env.NODE_ENV': JSON.stringify('production')
  })
]

// 代码中使用
console.log(process.env.API_URL); // https://api.example.com

九、总结

  1. Webpack是打包工具:把所有资源当模块,根据依赖关系打包
  2. Loader转换文件:非JS文件转成JS能识别的格式
  3. Plugin扩展功能:在打包生命周期中做各种事情

Webpack 的核心公式:

Entry + Loader + Plugin + Output = Bundle
NPM 2026-08-24
TypeScript入门 2026-08-28

© 2026 日志记录