1. 项目概述:Raspberry Pi Zero W 的“Package E”是什么?
如果你手头有一块树莓派 Zero W,并且热衷于折腾各种嵌入式项目,那你很可能在寻找系统镜像或者刷写工具时,遇到过“Package E”这个有点神秘的标签。它不像“Raspbian”或者“Raspberry Pi OS”那样广为人知,但却是许多资深玩家和特定应用场景下的“隐藏选项”。简单来说,“Package E”通常指的是一个为树莓派 Zero W 这类资源受限设备特别优化、高度精简的 Linux 系统软件包集合。它不是一个官方的发行版名称,而更像是一个社区或特定项目中对某种系统配置方案的约定俗成的称呼。
这个“E”可以有很多种解读:可能是“Embedded”(嵌入式),强调其极致的精简和定制化,去掉了图形界面和绝大多数非核心服务;也可能是“Essential”(基础),只包含让设备跑起来最核心的组件;甚至是“Efficient”(高效),一切为了在 Zero W 那单核 CPU 和 512MB 内存的有限资源下,榨取出最高的运行效率。无论哪种解读,其核心目标都是一致的:为树莓派 Zero W 提供一个稳定、轻量、启动快速、且专注于单一任务或有限功能集的运行环境。这非常适合用来做 7x24 小时运行的家庭服务器(如 Pi-hole 广告屏蔽)、物联网网关、无线传感器节点、简单的网络监控工具,或者是一个超低功耗的下载机。
对于刚接触树莓派的新手,可能会直接使用官方的 Raspberry Pi OS Lite(无桌面版),这已经比完整版轻量很多。但“Package E”的思路往往走得更远,它可能基于更底层、更中性的发行版如 Debian 或 Alpine Linux 进行构建,通过手动挑选每一个安装的软件包,移除所有调试工具、非必要文档、甚至是不需要的内核模块,将系统体积压缩到极致(有时可以控制在 300MB 以内),从而减少存储卡读写、降低内存占用,并提升启动速度。接下来,我就为你拆解构建和使用这样一个“Package E”系统的核心思路、实操步骤以及我趟过的那些坑。
2. 核心设计思路与方案选型
为什么我们需要为树莓派 Zero W 专门准备一个“Package E”?直接使用官方镜像不行吗?答案是,可以,但不够优雅,尤其在资源利用率和长期运行稳定性上。树莓派 Zero W 的硬件规格决定了我们必须精打细算。
2.1 硬件限制与优化方向
树莓派 Zero W 搭载了一颗单核 1GHz 的 ARM11 处理器和 512MB 的 LPDDR2 内存。这个配置在今天看来相当基础,运行一个完整的桌面系统会非常吃力。即便使用 Lite 版,系统后台仍然会运行一些你可能不需要的服务,比如avahi-daemon(服务发现)、triggerhappy(热键守护进程)等,它们都会占用宝贵的内存和 CPU 周期。
因此,“Package E”的设计首要目标就是“减负”和“聚焦”:
- 极简内核:编译或配置一个只包含必要驱动和功能的内核,移除所有与特定硬件(如某些型号的摄像头、音频芯片)无关的模块,减少内核大小和内存占用。
- 最小化根文件系统:只安装运行目标应用所必需的系统库和工具。例如,如果你的应用只用 Python,那么就不需要安装 GCC 编译套件;如果不需要包管理,甚至可以移除
apt。 - 禁用非必要服务:系统启动时,除了必须的硬件初始化、网络和你的应用服务,其他一切皆可关闭。
- 优化存储与日志:使用 RAM disk(tmpfs)来存放临时文件和日志,减少对 SD 卡的写入,这不仅能提升速度,还能显著延长 SD 卡的使用寿命,因为 SD 卡的擦写次数是有限的。
2.2 基础系统选型:Debian vs Alpine
构建这样一个系统,通常有两个主流的基础选择:
Debian (Raspberry Pi OS 的基石)
- 优点:与树莓派官方生态兼容性最好,软件包丰富,社区支持强大。你可以从
raspbian-ua-netinst(一个极简的网络安装器)开始,或者手动裁剪一个已有的 Raspberry Pi OS Lite。 - 缺点:即使是最小安装,相比 Alpine 仍显臃肿。
systemd作为初始化系统虽然强大,但本身有一定资源开销。 - 适用场景:你需要使用大量仅适用于 Debian/Ubuntu 的软件包,或者你的应用严重依赖
systemd的功能。
Alpine Linux
- 优点:以小巧、安全、简单著称。其
musl libc和BusyBox组合使得基础系统镜像可以非常小(几十MB)。使用 OpenRC 作为初始化系统,比systemd更轻量。 - 缺点:软件库虽然齐全但数量不如 Debian,某些专有或闭源软件(如某些版本的 Oracle JDK)可能不支持。
musl libc与常见的glibc在某些边缘行为上有差异,可能导致特定二进制文件无法运行。 - 适用场景:追求极致的镜像体积和内存占用,应用环境相对标准(如使用 Go 静态编译的程序、Python 脚本、标准 C 库应用)。
我的选择建议:对于大多数树莓派 Zero W 的“Package E”项目,我倾向于从 Alpine Linux 开始。它的轻量特性与 Zero W 的硬件限制简直是天作之合。除非你有明确的软件兼容性要求,否则 Alpine 带来的资源节省是实实在在的。下面的实操也将以 Alpine Linux 为例。
2.3 构建方式:手动裁剪 vs 自动化工具
- 手动裁剪:在一台性能更强的机器(可以是 x86 的 PC 或另一台树莓派)上,挂载 Zero W 的 SD 卡,通过
chroot进入其环境,然后像管理一台普通 Linux 一样,用apk(Alpine 的包管理器)一点点安装和配置。这种方式灵活性最高,你能完全掌控每一个细节,但过程繁琐,且不易复现。 - 自动化工具:使用像
pi-gen(官方镜像构建工具)或 Alpine 的mkimage脚本进行定制。这需要一定的脚本编写能力,但一旦写好构建脚本,就能一键生成可重复的镜像。对于需要多次部署或团队共享的场景,这是更优解。
考虑到可复现性和学习价值,我将介绍一种“半自动”的构建方法:在 PC 上使用 Docker 模拟 ARM 环境来构建 Alpine 根文件系统,然后结合脚本完成最终配置。这种方法不需要额外的硬件,且环境干净、易于清理。
3. 构建“Package E”系统镜像的详细步骤
这里我们以构建一个用于运行 Python 网络服务(例如一个简单的 Flask API)的 Alpine Linux 系统为例。
3.1 准备构建环境
首先,在你的开发机(Linux 或 macOS,Windows 需使用 WSL2)上安装 Docker。这是为了创建一个与树莓派 Zero W(ARMv6 架构)一致的构建环境。
创建项目目录:
mkdir -p pi-zero-package-e && cd pi-zero-package-e mkdir rootfsrootfs目录将用于存放我们构建出的根文件系统。使用 Docker 获取基础 Alpine 文件系统: 我们拉取针对 ARMv6(Zero W 的架构)的 Alpine 镜像,并将其文件系统导出。
# 拉取适合树莓派 Zero (ARMv6) 的 Alpine 镜像 docker pull alpine:latest # 注意:latest 标签可能是多架构的,我们需要明确armv6 # 更可靠的方式是使用官方为树莓派准备的镜像,或指定sha256摘要 # 这里我们使用一个已知支持armv6的标签,例如: # docker pull arm32v6/alpine:latest # 创建一个临时容器并复制出它的文件系统 docker create --name alpine_temp arm32v6/alpine:latest docker export alpine_temp | tar -x -C ./rootfs docker rm alpine_temp执行后,
./rootfs目录下就是最基础的 Alpine Linux 根文件系统了,大小约 5-8 MB。
3.2 定制根文件系统
现在,我们通过chroot进入这个rootfs进行定制。我们将使用一个工具qemu-user-static,它允许我们在 x86 主机上运行为 ARM 编译的程序。
安装 qemu-user-static 并设置:
# 在 Ubuntu/Debian 上 sudo apt-get install qemu-user-static # 将 qemu-arm-static 复制到 rootfs 中 sudo cp /usr/bin/qemu-arm-static ./rootfs/usr/bin/基础系统配置:
# 挂载必要的虚拟文件系统并 chroot sudo mount --bind /dev ./rootfs/dev sudo mount --bind /dev/pts ./rootfs/dev/pts sudo mount --bind /proc ./rootfs/proc sudo mount --bind /sys ./rootfs/sys sudo chroot ./rootfs /bin/sh现在,你的命令行提示符应该变了,表示你已经在“模拟”的 ARM 系统内部。
在 chroot 环境内进行配置:
# 1. 设置 Alpine 的包管理仓库(使用国内镜像加速) echo "https://mirrors.aliyun.com/alpine/v3.19/main" > /etc/apk/repositories echo "https://mirrors.aliyun.com/alpine/v3.19/community" >> /etc/apk/repositories # 2. 更新索引并安装最必要的包 apk update apk add --no-cache busybox-static # 确保 busybox 完整 apk add --no-cache alpine-base # 基础系统包 apk add --no-cache sudo bash curl ca-certificates # 常用工具 apk add --no-cache python3 py3-pip # 我们的目标运行环境 # 3. 设置主机名、时区 echo "pi-zero-e" > /etc/hostname apk add --no-cache tzdata ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime echo "Asia/Shanghai" > /etc/timezone apk del tzdata # 安装后可以删除 tzdata 的安装包,但保留文件 # 4. 创建用户并设置密码 adduser -D -s /bin/bash pi echo "pi:your_secure_password" | chpasswd # 将 pi 用户加入 sudo 组 (Alpine 下通常是 wheel 组) adduser pi wheel # 允许 wheel 组 sudo 无需密码(根据安全要求可选) echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers # 5. 启用 SSH 服务(因为我们用 Zero W,无线连接是关键) apk add --no-cache openssh openssh-server-pam # 配置 SSH 允许密码登录(首次建议,后续可改为密钥) sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config # 设置开机启动(Alpine 使用 OpenRC) rc-update add sshd default # 6. 配置无线网络(WLAN) apk add --no-cache wpa_supplicant wireless-tools # 创建 wpa_supplicant 配置文件 cat > /etc/wpa_supplicant/wpa_supplicant.conf << EOF ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=CN network={ ssid="你的Wi-Fi名称" psk="你的Wi-Fi密码" key_mgmt=WPA-PSK } EOF chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf # 7. 配置网络接口 cat > /etc/network/interfaces << EOF auto lo iface lo inet loopback auto wlan0 iface wlan0 inet dhcp pre-up ip link set wlan0 up pre-up wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf post-down killall wpa_supplicant EOF # 8. (关键优化)将临时文件和日志移到内存盘 # 修改 /etc/fstab,添加以下几行 cat >> /etc/fstab << EOF tmpfs /tmp tmpfs defaults,nosuid,nodev,noatime 0 0 tmpfs /var/log tmpfs defaults,nosuid,nodev,noatime 0 0 tmpfs /var/tmp tmpfs defaults,nosuid,nodev,noatime 0 0 EOF # 9. 退出 chroot 环境 exit
3.3 制作可启动的 SD 卡镜像
退出 chroot 后,我们回到主机环境。现在需要将定制好的rootfs制作成一个完整的、包含 boot 分区的 SD 卡镜像。
卸载虚拟文件系统:
sudo umount ./rootfs/{sys,proc,dev/pts,dev}下载树莓派官方固件: 树莓派启动需要 boot 分区里的特定固件文件(
start*.elf,fixup*.dat,bootcode.bin等)。我们可以从官方 GitHub 获取。wget https://github.com/raspberrypi/firmware/archive/refs/heads/master.zip -O firmware.zip unzip firmware.zip -d firmware-master # 我们只需要 boot 目录下的文件 mkdir -p boot cp -r firmware-master/firmware-master/boot/* boot/ # 清理 rm -rf firmware-master firmware.zip创建空的镜像文件并分区:
# 创建一个约 1GB 的镜像文件(可根据需要调整) dd if=/dev/zero of=pi-zero-e.img bs=1M count=1024 # 分区:第一个分区(FAT32,boot),第二个分区(ext4,rootfs) sudo parted pi-zero-e.img --script mklabel msdos sudo parted pi-zero-e.img --script mkpart primary fat32 1MiB 256MiB sudo parted pi-zero-e.img --script mkpart primary ext4 256MiB 100%挂载镜像并复制文件:
# 将镜像文件关联到循环设备 LOOP_DEV=$(sudo losetup --show -f -P pi-zero-e.img) # 格式化分区 sudo mkfs.vfat -F 32 ${LOOP_DEV}p1 sudo mkfs.ext4 ${LOOP_DEV}p2 # 挂载 mkdir -p mnt/boot mnt/rootfs sudo mount ${LOOP_DEV}p1 mnt/boot sudo mount ${LOOP_DEV}p2 mnt/rootfs # 复制 boot 文件 sudo cp -r boot/* mnt/boot/ # 复制 rootfs 文件 sudo cp -a rootfs/. mnt/rootfs/ # 为树莓派 Zero W 创建 cmdline.txt 和 config.txt echo "console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait quiet" | sudo tee mnt/boot/cmdline.txt # 在 config.txt 中启用 UART(可选,用于调试)并做基本配置 cat << EOF | sudo tee mnt/boot/config.txt # 启用 UART enable_uart=1 # 针对 Zero W 的 ARM CPU arm_freq=1000 core_freq=400 # 禁用 HDMI 以省电(如果是无头运行) hdmi_blanking=1 hdmi_ignore_cec_init=1 hdmi_ignore_cec=1 EOF清理与卸载:
sudo umount mnt/boot mnt/rootfs sudo losetup -d $LOOP_DEV rm -rf mnt现在,
pi-zero-e.img就是一个可以直接用dd或Raspberry Pi Imager写入 SD 卡的系统镜像了。
4. 系统优化与深度调优技巧
镜像做好只是第一步,要让“Package E”在 Zero W 上跑得既稳又快,还需要一些额外的优化。
4.1 内核与启动参数优化
默认的 Alpine 内核可能包含很多用不上的模块。我们可以为树莓派 Zero W 编译一个定制内核。
获取内核源码与工具链:
# 在构建机上(非树莓派),安装交叉编译工具链 git clone --depth=1 https://github.com/raspberrypi/linux git clone --depth=1 https://github.com/raspberrypi/tools配置内核:
export ARCH=arm export CROSS_COMPILE=$(pwd)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- cd linux # 使用 Zero W 的默认配置作为起点 make bcmrpi_defconfig # 进入菜单化配置,进行精简 make menuconfig在
menuconfig中,可以安全地移除:- 不需要的文件系统驱动(如 Btrfs, XFS, 如果你只用 ext4)。
- 不需要的网络协议(如 IPX, Appletalk)。
- 不需要的硬件驱动(如声卡、某些 USB 设备驱动)。
- 内核调试信息 (
Kernel hacking-> 减少调试选项)。 - 将不必要的模块编译方式从
<M>(模块) 改为<N>(不编译),能直接内置 (<Y>) 的就内置,减少initramfs的复杂度。
编译与安装:
make -j$(nproc) zImage modules dtbs # 将编译好的内核、模块和设备树复制到之前制作的 rootfs/boot 目录对应位置 # 这是一个复杂的过程,需要替换原有文件。建议先研究 Alpine 的 linux-rpi 包的结构。注意:为 Alpine 交叉编译内核并整合是一个高级话题,涉及内核版本匹配、模块依赖等。对于初学者,可以暂时使用 Alpine 官方仓库的
linux-rpi包(apk add linux-rpi),它已经是一个为树莓派优化过的、相对精简的内核。
4.2 服务管理与开机自启优化
Alpine 使用 OpenRC,比 systemd 更轻量,但配置方式不同。确保只有必要的服务在运行。
# 在树莓派系统内查看所有服务 rc-status # 禁用不需要的服务(示例,根据实际情况调整) sudo rc-update del local default # 可能不需要本地脚本服务 sudo rc-update del networking boot # 如果我们的接口配置在 /etc/network/interfaces 里,可能不需要 networking 服务 # 确保 sshd 和必要的服务在 default runlevel sudo rc-update add sshd default sudo rc-update add wpa_supplicant default # 如果使用我们上面的 interfaces 配置,这个可能不需要单独服务 sudo rc-update add dhcpcd default # 如果使用 dhcpcd 而不是 interfaces 文件关键优化:使用syslog-ng或busybox syslogd替代rsyslog。Alpine 默认的busybox syslogd非常轻量,足够使用。避免安装完整的日志系统。
4.3 存储与内存优化实践
Swap 分区/文件:在 512MB 内存上,适当的 Swap 可以防止应用在内存不足时直接崩溃。但 SD 卡上的 Swap 会严重影响寿命和性能。我的建议是:如果应用内存需求可控,最好禁用 Swap。如果必须启用,可以创建一个很小的 Swap 文件(如 100MB)并设置极低的
swappiness值。# 禁用 Swap sudo swapoff -a sudo rc-update del swap boot # 或者,创建并启用一个小的 Swap 文件(谨慎使用) sudo dd if=/dev/zero of=/var/swapfile bs=1M count=100 sudo chmod 600 /var/swapfile sudo mkswap /var/swapfile sudo swapon /var/swapfile # 设置 swappiness 为非常低的值(1-10),表示尽量少用 Swap echo "vm.swappiness=5" | sudo tee -a /etc/sysctl.conf sudo sysctl -p使用
logrotate并限制日志:即使日志在内存盘,也要防止单个日志文件过大。sudo apk add --no-cache logrotate sudo cat > /etc/logrotate.conf << EOF # 每周轮转,保留4个旧日志,压缩 weekly rotate 4 compress create include /etc/logrotate.d EOF
5. 应用部署示例:部署一个轻量级 Flask API
现在,我们的“Package E”系统已经就绪。假设我们要部署一个简单的监控 API,返回系统状态。
在开发机准备应用:
# app.py from flask import Flask, jsonify import psutil app = Flask(__name__) @app.route('/status') def status(): cpu = psutil.cpu_percent(interval=1) mem = psutil.virtual_memory() disk = psutil.disk_usage('/') return jsonify({ 'cpu_percent': cpu, 'memory_percent': mem.percent, 'disk_percent': disk.percent, }) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)# requirements.txt flask psutil在树莓派上部署:
- 将
app.py和requirements.txt通过 SCP 传到树莓派/home/pi/目录。 - 在树莓派上安装依赖(使用国内 PyPI 镜像):
sudo pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt - 测试运行:
python3 app.py。
- 将
配置为系统服务(OpenRC):
sudo cat > /etc/init.d/myflaskapp << 'EOF' #!/sbin/openrc-run name="myflaskapp" command="/usr/bin/python3" command_args="/home/pi/app.py" command_background=true pidfile="/run/${RC_SVCNAME}.pid" command_user="pi" command_group="pi" depend() { need net after firewall } EOF sudo chmod +x /etc/init.d/myflaskapp sudo rc-update add myflaskapp default sudo service myflaskapp start现在,你的 Flask API 就会在系统启动时自动运行,并且可以通过
http://<树莓派IP>:5000/status访问。
6. 常见问题与排查实录
在构建和运行“Package E”系统的过程中,我遇到了不少典型问题,这里记录下排查思路。
6.1 系统无法启动(卡在彩虹屏或黑屏)
- 问题现象:SD 卡插入 Zero W 后,电源灯常亮,但 ACT 灯不闪烁,屏幕无输出或卡在彩虹屏。
- 排查步骤:
- 检查 boot 分区文件:确保
boot分区里有正确的start*.elf,fixup*.dat,bootcode.bin(Zero W 需要),以及cmdline.txt和config.txt。cmdline.txt中的root=参数必须指向正确的 root 分区(如/dev/mmcblk0p2)。 - 检查内核兼容性:确保使用的内核镜像(
kernel.img或kernel7.img)与树莓派型号和你的 rootfs 匹配。对于 Zero W,通常是kernel.img。Alpine 的linux-rpi包会处理好这个。 - 检查电源:使用质量合格的 5V/2.5A 电源,并确保 Micro USB 线能承载足够电流。供电不足是树莓派启动异常的常见原因。
- 最小化测试:尝试使用一个未经修改的官方 Raspberry Pi OS Lite 镜像启动,以排除硬件问题。
- 检查 boot 分区文件:确保
6.2 无线网络无法连接
- 问题现象:系统启动后,
wlan0接口不存在或无法获取 IP 地址。 - 排查步骤:
- 检查驱动和固件:确保安装了
linux-firmware或linux-firmware-brcm包,其中包含博通 WiFi 芯片的固件。Alpine 中可能需要apk add linux-firmware-cypress(针对某些型号)。 - 检查
wpa_supplicant.conf:确认 SSID 和密码正确,且文件权限是600。一个常见的错误是密码包含特殊字符未正确转义。 - 查看日志:使用
dmesg | grep -i firmware和dmesg | grep -i wlan查看内核加载无线驱动和固件的日志。使用rc-service wpa_supplicant log查看 wpa_supplicant 的运行日志。 - 手动启动测试:停止服务,手动运行命令调试:
在另一个终端尝试sudo ip link set wlan0 up sudo wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf -dsudo dhcpcd wlan0。观察命令行输出中的错误信息。
- 检查驱动和固件:确保安装了
6.3 应用运行缓慢或内存不足
- 问题现象:部署的 Python 服务响应慢,或偶尔崩溃,
free -m显示内存几乎用尽。 - 排查与解决:
- 监控工具:安装
htop或使用glances(更轻量)来实时查看 CPU 和内存使用情况。apk add htop。 - 优化 Python:
- 使用
--no-cache-dir安装 pip 包减少空间占用。 - 考虑使用
PyPy替代 CPython 来运行某些计算密集型脚本,PyPy 的 JIT 编译器有时能带来显著性能提升,且内存管理可能更高效(需测试兼容性)。 - 对于 Web 服务,使用生产级 WSGI 服务器如
gunicorn或waitress,而不是 Flask 自带的开发服务器,并调整 worker 数量(对于单核 Zero W,1-2 个 worker 足矣)。
- 使用
- 审视依赖:用
pip list检查是否安装了非必要的庞大库。例如,如果只是用requests做简单 HTTP 调用,可以考虑用更轻量的urllib3或http.client。 - 启用 ZRAM:这是一个比传统 Swap 更优的内存压缩方案,尤其适合树莓派。它会在内存中创建一个压缩块设备作为 Swap。Alpine 社区有
zram-init包可以方便地配置。
这会在启动时自动配置 ZRAM,通常能有效缓解内存压力。sudo apk add zram-init sudo rc-update add zram-init boot sudo service zram-init start
- 监控工具:安装
6.4 系统时钟不准或时区错误
- 问题现象:日志时间戳不对,或应用获取的时间与本地时间不符。
- 解决:
- 确保已设置时区:如前面步骤所示,安装
tzdata并软链接到正确时区。 - 启用 NTP 同步:安装并启动
chrony或ntpd(chrony更轻量)。sudo apk add chrony sudo rc-update add chronyd default sudo service chronyd start - 检查硬件时钟:树莓派没有电池供电的 RTC,关机后时间会丢失。网络启动后,NTP 会将其校正。确保系统能正常联网,NTP 服务才能工作。
- 确保已设置时区:如前面步骤所示,安装
构建一个为树莓派 Zero W 量身定制的“Package E”系统,是一个从“能用”到“好用”再到“精用”的过程。它迫使你去理解每一个运行在设备上的进程、每一兆内存的用途、每一个服务的必要性。这种深度掌控带来的不仅是性能的提升和稳定性的增强,更是一种纯粹的极客乐趣。当你看到自己亲手裁剪的系统在小小的 Zero W 上飞快启动,并以极低的资源占用稳定运行数周时,那种成就感是使用现成全功能镜像无法比拟的。最后一个小建议:将整个构建过程,包括所有的配置文件和脚本,用 Git 管理起来。这样,下一次为不同的项目构建新的“Package E”时,你就能快速地从一份已知良好的基础开始迭代,而不是从头再来。