Skip to content

为什么要打包

  • 模块化
  • 可维护性
  • 可复制性

模块化定义:以功能块为单位进行程序设计,实现其求解算法的方法称为模块化。

模块化的目的是为了降低程序复杂度,使程序设计、调试和维护等操作简单化。

模块化发展史

也可谓是前端进化史

全局变量 + 命名空间

缺点:

  • 依赖全局变量,污染全局作用域,不安全
  • 依赖约定命名空间来避免冲突,可靠性不高
  • 需要手动管理依赖并控制执行顺序,容易出错
  • 需要再最终上线前手动合并所有用到的模块

common.js / AMD

common.js 之前很流行,但缺点是没法在浏览器里直接运行

js
const bar = require('./bar')
module.exports = function () {}

AMD - Asynchoronous module definition

js
define(function (require) {
  // 通过相对路径获取依赖模块
  const bar = require('./bar')
  // 模块产出
  return function () {}
})
  • 采用异步方式加载模块
  • 需要在全局环境定义 require 和 define ,不需要其他的全局变量
  • 通过文件路径和模块自己声明的模块名定位模块
  • 提供了打包工具自动分析依赖并合并
  • 配合特定的 AMD 加载器使用,RequireJS

ES6 modules

js
// 通过相对路径获取依赖模块
import bar from './bar'
// 模块导出
export const foo = ''
export default function () {}
  • 引入和导出的方式更多
  • 支持复杂的静态分析

打包工具的功能和作用

  • webpack
  • vite (通过 Rollup 和 ESBuild)

学习使用 vite(Rollup)实现代码打包

  • 代码入口文件
  • 配置文件
  • 生成多种文件类型
  • 生成样式文件
  • TypeScript 定义文件 d.ts

Vite

大型应用使用 webpack 等传统打包工具遇到性能瓶颈:非常慢。而 Vite

Vite 以 原生 ESM 方式提供源码。实际上是让浏览器接管了打包程序的部分工作

还是直接看文档来得快些 https://cn.vitejs.dev/guide/why.html

Bundle based dev serverentry···routeroutemodulemodulemodulemodule···BundleServer ready

Native ESM based dev serverentry···routeroutemodulemodulemodulemodule···Server readyDynamic import (code split point)HTTP request

依赖:使用 esbuild 进行预构建(由 go 编写的,比 Node.js 快 N 倍)

  • 处理 CommonJs 以及 UMD 类型文件的兼容性,转换为 ESM 及 ESM 的导入形式
  • 提高性能,将多个模块合并成单个模块,因为原生 ESM 格式下,一个文件就是一次请求
  • 缓存,将预构建的依赖项缓存到 node_modules/.vite 中

源码:包含一些非 JS 标准格式的文件,如 jsx/css/vue 等,时常会被编辑

发布到 npm

  • 本地测试
  • 注册发布到 npm
  • npm hooks

打包什么类型的文件

  • CommonJs, ES6 modules 需要特殊的打包工具支持
  • AMD 已过时
  • 浏览器直接使用 (UMD)Universal Module Definition
    • 通用 JS 格式
    • 兼容 Common.js、AMD、浏览器
js
;(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['b'], factory)
  } else if (typeof module === 'object' && module.exports) {
    // Node. Does not work with strict CommonJS, but only
    // CommonJS-like environments that supportmodule.exports, like Node
    module.exports = factory(require('b'))
  } else {
    // Browser globals (root is window)
    root.returnExports = factory(root.b)
  }
})(typeof self !== 'undefined' ? self : this, function (b) {
  return {}
})()

但是,不是推荐格式,因为太大了,不支持 Tree Shaking

综上:

  • 首要格式 - ES Module ,并且提供支持 TypeScript 的 type 文件
  • 备选方案 - UMD