前端工程化-重新学习-20260407

4 阅读6分钟

前端工程化

Webpack 基础

Webpack 作用、核心概念与工具对比

包含的题目:

  1. Webpack 的作用是什么?(高频考点)
  2. Webpack 的核心概念有哪些?(高频考点)
  3. Webpack 与 Vite 的区别是什么?(高频考点)
  4. Webpack 与 Rollup 的区别是什么?

详细答案:

Webpack 作用

  • 模块打包:将多个模块打包成静态资源
  • 代码转换:通过 Loader 处理各种文件类型
  • 代码优化:压缩、分割、Tree Shaking 等
  • 开发支持:开发服务器、热更新、Source Map

核心概念

  • Entry:入口起点
  • Output:输出配置
  • Loader:文件转换器
  • Plugin:扩展插件
  • Mode:开发/生产模式
  • Module:项目中的每个文件
  • Chunk:代码块
  • Bundle:最终输出文件

配置文件示例

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' },
      { test: /\.css$/, use: ['style-loader', 'css-loader'] },
    ],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  mode: 'development',
};

工具对比

工具特点适用场景
Webpack功能全面,生态成熟大型复杂项目
Vite启动快,开发体验好现代前端项目
Rollup打包效率高,Tree Shaking 好库/组件开发

Webpack 核心概念详解

Entry、Output、Loader、Plugin

包含的题目: 5-18. Entry、Output、Loader、Plugin、Mode 相关题目

详细答案:

Entry 配置

// 单入口
entry: './src/index.js'

// 多入口
entry: {
  main: './src/index.js',
  vendor: './src/vendor.js',
}

Output 配置

output: {
  path: path.resolve(__dirname, 'dist'),
  filename: '[name].[contenthash].js',
  publicPath: '/',
  clean: true,
}

Loader 配置

rules: [
  // JavaScript
  { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' },
  
  // CSS
  { test: /\.css$/, use: ['style-loader', 'css-loader'] },
  
  // 图片
  { test: /\.(png|jpg|jpeg|gif|svg)$/, type: 'asset/resource' },
  
  // 字体
  { test: /\.(woff|woff2|eot|ttf|otf)$/, type: 'asset/resource' },
]

常用 Loader

  • babel-loader:ES6+ 转换
  • css-loader/style-loader:CSS 处理
  • sass-loader/less-loader:预处理器
  • file-loader/url-loader:文件处理
  • vue-loader:Vue 单文件组件

Plugin 配置

plugins: [
  new HtmlWebpackPlugin({ template: './src/index.html' }),
  new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
  new CleanWebpackPlugin(),
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify('production'),
  }),
]

常用 Plugin

  • HtmlWebpackPlugin:生成 HTML
  • MiniCssExtractPlugin:提取 CSS
  • CleanWebpackPlugin:清理输出目录
  • DefinePlugin:定义环境变量
  • HotModuleReplacementPlugin:热更新

Webpack Loader 与 Plugin 原理

包含的题目: 23-41. Loader 与 Plugin 原理相关题目

详细答案:

Loader 原理

  • 函数式处理,接收源文件内容,返回处理结果
  • 链式调用:从右到左执行
  • 可以同步或异步

自定义 Loader 示例

module.exports = function(source) {
  // 处理逻辑
  const result = source.replace(/console\.log\(.*?\);/g, '');
  return result;
};

Plugin 原理

  • 基于 Tapable 事件流机制
  • 通过 apply 方法注册到 Webpack 生命周期
  • 可以访问整个编译过程

自定义 Plugin 示例

class MyPlugin {
  apply(compiler) {
    compiler.hooks.done.tap('MyPlugin', (stats) => {
      console.log('编译完成');
    });
  }
}

Webpack 生命周期钩子

  • environment:环境准备
  • compile:开始编译
  • make:构建模块
  • emit:输出资源
  • done:完成构建

Webpack 构建流程

包含的题目: 42-48. 构建流程相关题目

详细答案:

Webpack 构建流程

  1. 初始化:合并配置,创建 Compiler 实例
  2. 编译:从 Entry 开始递归解析依赖
  3. 构建:调用 Loader 转换模块
  4. 生成:创建 Chunk,构建依赖图
  5. 输出:将资源写入文件系统

Tapable 事件流

// Webpack 核心事件机制
compiler.hooks.compile.tap('Plugin', () => {
  console.log('开始编译');
});

Compiler vs Compilation

  • Compiler:编译器实例,包含完整配置
  • Compilation:单次构建上下文,包含本次构建信息

Webpack 优化

包含的题目: 49-64. 性能优化相关题目(高频考点)

详细答案:

构建速度优化

// 1. 缩小搜索范围
resolve: {
  extensions: ['.js', '.jsx'],
  modules: [path.resolve(__dirname, 'node_modules')],
}

// 2. 使用缓存
cache: { type: 'filesystem' }

// 3. 多进程构建
use: ['thread-loader', 'babel-loader']

// 4. DllPlugin 预编译
new webpack.DllPlugin({ /* 配置 */ })

打包体积优化

// 1. 代码压缩
optimization: {
  minimize: true,
  minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
}

// 2. 代码分割
splitChunks: {
  chunks: 'all',
  cacheGroups: {
    vendors: { test: /[\\/]node_modules[\\/]/, name: 'vendors' },
  },
}

// 3. 按需加载
import(/* webpackChunkName: "lazy" */ './lazy-module')

Tree Shaking 原理

  • 基于 ES6 模块的静态分析
  • 移除未使用的代码
  • 需要满足条件:
    • 使用 ES6 模块语法
    • 生产模式自动开启
    • package.json 中配置 sideEffects

Scope Hoisting

  • 将多个模块合并到一个函数作用域
  • 减少函数声明和闭包
  • 提升运行速度

懒加载实现

// React 懒加载
const LazyComponent = React.lazy(() => import('./LazyComponent'));

// 使用 Suspense
<Suspense fallback={<div>加载中...</div>}>
  <LazyComponent />
</Suspense>

缓存优化策略

  • 文件名使用 contenthash
  • 提取第三方库到单独 chunk
  • 使用持久化缓存

Webpack 开发环境

包含的题目: 61-64. 开发环境配置相关题目

详细答案:

devServer 配置

devServer: {
  static: './public',
  compress: true,
  port: 3000,
  open: true,
  hot: true,
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
    },
  },
  historyApiFallback: true,
}

HMR 热更新原理

  1. 建立 WebSocket 连接
  2. 文件变化时重新编译
  3. 通过 WebSocket 发送更新
  4. 客户端替换模块
  5. 保持应用状态

source-map 类型

  • 开发环境eval-cheap-module-source-map
  • 生产环境source-maphidden-source-map

Vite 基础

包含的题目: 65-67. Vite 基础相关题目(高频考点)

详细答案:

Vite 核心特性

  • 闪电启动:基于原生 ES Modules
  • 即时热更新:HMR 速度快
  • 按需编译:只编译所需模块
  • 预构建:转换 CommonJS 模块
  • 框架支持:Vue、React、Svelte 等

Vite 优势

  • 开发体验好,启动快
  • 配置简单,开箱即用
  • 构建高效,生产使用 Rollup
  • 生态完善,插件丰富

Vite vs Webpack

对比项ViteWebpack
启动速度极快(< 1s)
热更新随项目增大变慢
配置简单复杂
生态中等非常成熟

Vite 原理

包含的题目: 68-73. Vite 原理相关题目(高频考点)

详细答案:

Vite 原理

  • 开发环境:原生 ES Modules + 按需编译
  • 生产环境:Rollup 打包

ES Modules 使用

<script type="module">
  import { hello } from './hello.js';
  hello('world');
</script>

开发服务器原理

  1. 浏览器请求模块
  2. Vite 拦截请求
  3. 按需编译后返回
  4. 缓存编译结果

预构建(Dependency Pre-bundling)

  • 扫描 CommonJS/UMD 模块
  • 使用 esbuild 转换为 ES Modules
  • 合并小模块,减少请求

HMR 热更新

if (import.meta.hot) {
  import.meta.hot.accept('./module.js', (newModule) => {
    newModule.render();
  });
}

生产构建

  • 使用 Rollup 打包
  • 代码分割、压缩、优化
  • 支持 Tree Shaking

Vite 配置

包含的题目: 74-76. Vite 配置相关题目

详细答案:

vite.config.js 基本配置

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  root: process.cwd(),
  base: '/',
  server: {
    host: 'localhost',
    port: 3000,
    proxy: { '/api': { target: 'http://localhost:8080' } },
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router'],
        },
      },
    },
  },
  resolve: {
    alias: { '@': path.resolve(__dirname, 'src') },
  },
});

环境变量使用

// .env 文件
VITE_API_URL=https://api.example.com

// 代码中访问
console.log(import.meta.env.VITE_API_URL);

Vite 插件

包含的题目: 77-81. Vite 插件相关题目

详细答案:

Vite 插件系统

  • 兼容 Rollup 插件
  • 提供丰富的生命周期钩子
  • 支持自定义插件

插件结构

export default function myPlugin() {
  return {
    name: 'my-plugin',
    config(config) {
      // 修改配置
      return config;
    },
    transform(code, id) {
      // 转换代码
      return code;
    },
  };
}

常用插件

  • @vitejs/plugin-vue:Vue 支持
  • @vitejs/plugin-react:React 支持
  • @vitejs/plugin-legacy:旧浏览器支持
  • vite-plugin-svg-icons:SVG 图标处理

常见问题与解决方案

包含的题目: 86-95. 常见问题相关题目

详细答案:

构建速度慢

  • 原因:项目过大,配置不当
  • 解决方案:
    1. 使用缓存(cache: { type: 'filesystem' })
    2. 多进程构建(thread-loader)
    3. 缩小文件搜索范围
    4. 使用 DllPlugin 预编译

打包体积大

  • 原因:未压缩,未分割,未 Tree Shaking
  • 解决方案:
    1. 代码压缩(TerserPlugin)
    2. 代码分割(splitChunks)
    3. 按需加载(import())
    4. 排除外部库(externals)

热更新失败

  • 原因:配置错误,模块不兼容
  • 解决方案:
    1. 检查 HMR 配置
    2. 确保模块支持 HMR
    3. 使用 module.hot.accept()

环境变量问题

  • 解决方案:
    1. 正确配置 DefinePlugin
    2. 使用 process.env 访问
    3. 区分开发/生产环境

版本升级

  • 步骤:
    1. 备份项目
    2. 查看官方迁移指南
    3. 逐步升级依赖
    4. 测试验证

以上是对前端工程化 95 道面试题目的综合解答,涵盖了 Webpack 和 Vite 的核心概念、配置、优化和常见问题。每个主题都包含了理论说明、配置示例和最佳实践建议。