打包工具

40 阅读3分钟

webpack与vite对比

  1. 构建方式

(1)webpack启动项目时,会根据配置文件中的入口(entry),分析出项目所有依赖关系,然后打包成一个或多个文件(bundle.js),交给浏览器去加载渲染。在生产环境中优化 bundle,比如 Tree-shaking、Code Splitting。

项目越大,需要打包的东西越多,启动时间越长。

(2)使用vite运行项目时,首先会用esbuild进行预构建,将所有模块转换为es module,不需要对整个项目进行编译打包,而是在浏览器需要加载某个模块时,拦截浏览器发出的请求,根据请求进行按需编译,然后返回给浏览器。

生产环境:借助 Rollup 打包,天然支持 ESModule,优化输出体积。

项目大小对vite启动速度的影响很小。

  1. 热更新

(1)webpack项目中,每次修改文件,都会对整个项目重新进行打包

(2)Vite 热更新的实现依赖 原生 ES Module (ESM)WebSocket 通信

  • 启动 Dev Server

Vite 启动一个开发服务器,基于 koa。同时在浏览器和服务器之间建立一个 WebSocket 连接

  • 文件变更监听

使用 chokidar 监听项目文件(.vue.js.ts.css 等)。一旦文件变更,通过 WebSocket 向浏览器发送更新消息(包含变化的模块路径、更新类型等)。

  • 浏览器接收并处理

浏览器端 Vite 注入了 HMR runtime(一个小的客户端脚本)。它会拦截 WebSocket 消息,替换对应的模块。

Webpack

  1. loader

告诉 webpack 如何处理非 JavaScript 文件(如 .css, .vue, .ts, .png 等),
并把它们转换成浏览器可以识别的 JS 模块

  • css-loader:把 .css 文件内容转换为 JS 中的字符串模块;
  • babel-loader:把 ES6+ 代码编译为兼容的 ES5;
  • file-loader / url-loader:处理图片、字体等资源。
  • sass-loader:把 Sass 转成 CSS
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,        // 匹配文件类型
        use: 'babel-loader',  // 使用哪个 loader 处理
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'] // 多个loader从右往左执行
      }
    ]
  }
}

  1. plugin

Plugin 是 webpack 的插件系统, 通过监听 webpack 的生命周期钩子(hooks)
在构建过程的不同阶段,扩展 Webpack 的功能

  • terser-webpack-plugin压缩 JS
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { DefinePlugin } = require('webpack');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new DefinePlugin({ VERSION: JSON.stringify('1.0.0') })
  ]
};

Rollup

Rollup 是一个 ES Module 打包工具,特别适合用于构建 库(Library)框架。与webpack相比, Rollup 缺少开发服务器、HMR、复杂资源处理等功能

  1. Tree-shaking

能在打包时完全移除未使用的函数/变量,生成非常干净的代码。

  1. Rollup 可以把源码打包成多种格式:
格式名全称适用场景特点
es / esmES Module现代浏览器、ESM 环境(如 Node 14+)使用 import / export 语法
cjsCommonJSNode.js (旧版)、Webpack (require)使用 require() / module.exports
umdUniversal Module Definition同时支持浏览器 + Node + AMD可挂到全局变量上
iifeImmediately Invoked Function Expression浏览器直接引入 <script>立即执行函数形式,适合全局变量输出
amdAsynchronous Module DefinitionRequireJS、老 AMD 体系很少使用
systemSystemJS动态模块加载场景适合 SystemJS runtime
  1. commonjs与esmodule的区别
特性CommonJSES Module
语法require / module.exportsimport / export
加载同步加载静态/异步加载
循环依赖返回部分对象实时绑定,保证值更新
浏览器原生支持<script type="module">
tree-shaking✅ 支持
默认导出通过 module.exportsexport default
Node.js 默认.js.mjs"type":"module"