前段时间Vue3.0生态的介绍提到了vite这个工具,借此文简单整理记录"no webpack,no bundle"的相关内容。
In
20192020, you should use a bundler because you want to, not because you need to.
在过去的几年中,如webpack 之类的bundle打包工具,已经从一个只限于输出优化bundle JavaScript的工具演变成一个需要为大多数web应用程序构建的必要步骤。不管你喜欢还是讨厌它,很难否认bundlers大幅增加了新web开发的复杂性。
为何会孕育出js捆绑打包的构建时代呢?个人认为有两个主要原因:
这也导致如今很难看到一个前端项目没有webpack介入,由此一个项目的复杂性也大大增加。以create-react-app为例,我们单纯只想在页面中显示一个"Hello world",但是我们需要安装200.9MB的node_modules,其中包含1,300+不同的依赖,10s~几十s的构建时间,这仅仅只是为了输出一个"Hello world"。
那么基于以上两点,现如今有没有其他更好的处理方式呢?
import
和export
,它们在浏览器端现在的兼容情况如下:
总体来看,兼容覆盖率还算良好,特别是一些PC如CRM这类不太考虑浏览器兼容的项目可以完全抛开bundle,并且往往也就是这些项目的复杂度和构建时间的消耗更高。
在此背景下,snowpack和vite先后应势而生。
Snowpack is a modern, lightweight toolchain for faster web development.
snowpack 项目最初时间约为18年下半年,当前(2020.08.09)最新版本为2.x,标语为不需打包的 O(1)
复杂度的构建系统。其核心特征如下:
# using npm
npm install --save-dev snowpack
# using yarn
yarn add --dev snowpack
Snowpack 也可以通过全局安装npm install -g snowpack
。但是推荐每个项目使用 --save-dev
/--dev
。
最简单的项目初始化就是使用Create Snowpack App
类似于create-react-app,通过命令初始化导入项目模板:
npx create-snowpack-app new-dir --template @snowpack/app-template-NAME [--use-yarn | --use-pnpm]
当前官方提供的模板:
比如初始了一个react项目,其目录结构如下:
其中最为核心的就是snowpack.config.json
,即项目配置文件。
拷贝模板项目下“src”和“public”文件到你的旧项目下,安装snowpack并执行snowpack dev
,连接并调整出现的异常即可。
通过 snowpack.config.json
文件配置,并能自动读取 babel.config.json
生效 babel 插件。
详细的配置和使用可见官网使用说明,从开发的角度来说跟以往项目基本无异。
调试
snowpack dev
编译
snowpack build
会自动以 src/index 作为应用入口进行编译。
snowpack dev
命令几乎是零耗时的,因为文件仅会在被浏览器访问时进行按需编译,因此构建速度是理想的最快速。如下实际执行的情况:
当浏览器访问文件时,snowpack 会将文件做如下转换:
// 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 文件编译的拓展。
默认情况下,snowpack build
和snowpack dev
效果是一样的,但是在生产环境的打包构建中,我们更希望拥有如tree-shaking等其他优化手段。这时候就需要在snowpack.config.json 中配置bundler 插件,比较常用的就是@snowpack/plugin-webpack
npm install @snowpack/plugin-webpack
// snowpack.config.json
{
// Optimize your production builds with Webpack
"plugins": [["@snowpack/plugin-webpack", {/* ... */}]]
}
snowpack是一个TypeScript项目,主要的三方依赖是rollup。
与webpack不同,snowpack独立处理文件,当文件更新时,snowpack也是只会跟新这个文件,而不是像webpack一样重新构建。这样的开发模式称为"Unbundled development"。
Unbundled development有以下优点:
从它的处理流程上来看,对业务代码的模块,基本只需要把 ESM 发布(拷贝)到发布目录,再将模块导入路径从源码路径换为发布路径即可。
而对 node_modules 则通过遍历 package.json 中的依赖,按该依赖列表为粒度将 node_modules 中的依赖打包。以 node_modules 中每个包的入口作为打包 entry,使用 rollup 生成对应的 ESM 模块文件,放到 web_modules 目录中,最后替换源码的 import 路径,是得可以通过原生 JavaScript Module 来加载 node_modules 中的包。
The faster frontend build tool. Unbundled web development.
vite这个项目开始时间约为2020年初,现在(2020-08-09)处于beta试用版,
其核心特征如下:
vite与snowpack类似,并且还有一部分依赖来自于snowpack v1。相比之下vite列出相比snowpack的优势是:
npm:
npm init vite-app
cd
npm install
npm run dev
yarn:
yarn create vite-app
cd
yarn
yarn dev
感觉与snowpack类似,也是一个TS项目,都是对单文件进行处理,核心使用了Koa。
从特性的构建流程来看看,vite 和 snowpack 十分接近,从现阶段来说,snowpack更加成熟,对框架的支持更好,而vite肯定对vue3生态的支持契合度更好,但是当前建设不够成熟。
简单来说,在vite和snowpack的选型中,如果你的项目是基于Vue的,那么就选择vite,react、Svelte的话还是使用snowpack吧。
那么现在应该使用snowpack/vite吗?
个人认为在大部分业务场景中还是否定的,总的原因还是兼容问题。不过可以尝试在开发环境使用snowpack/vite以提升构建速度,在生产仍然使用bundle模式。不过配置项不同也要承担一定风险:
不过未来比较明确的是,nowebpack即使不能成为主流也一定能占一席之地。