精读《snowpack》

1 引言

基于 webpack 构建的大型项目开发速度已经很是慢了,前端开发者已经逐渐习惯忍受超过 100 秒的启动时间,超过 30 秒的 reload 时间。即使被寄予厚望的 webpack5 内置了缓存机制也不会获得质的提高。但放到十年前,等待时间是几百毫秒。css

好在浏览器支持了 ESM import 模块化加载方案,终于原生支持了文件模块化,这使得本地构建再也不须要处理模块化关系并聚合文件,这甚至能够将构建时间从 30 秒下降到 300 毫秒。前端

固然基于 ESM import 的构建框架不止 snowpack 一个,还有好比基于 vue 的 vite,由于浏览器支持模块化是一个标准,而不与任何框架绑定,将来任何构建工具都会基于此特性开发,这意味着在将来的五年,前端构建必定会回到十年前的速度,这个趋势是明显、肯定的。vue

ESM import 带来的最直观的改变有下面三点:node

  1. node_modules 彻底不须要参与到构建过程,仅这一点就足以让构建效率提高至少 10 倍。
  2. 模块化交给浏览器管理,修改任何组件都只需作单文件编译,时间复杂度永远是 O(1),reload 时间与项目大小无关。
  3. 浏览器彻底模块化加载文件,不存在资源重复加载问题,这种原生的 TreeShaking 还能够作到访问文件时再编译,作到单文件级别的按需构建。

因此能够说 ESM import 模式下的开发效率,能作到与十年前修改 HTML 单文件的零构建效率几乎至关。react

2 简介 & 精读

snowpack 核心特征:webpack

  • 开发模式启动仅需 50ms 甚至更少。
  • 热更新速度很是快。
  • 构建时能够结合任何 bundler,好比 webpack。
  • 内置支持 TS、JSX、CSS Modules 等。
  • 支持自定义构建脚本以及三方插件。

安装

yarn add --dev snowpack
复制代码

经过 snowpack.config.json 文件配置,并能自动读取 babel.config.json 生效 babel 插件。git

开发调试

调试 snowpack dev,编译 snowpack build,会自动以 src/index 做为应用入口进行编译。github

snowpack dev 命令几乎是零耗时的,由于文件仅会在被浏览器访问时进行按需编译,所以构建速度是理想的最快速。web

当浏览器访问文件时,snowpack 会将文件作以下转换:npm

// Your Code:
import * as React from "react";
import * as ReactDOM from "react-dom";

// Build Output:
import * as React from "/web_modules/react.js";
import * as ReactDOM from "/web_modules/react-dom.js";
复制代码

目的就是生成一个相对路径,并启动本地服务让浏览器能够访问到这些被 import 的文件。其中 web_modules 是 snowpack 对 node_modules 构建的结果。

在这以前也会对 Typescript 文件作 tsc 编译,或者 babel 编译。

编译

编译命令 snowpack build 默认方式与 snowpack dev 相同:

也能够指定以 webpack 做为构建器:

// snowpack.config.json
{
  // Optimize your production builds with Webpack
  "plugins": [
    [
      "@snowpack/plugin-webpack",
      {
        /* ... */
      }
    ]
  ]
}
复制代码

除了默认构建方式以外,还支持自定义文件处理,经过 snowpack.config.json 配置 scripts 指定:

{
  "extends": "@snowpack/app-scripts-react",
  "scripts": {
    "build:scss": "sass $FILE"
  },
  "plugins": []
}
复制代码

好比上述语法支持了对 scss 文件编译的拓展。

"build:*": "..."

对文件后缀进行编译,好比:"build:js,jsx": "babel --filename $FILE" 指定了对 js,jsx 后缀的文件进行 babel 构建。

"run:*": "..."

仅执行一次,能够用来作 lint,也能够用来配合批量文件处理命令,好比 tsc: "run:tsc": "tsc"

"mount:*": "mount DIR [--to /PATH]"

将文件部署到某个 URL 地址,好比 "mount:public": "mount public --to /" 意味着将 public 文件夹下的文件部署到 / 这个 URL 地址。

还有 proxy 等 API 就不一一列举了,详细能够见 官方文档

咱们能够从构建命令体会到 snowpack 的理念,将源码以流式方式编译后,直接部署到本地 server 提供的 URL 地址,浏览器经过一个 main 入口以 ESM import 的方式加载这些文件。

因此全部加载与构建逻辑都是按需的,snowpack 要作的只是将本地文件逐个构建好并启动本地服务给浏览器调用。

前端开发离不开 node_modules,snowpack 经过 snowpack install 的方式支持了这一点。

snowpack install

这个命令已经被 snowpack dev 内置了,因此 snowpack install 仅用来理解原理。

如下是 snowpack install 执行的结果:

✔ snowpack install complete. [0.88s]

  ⦿ web_modules/                 size       gzip       brotli
    ├─ react-dom.js              128.93 KB  39.89 KB   34.93 KB
    └─ react.js                  0.54 KB    0.32 KB    0.28 KB
  ⦿ web_modules/common/ (Shared)
    └─ index-8961bd84.js         10.83 KB   3.96 KB    3.51 KB
复制代码

能够看到,snowpack 遍历项目源码对 node_modules 的访问,并对 node_modules 进行了 Web 版 install,能够认为 npm install 是将 npm 包安装到了本地,而 snowpack install 是将 node_modules 安装到了 Web API,因此这个命令只需构建一次,node_modules 就变成了能够按需被浏览器加载的静态资源文件。

同时源码中对 npm 包的引用都会转换为对 web_modules 这个静态资源地址的引用:

import * as ReactDOM from "react-dom";

// 转换
import * as React from "/web_modules/react.js";
复制代码

但同时能够看到 snowpack 对前端生态的高要求,若是某些包经过 webpack 别名设置了一些 magic 映射,就没法经过文件路径直接映射,因此 snowpack 生态成熟须要一段时间,但模块标准化必定是趋势,不规范的包在将来几年内会逐步被淘汰。

2020 年适合使用 snowpack 吗

答案是还不适合用在生产环境。

固然用在开发环境仍是能够的,但须要承担三个风险:

  1. 开发与生产环境构建结果不一致的风险。
  2. 项目生态存在非 ESM import 模块化包而致使大量适配成本的风险。
  3. 项目存在大量 webpack 插件的 magic 魔法,致使标准化后丢失定制打包逻辑的风险。

但能够看到,这些风险的缘由都是非标准化形成的。咱们站在 2020 年看之前浏览器非标准化 API 适配与兼容工做,可能会以为难以想象,为何要与那些陈旧非标准化的语法作斗争;相应的,2030 年看 2020 年的今天可能也以为难以想象,为何不少项目存在大量 magic 自定义构建逻辑,明明标准化构建逻辑已经彻底够用了 :P。

因此咱们要看到将来的趋势,也要理解当下存在的问题,不要在生态还没有成熟的时候贸然使用,但也要跟进前端规范化的步伐,在合适的时机跟上节奏,毕竟 bundleless 模式带来的开发效率提高是很是明显的。

3 总结

前端发展到 2020 年这个时间点,代码规范已经基本稳定,工程化要作的事情已经重新增功能逐渐转移到研发提效上了,所以提高开发时热更新速度、构建速度是当下前端工程化的重中之重。

snowpack 表明的 bundleless 方案确定是光明的将来,带来的构建提效很是明显,人力充足的前端团队与不须要考虑浏览器兼容性的敏捷小团队都已经开始实践 bundleless 方案了。

但对于业务须要兼容各浏览器的大团队来讲,目前 bundleless 方案仅可用于开发环境,生产环境仍是须要 webpack 打包,所以 webpack 生态还能够继续繁荣几年,直到大的前端团队也抛弃它为止。

若是看将来十年,可能前端工程化构建脚本都不须要了,浏览器能够直接运行源码。在这一点上,以 snowpack 为表明的 bundleless 模式着实跨越了一大步。

讨论地址是:精读《snowpack》· Issue #252 · dt-fe/weekly

若是你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证

相关文章
相关标签/搜索