前端面试准备指南六之前端工程化篇


一、模块化规范

1.1 模块化概述

前端模块化是将大型前端项目拆分为独立、可复用模块的标准化方法。它解决了以下问题:

  • 变量污染:避免全局变量冲突
  • 依赖管理:清晰管理模块间的依赖关系
  • 代码复用:提高代码的复用性和可维护性
  • 按需加载:支持动态加载,提升性能

模块化规范主要分为四种:CommonJS、AMD、CMD、ES Module。

1.2 CommonJS

定义:服务器端模块规范,由 Node.js 推广使用,Webpack 也采用这种规范。

核心特点

特性 说明
模块定义 每个文件就是一个模块,拥有独立作用域
模块标识 require() 方法的参数,支持小驼峰命名、相对路径、绝对路径
模块引用 require() 同步加载模块
模块导出 使用 module.exportsexports 向外暴露接口

示例

// 导出模块
// utils.js
const sum = (a, b) => a + b;
module.exports = { sum };

// 导入模块
// app.js
const { sum } = require("./utils");
console.log(sum(1, 2)); // 3

优缺点

优点 缺点
解决变量污染问题 同步加载,不适合浏览器环境
模块定义简单、接口简洁 没有并行加载机制
支持引入和导出,便于依赖管理 浏览器端需要从服务器加载,可能导致假死

1.3 AMD(Asynchronous Module Definition)

定义:浏览器端异步模块定义规范,由 RequireJS 推广。

核心特点

  • 依赖前置:定义模块时声明所有依赖
  • 异步加载:不会阻塞浏览器渲染

示例

// 定义模块
define(["jquery"], function ($) {
    return {
        init: function () {
            $("body").css("background", "red");
        },
    };
});

// 加载模块
require(["./module"], function (module) {
    module.init();
});

优缺点

优点 缺点
用户体验好,无延迟 依赖前置可能加载未使用的模块
异步加载不阻塞页面 代码书写复杂

1.4 CMD(Common Module Definition)

定义:通用模块定义规范,由 SeaJS 推广。

核心特点

  • 依赖就近:用到时才 require
  • 按需加载:性能更好

示例

// 定义模块
define(function (require, exports, module) {
    // 依赖就近声明
    const $ = require("jquery");

    exports.init = function () {
        $("body").css("background", "red");
    };
});

优缺点

优点 缺点
性能好,按需加载 依赖分析复杂
代码书写自然 生态不如 AMD

1.5 ES Module

定义:ES6 官方模块化规范,现已成为前端主流。

核心特点

特性 说明
静态导入 import 语句在编译时执行
动态导入 import() 返回 Promise,支持按需加载
模块导出 export 导出,export default 默认导出
严格模式 模块自动运行在严格模式下

示例

// 导出模块
// utils.js
export const sum = (a, b) => a + b;
export default function () {
    console.log("default export");
}

// 导入模块
// app.js
import defaultFn, { sum } from "./utils";
defaultFn(); // 'default export'
console.log(sum(1, 2)); // 3

// 动态导入
import("./utils").then(({ sum }) => {
    console.log(sum(1, 2));
});

优缺点

优点 缺点
官方标准,语法简洁 旧浏览器不支持,需要编译
静态分析,支持 Tree Shaking 动态导入需要 Promise 支持
支持循环引用 模块路径必须完整

1.6 四种规范对比

特性 CommonJS AMD CMD ES Module
加载方式 同步 异步 异步 静态(编译时)
依赖声明 动态 前置 就近 静态
适用环境 服务器端 浏览器端 浏览器端 通用
支持循环引用
Tree Shaking 不支持 不支持 不支持 支持
模块路径完整性 必须完整 必须完整 必须完整 必须完整

二、Webpack 构建工具

2.1 Webpack 打包原理

核心概念

  1. 依赖分析:递归构建依赖关系图
  2. 模块转换:通过 Loader 转换不同类型文件
  3. 代码优化:压缩、去重、Tree Shaking
  4. 资源输出:生成静态资源 bundle

打包流程

入口文件 → 依赖分析 → 模块转换(Loader) → 代码优化(Plugin) → 输出bundle

webpack 打包原理是根据文件间的依赖关系对其进行静态分析,将这些模块按指定规则生成静态资源。当 webpack 处理程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,将所有这些模块打包成一个或多个 bundle。

webpack 有两种组织模块的依赖方式:同步、异步。异步依赖将作为分割点,形成一个新的块;在优化了依赖树之后,每一个异步区块都将作为一个文件被打包。

webpack 有一个智能解析器,几乎可以处理任何第三方库。无论它们的模块形式是 CommonJS、AMD 还是普通的 JS 文件;甚至在加载依赖的时候,允许使用动态表 require("/templates/"+name+".jade")

2.2 Webpack 配置结构

模块组成:import、export、require

module.exports = {
    mode: "development", // 模式:development | production
    entry: "./src/index.js", // 入口
    output: {
        // 输出
        filename: "bundle.js",
        path: "./dist",
    },
    module: {
        rules: [
            // Loader 配置
            { test: /\.js$/, use: "babel-loader" },
            { test: /\.css$/, use: ["style-loader", "css-loader"] },
        ],
    },
    plugins: [
        // Plugin 配置
        new HtmlWebpackPlugin(),
    ],
};

webpack4.0优化点详解

零配置模式

  • Webpack 4.0 带来了零配置体验,无需手动编写复杂的 webpack.config.js
  • 默认入口:./src/index.js
  • 默认输出:./dist/main.js
  • 默认模式:根据环境自动选择 development 或 production

SplitChunksPlugin

  • 内置代码分割插件,无需额外安装
  • 替代了 Webpack 3.x 中的 CommonsChunkPlugin
  • 自动提取多个 chunk 中的公共代码
  • 支持按需加载优化

Mode 模式

  • development 模式:开发环境优化,保留调试信息
  • production 模式:生产环境优化,自动启用代码压缩、Tree Shaking 等
  • 只需设置 mode: 'production'mode: 'development'

Tree Shaking

  • 生产模式下自动开启
  • 通过静态分析移除未使用的代码
  • 要求使用 ES Module 语法(import/export)
  • 需要设置 sideEffects: false 配合

缓存优化

  • cache-loader:缓存 loader 的编译结果,加速二次构建
  • hard-source-webpack-plugin:缓存模块解析结果

多线程打包

  • thread-loader:将耗时的 loader 分配到 worker 池中执行
  • happyPack:多进程并行处理文件
  • 显著加速大型项目的构建速度

2.3 常用 Loader

Loader 定义:是一个导出为函数的 javascript 模块,根据 rule 匹配文件扩展名,处理文件的转换器。

Loader 作用 使用场景
babel-loader ES6+ES5 处理 JavaScript
css-loader 加载 CSS,支持模块化、压缩、文件导入等特性 处理 CSS
style-loader CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS 开发环境快速预览
sass-loader SCSS/SASSCSS 处理预处理器
file-loader 把文件输出到指定目录,在代码中通过相对 URL 去引用输出的文件 处理图片、字体
url-loader 设置一个阈值,小于阈值时把文件 base64 编码,大于阈值时交给 file-loader 处理 优化小资源加载
postcss-loader 扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀 自动补全前缀
image-loader 加载并且压缩图片文件 优化图片
eslint-loader 通过 ESLint 检查 JavaScript 代码 代码检查

2.4 常用 Plugin

Plugin 定义:本质是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

Plugin 作用 使用场景
html-webpack-plugin 简化 HTML 文件创建 (依赖于 html-loader) 自动引入 bundle
mini-css-extract-plugin 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代 extract-text-webpack-plugin) 生产环境分离样式
terser-webpack-plugin 压缩 JavaScript 生产环境优化
clean-webpack-plugin 清空输出目录 构建前清理
split-chunks-plugin 代码分割 提取公共代码(Webpack 4 内置)
uglifyjs-webpack-plugin 压缩 JavaScript 文件 代码压缩
optimize-css-assets-webpack-plugin 压缩 CSS 文件 CSS 优化

2.5 Loader vs Plugin 对比

对比维度 Loader Plugin
配置位置 module.rules plugins
作用对象 单个文件 整个构建过程
执行时机 模块解析阶段 构建的各个阶段
实现方式 导出函数 类实例
  • Loadermodule.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loaderoptions (参数)等属性。
  • Pluginplugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。

2.6 代码分离策略

代码分离:将代码分割成多个 bundle,按需加载,提升首屏性能。

分离方式 说明 配置方式
入口起点 手动配置多个入口 entry: { main: './src/main.js' }
防止重复 使用 SplitChunksPlugin 去重和分离 chunk splitChunks: { chunks: 'all' }
动态导入 运行时按需加载 import('./module')
第三方库分离 单独打包第三方依赖 splitChunks.cacheGroups.vendor

webpack如何实现代码分离

  • 入口起点:使用 entry 配置手动地分离代码
  • 防止重复:使用 SplitChunksPlugin 去重和分离 chunk(Webpack 4 内置)
  • 动态导入:通过模块的内联函数调用来分离代码

示例:动态导入

// 路由懒加载
const Home = () => import("./Home.vue");
const About = () => import("./About.vue");

const routes = [
    { path: "/", component: Home },
    { path: "/about", component: About },
];

2.7 Webpack 性能优化策略

构建优化

  • 缓存策略:使用 cache-loaderhard-source-webpack-plugin

  • 并行构建thread-loaderhappyPack

  • 减少解析include / exclude 限制解析范围

  • CDN 引入:将第三方库通过 CDN 引入,不打包

  • 代码分割

    • 入口起点分割:多个入口文件
    • 公共代码分割:提取重复代码
    • 动态导入:按需加载模块
    • 第三方库分割:单独打包第三方依赖
  • Tree Shaking

    • 启用 production 模式
    • 使用 ES6 模块语法
    • 避免副作用
    • 配置 sideEffects
  • 懒加载

    • 路由懒加载:import()动态导入
    • 组件懒加载:需要时再加载
    • 图片懒加载:滚动到可视区域再加载
  • 缓存配置

    • 文件名哈希:[contenthash]
    • 长期缓存:分离runtime chunk
    • 缓存loader结果:cacheDirectory
    • 模块标识符:ModuleScopePlugin

Babel优化

  • 避免不必要的转译:使用 includeexclude 配置,不转译 node_modules 中的 js 文件
  • 缓存转译结果:设置 loader: 'babel-loader?cacheDirectory=true',减少重复转译
  • 使用 @babel/preset-env:按需转译
  • 启用 core-js:按需导入 polyfill

插件优化

  • 使用HtmlWebpackPlugin:自动生成HTML
  • 使用MiniCssExtractPlugin:提取CSS到独立文件,减少HTML大小
  • 使用OptimizeCssAssetsPlugin:压缩CSS文件
  • 使用TerserWebpackPlugin:压缩JS文件

输出优化

  • 代码压缩:TerserPlugin 压缩 JS,CSSMinimizerPlugin 压缩 CSS
  • Tree Shaking:确保使用 ES Module,开启 sideEffects: false
  • 代码分割:提取公共代码、按需加载
  • 资源优化:图片压缩、Base64 内联小资源

图片优化

  • 压缩图片
    • 使用工具:TinyPNG、ImageOptim
    • Webpack插件:image-webpack-loader
    • 保持合理的质量:70-80%
  • 使用适当的图片格式
    • JPEG:适合照片等复杂图像
    • PNG:适合图标、透明图像
    • WebP:现代浏览器支持,更小体积
    • SVG:适合图标、矢量图形
    • AVIF:新一代格式,更高压缩率
  • 响应式图片
    • srcset属性:提供不同尺寸的图片
    • sizes属性:指定图片显示尺寸
    • <picture>元素:根据设备选择图片
    • 服务端自适应:根据设备提供合适尺寸
  • 图片懒加载
    • loading="lazy"属性
    • 自定义懒加载库
    • Intersection Observer API
    • 滚动事件监听(传统方式)
  • 其他图片优化
    • 使用CDN托管图片
    • 图片CDN:自动处理图片尺寸
    • 避免图片缩放:使用合适尺寸
    • 图标字体:替代小图标

2.8 其他构建优化

Gzip/Brotli压缩

  • 前端配置:在request headers中添加accept-encoding: gzip
  • webpack配置:使用 CompressionWebpackPlugin 插件
  • 服务端配置:Nginx启用gzip
  • 压缩格式:支持gzip、deflate、br(Brotli)

构建速度优化

  • 多线程构建:thread-loader
  • 并行压缩:parallel: true
  • 减少搜索范围:resolve.modules
  • 缓存:webpack.cache

体积优化

  • 移除未使用的代码
  • 按需加载第三方库
  • 使用更小的替代库
  • 代码分割和按需加载

三、工程化最佳实践

3.1 持续集成与持续部署(CI/CD)

CI(持续集成)

  • 自动构建、测试
  • 尽早发现问题
  • 工具:GitHub Actions、GitLab CI、Jenkins

CD(持续部署)

  • 自动部署到生产环境
  • 蓝绿部署、滚动更新
  • 工具:Docker、Kubernetes

3.2 代码质量保障

代码规范

  • ESLint:JavaScript 代码检查
  • Prettier:代码格式化
  • Stylelint:CSS 代码检查
  • Git钩子工具:Husky、lint-staged(自动化规范检查)

自动化测试

  • 单元测试:Jest、Mocha
  • 集成测试:Cypress、Playwright
  • E2E 测试:Cypress、TestCafe

3.3 性能监控

监控指标

  • Core Web Vitals:LCP、FID、CLS
  • 错误监控:Sentry
  • 性能监控:Lighthouse、Web Vitals Extension

优化方向

  • 首屏加载时间
  • 页面响应时间
  • 内存使用情况

文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
 上一篇
前端面试准备指南八之网络安全篇 前端面试准备指南八之网络安全篇
网络安全与HTTP协议核心知识点,涵盖网络基础、HTTP协议、安全攻击及跨域通信,包括七层协议、TCP/UDP区别、HTTPS、三次握手四次挥手、HTTP版本对比、状态码、XSS/CSRF/DDoS、同源策略、跨域方案等
下一篇 
前端面试准备指南二之JavaScript核心篇 前端面试准备指南二之JavaScript核心篇
JavaScript核心知识点,包括数据类型、闭包、原型链、ES6新特性、异步编程等
  目录