工程化

高频版 · 来自面试实战和个人笔记

1 Webpack 深入

Webpack 五大概念与构建流程
五大核心概念:入口(entry)、输出(output)、加载器(loader)、插件(plugin)、模式(mode)。

构建流程:1. 初始化参数(合并配置)→ 2. 开始编译(初始化 Compiler,加载插件)→ 3. 确定入口 → 4. 编译模块(Loader 翻译,递归依赖)→ 5. 完成模块编译(得到依赖图)→ 6. 输出资源(组装 Chunk,生成文件)→ 7. 输出完成(写入文件系统)。

生产环境构建优化

多线程/多进程:thread-loader、TerserPlugin 的 parallel 选项。

代码分割:SplitChunksPlugin 将应用拆成多个 bundle。

缓存cache: { type: 'filesystem' }、babel-loader 的 cacheDirectory。

压缩:TerserPlugin 压缩 JS,css-minimizer-webpack-plugin 压缩 CSS,开启 cache 和 parallel。

Tree Shaking:ES6 模块 + optimization.usedExports,移除未使用代码。

其他:resolve.alias、resolve.extensions 减少查找范围;DllPlugin 预编译第三方库;stats: 'errors-only'。

开发环境构建优化

cache: { type: 'filesystem' };devtool: 'cheap-module-source-map';watchOptions.ignored: /node_modules/;loader 的 include/exclude;thread-loader;resolve.modules、alias、extensions;optimization.minimize: false。

2 Plugin 与 Loader

Plugin 实现原理:Tapable 钩子
插件是具有 apply 方法的类,在 Webpack 编译生命周期中被调用。通过 compiler.hooks 注册钩子,在特定阶段执行逻辑。
class MyPlugin {
  apply(compiler) {
    compiler.hooks.done.tap('MyPlugin', (stats) => {
      console.log('编译完成!', stats.endTime - stats.startTime, 'ms');
    });
  }
}

常用钩子:compile(编译开始前)、compilation(创建编译对象)、emit(生成文件前)、done(编译完成)。

Loader 链式处理与常用 Loader

Loader 链式操作:一个文件经多个 Loader 处理,前一个输出作为后一个输入。例如 LESS:less-loader → CSS → css-loader → JS 模块 → style-loader → 注入 DOM。最终产物是 JS 模块,运行时创建 style 标签。

常用:babel-loader、style-loader、css-loader、less-loader、sass-loader、file-loader、url-loader。

自定义 Loader 与 Plugin 示例
// 清除 console 的 loader
module.exports = function(source) {
  return source.replace(/console\.log\(.*\);?/g, '');
};

// 简单 Plugin
class NotifyPlugin {
  apply(compiler) {
    compiler.hooks.done.tap('NotifyPlugin', () => console.log('Build done!'));
  }
}

3 SplitChunks 配置

splitChunks 详细配置
splitChunks: {
  chunks: 'all',
  minSize: 20000,
  maxSize: 70000,
  minChunks: 1,
  maxAsyncRequests: 30,
  maxInitialRequests: 30,
  automaticNameDelimiter: '-',
  cacheGroups: {
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      name: 'vendors',
      chunks: 'all',
      priority: -10,
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true,
    },
  },
}
reuseExistingChunk 与 chunk/bundle/module 区分

reuseExistingChunk:若已有 Chunk 符合条件,复用而非新建。lodash 等公共依赖仍会被提取为独立 Bundle,A、B 页面共享引用。

Module:构建单元,通常一个源文件。Loader 处理后转为 Webpack 可管理格式。

Chunk:模块的集合,由 Webpack 根据依赖和配置分组。可包含多模块,或动态导入的单一模块。

Bundle:最终输出文件,由一个或多个 Chunk 打包而成。Tree Shaking 以 Module 为单位优化,Chunk 是代码分割的基本单位。

4 微前端

90+ 应用聚合方案与微前端通信
微前端将前端应用拆成多个独立模块,各团队独立开发、部署。核心理念:独立性、技术栈无关、渐进式集成、独立部署、隔离性。

90+ 应用聚合:通过微前端框架(如 qiankun、single-spa)将多个子应用插到基座应用中。

通信方式:URL 参数;自定义事件;全局状态(Redux/Zustand);localStorage/sessionStorage;发布-订阅;Module Federation 共享模块;qiankun 的 props 机制。优先松耦合方式。

iframe vs qiankun vs Module Federation

iframe:各微应用独立运行,隔离性强,但用户体验和性能较差,通信复杂。

qiankun / single-spa:通过 JS 沙箱、样式隔离管理子应用,支持多技术栈,通信通过 props 或全局事件。适合 SPA 聚合。

Module Federation:Webpack 5 特性,应用间直接共享模块(组件、库),动态加载。适合组件和库共享,实现微前端时应用间可互相引用模块。

5 低代码

amis / dataseed 方案与低代码平台设计
低代码通过配置和模板快速生成页面,减少手写代码。基于百度 amis 二次开发的 dataseed design 是常见方案。

常用手段:页面模板、组件库、表单/表格配置化、辅助函数。问题:辅助函数是黑盒,可能嵌套多层,样式难解耦,不便修改和调试。

改进方向:解耦型低代码框架,将逻辑、样式、配置分离,便于维护和扩展。