首页>国内 > 正文

超全面的前端新一代构建工具对比: esbuild、Snowpack、Vite、wmr

2022-04-18 11:51:09来源:秋风的笔记

在过去的一年里,出现了一批新的开发者工具,它们正在紧跟过去几年主导前端开发的工具,包括webpack、Babel、Rollup、Parcel、create-react-app。

这些新的工具并不是为了完成完全相同的功能而设计的,每个工具都有不同的目标和功能。尽管存在差异,但这些工具有一个共同的目标:改善开发者体验。

概览esbuildSnowpackVitewmrFeature comparisonWrapping up

具体来说,我想对每一个进行评估,概述它们的作用,为什么我们需要它们,以及它们的使用案例。比较并不总是公平的,我们在这篇文章中看到的东西也不是直接的竞争对手。事实上,Snowpack和Vite在某些任务中都使用了esbuild。我们的目标更多的是为了更好地了解运行任务的开发者工具的格局,让我们的工作更轻松。通过这种方式,我们就能看到有哪些选择,以及它们是如何配合的,这样我们就能在需要的时候做出最好的选择。

当然,我分析的所有的这些都会受到我使用React和Preact的经验的影响。我对这些框架库比较熟悉,但我也会关注它们对其他前端框架的支持。

为啥这些工具现在都出现了?

在某种程度上,我认为这些工具的到来是对JavaScript工具疲劳的一种反应。

Snowpack、Vite和wmr都用到了浏览器中的原生JavaScript模块。早在2018年,Firefox 60发布时默认启用了ECMAScript 2015的Module。此后,各大浏览器引擎都支持原生JavaScript模块。Node.js也在2019年11月推出了原生JavaScript模块。在2021年的今天,我们还在寻找原生JavaScript模块能够带来哪些新的可能性。

这些工具和现有的工具有什么不同?

无论我们在开发服务器上使用webpack、Rollup还是Parcel,工具都会从我们的源代码和node_modules文件夹中把我们的整个代码库打包在一起,通过构建过程运行这些代码,比如Babel、TypeScript或PostCSS,然后将打包的代码推送到我们的浏览器上。这一切都需要花费大量的工作,并且会使开发服务器在更大的代码库中慢慢爬行,甚至在所有的工作都用于缓存和优化之后也是如此。

Snowpack、Vite和wmr开发服务器则不采用这种模式。相反,它们会等到浏览器找到一个import语句,并为模块发出HTTP请求。只有在这个请求发出后,该工具才会对请求的模块和模块导入树中的任何叶节点应用转换,然后将这些转换提供给浏览器。这大大加快了速度,因为在推送到开发服务器的过程中减少了工作。

你会注意到描述中缺少了esbuild。它首先是一个bundler程序。它并不像其他工具那样绕开bundler。相反,esbuild通过避免昂贵的转换、利用并行化和使用Go语言来快速处理代码。

实验

我从React文档中选取了一个示例应用,并使用文中所提到的每个工具重新构建了它。我选择的项目是Yogita Verma的Snap Shot。这里有一个原始repo的链接,还有一个我的repo链接,里面有四个版本的Snap Shot,每个版本都使用不同的构建工具。我们稍后会比较每个构建步骤的输出。重新构建这个应用程序,让我可以测试开发人员将一些相当标准的React依赖项添加到工具(包括React Router和axios)中的体验。

原始 repo:https://github.com/Yog9/SnapShotDemo:https://github.com/Elliotclyde/build-tool-test可以比较的功能

在我们深入了解每个工具的具体内容之前,它们都支持以下功能(在不同程度上)。

对原生JavaScript模块的一流支持TypeScript编译(但不进行类型检查)JSX用于扩展性的插件API内置开发服务器CSS bundling和对CSS-in-JS的支持。

所有这些工具都可以将TypeScript编译成JavaScript,但即使有类型错误也会这样做。为了进行正确的类型检查,你需要安装TypeScript,并在你的JavaScript根文件上运行tsc --noEmit,或者使用编辑器插件来观察类型错误。

好了,下面我们来具体看看每个工具。

esbuild

esbuild是由Evan Wallace(Figma的CTO)创建的。它的主要特点是,它提供的构建步骤比基于Node的打包器快10×-100×(根据他们自己的基准)。它没有提供许多你可能会在create-react-app这样的工具中找到的开发者便利。但是有越来越多的esbuild starter启动器出现来填补这些空白,包括create-react-app-esbuild,estrella和Snowpack,它们的构建步骤使用esbuild。

esbuild是非常新的。它还没有达到1.0版本,还没有完全准备好用于生产使用 — 但它已经不远了。它为你提供了直观的JavaScript和带有智能默认值的命令行API。

用例

esbuild完全改变了bundler的游戏规则。它将在大型代码库中发挥最大的作用,因为esbuild和node打包器之间的速度差异会成倍增加。当esbuild达到1.0的时候,它在大型生产站点中会非常有用,将为团队节省大量等待构建完成的时间。不幸的是,大型生产站点必须要等到esbuild变得稳定。在此期间,它只是很好地增加了一些速度,让你在项目中的bundling变得更快。

esbuild快如闪电的速度对于你正在做的任何工作来说都是一种奖励。减少等待构建运行的时间,对开发者的体验总是有好处的! 考虑到这一点,如果你是在做快速应用的原型,你可能会想要从比esbuild更高级的东西开始--否则,在获得我们期望的JavaScript中的便利之前,你需要花一些时间引入依赖项并配置你的环境生态系统。另外,如果你想尽可能地减小bundle包的大小,你可能会想使用Rollup和terser,它们会产生略小的bundle大小。

设置

我决定以一种幼稚的方式在esbuild中启动一个React项目:npm安装esbuild、React和ReactDOM。我创建了一个src/code秘密花园.jsx文件和一个dist/index.html文件。然后,我使用下面的命令将app编译成一个dist/bundle.js文件。

./node_modules/.bin/esbuild src/code秘密花园.jsx --bundle --platform=browser --outfile=dist/bundle.js

当我在浏览器中打开index.html时,我遇到了 "白屏 "和 "Uncaught ReferenceError: process is not defined " 的控制台错误。文档和CLI都准确地解释了你需要做什么来避免这种情况,但对于初学者来说,这可能有点 "捉襟见肘",因为在bundling React时,它需要一个额外的参数。

--define:process.env.NODE_ENV="production"

或者,如果你在npm脚本中包含了esbuild,就像这样写来转义引号。

--define:process.env.NODE_ENV=\"production\"

任何绑定到浏览器的需要node环境变量的库都需要这个define参数。Vue 2.0也需要这些参数。你在使用Preact时不会有同样的问题,因为它不需要任何环境变量,而且默认情况下已经为浏览器准备好了。

在运行了带有定义参数的命令后,我的 "Hello world ConardLi " React 应用完美地运行了。JSX可以使用.jsx文件开箱即用。也就是说,React需要手动导入,然后将JSX转换为React.createElement。然而,有一些方法可以在JSX中添加自动导入,或为Preact配置JSX。

用法

esbuild为开发服务器提供了一个-serve的选项。它绕过了文件系统,直接从内存中为模块提供服务,确保浏览器不会提取旧版本的模块。然而,它不包括实时/热重载,所以你会发现自己在保存后要刷新浏览器,这不是一个良好的体验。

我决定使用新发布的watch功能.这告诉esbuild在每次保存源文件时重新编译代码。但是我们仍然需要一个服务器来查看我们保存的变化。我们可以拉入一个开发服务器包,比如Luke Jackson的servor。

npm install servor --save-dev

然后我们就可以使用esbuild的Javascript API作为服务器启动,同时运行esbuild的watch模式。让我们在项目的根目录创建一个名为watch.js的文件。

// watch.jsconst esbuild = require("esbuild");const servor = require("servor");esbuild.build({  // pass any options to esbuild here...  entryPoints: ["src/app.jsx"],  outdir: "dist",  define: { "process.env.NODE_ENV":  "production"  },  watch: true,});async function serve(){  console.log("running server from: http://localhost:8080/");  await servor({    // pass any options to servor here...    browser:true,    root: "dist",    port: 8080,  });}serve();

现在在命令行中运行node watch.js。这为我们提供了一个很好的开发服务器,但是同样,它也不能给我们提供热更新或者快速刷新(也就是说,你的客户端状态不会被保存)。但这已经足够满足我的测试需求了。

即使我们每次保存文件时都要对整个应用程序进行重新编译,但在esbuild变慢之前,我们需要有一个相当庞大的应用程序。在我设置了这个工具之后,我从更改中得到了即时的反馈。我的电脑使用的是2012年的英特尔i7,所以它肯定不是一台顶级的机器。

如果你需要一个带有实时重载和一些React默认值的预配置esbuild版本,你可以克隆这个repo。

https://github.com/Elliotclyde/esbuild-react-starter

支持的文件

如果这是你的风格,esbuild可以在JavaScript中导入CSS。它将会把CSS编译成一个输出文件,名字和你的主输出JavaScript文件一样。它还可以默认打包CSS @import语句。目前还没有对CSS模块的支持,但有计划。

用于esbuild的插件社区正在不断壮大。例如,Vue单文件组件和Svelte组件都有可用的插件。

esbuild可以使用JSON文件,并且可以将它们bundle到JavaScript模块中,无需任何配置。

它还可以用JavaScript导入图片,可以选择将图片转换为数据URL或复制到输出文件夹中。这种行为在默认情况下并没有启用,但你可以在你的esbuild配置对象中添加以下内容来启用这两个选项。

loader: {  .png :  dataurl  } // Converts to data url in JS bundleloader: {  .png :  file  } // Copies to output folder

代码拆分似乎是一项正在进行中的工作,但大多数情况下是以ESM输出格式进行的,而且看起来确实是项目的优先级。另外值得一提的是,tree-shaking是esbuild默认内置的,无法关闭。

生产构建

在 esbuild 命令中使用 "minify "和 "bundle " 选项不会创建一个像Rollup/Terser流水线一样小的bundle。这是因为esbuild牺牲了一些bundle大小的优化来尽可能少的通过你的代码。然而,根据你的项目,这种差异可能是微不足道的,但对于bundle速度的提高来说是值得的。在我的Snap Shot应用程序的克隆中,esbuild创建了一个177KB的包,这比使用rollup和terser的Vite产生的165KB多不了多少。

总结

esbuild是一个非常强大的工具。但如果你习惯于零配置的设置,那可能会很困难。如果你需要更多,那么你可能想看看下一个工具,基于esbuild的Snowpack。

Snowpack

Snowpack是由Skypack和Pika的创造者开发的一款构建工具。它提供了一个很棒的开发服务器,并且是以 "非打包式开发 "的理念创建的。

引用文档中的一句话 "你应该能够使用一个打包程序,因为你想要,而不是因为你需要。"

默认情况下,Snowpack的构建步骤并没有将文件打包到一个单一的包中,而是提供了在浏览器中运行的非打包esmodules。实际上esbuild是作为一个依赖关系包含在其中的,但我们的想法是使用JavaScript模块,只有在需要时才与esbuild打包。

Snowpack有一些非常精巧的文档,包括一个与JavaScript框架一起使用的指南列表,以及一堆模板。有些指南还在不断完善中,但其他的指南,比如针对React的指南,就很不错,很清晰。看起来Snowpack也把Svelte当做一等公民来对待。实际上,我第一次听说Snowpack是在2020年Svelte峰会上Rich Harris的 "未来主义Web开发 "演讲中。也就是说,即将推出的Svelte元框架SvelteKit本来应该由Snowpack提供支持,但后来改用了Vite(我们接下来会对其进行评测)。

使用案例

如果你想在非打包部署上加倍努力,Snowpack是个不错的选择。你可能会用少量的模块来编写源代码,这就意味着你不会用非捆绑构建来创建一个大的请求瀑布。如果你不需要额外的复杂性和技术债务,那么Snowpack是一个很好的选择。一个很好的用例是,如果你正在增量地将前端框架采用到服务器渲染或静态的应用程序中。你可以从node生态系统中获得尽可能少的工具,但你仍然会得到声明式前端框架的好处。

其次,我认为Snowpack是esbuild的一个很好的封装器。如果你想尝试esbuild,但同时又想拥有一个开发服务器和预先编写的前端框架模板,那么选择Snowpack是不会错的。在Snowpack配置的构建步骤中启用esbuild,你就可以了。

就目前的情况来看,我认为Snowpack不会是像create-react-app这样的零配置工具的最佳替代品,因为如果你有一个大的应用,需要一个超级花哨的优化生产就绪的构建步骤,你就需要自己导入插件并配置它们。

设置

让我们通过命令行来启动Snowpack的项目。

mkdir snowpackprojectcd snowpackprojectnpm init #fill with defaults npm install snowpack

现在,让我们在package.json中添加以下内容。

// package.json"scripts": {  "start": "snowpack dev",  "build": "snowpack build"},

接下来,我们将创建一个配置文件。

// Mac or Linuxtouch snowpack.config.js// Windowsnew-item snowpack.config.js

我认为Snowpack最神奇的地方在于在配置文件中设置一个看似无害的键值对。例如,把这个粘贴到配置文件中。

// snowpack.config.jsmodule.exports = {  packageOptions: {    "source": "remote",  }};

source: remote启用了一种叫做流式导入的东西。通过流式导入使Snowpack能够绕过npm安装,将裸导入(例如,从import React from‘ React’)转换为Skypack的CDN导入。

继续前进,让我们创建一个index.html文件。

  >  Snowpack streaming imports  
<script type="module" src="app.js"></script>

最后,我们将添加一个code秘密花园.jsx文件。

// code秘密花园.jsx import React from  react import ReactDOM from  react-dom const App = ()=>{  return 

Welcome to Snowpack streaming imports!

}ReactDOM.render(,document.getElementById( root )); 0

注意,我们在任何阶段都没有安装React或ReactDOM的npm。但如果我们像这样启动Snowpack开发者服务器。

./node_modules/.bin/snowpack dev

我们的应用程序还能用。

Snowpack不是从nodemodules文件夹中提取,而是从Skypack中提取npm包,Skypack是一个托管npm注册表的CDN,它是预先优化的,可以在浏览器中工作。然后,Snowpack将它放在一个./snowpack/pkgURL中。

用法

这离基于Node/npm的工作流还有很大的差距。我们实际上看到的是一个新的基于CDN/JavaScript模块的工作流。

然而,如果我们的应用按原样运行生产构建,Snowpack会抛出一个错误。这是因为它需要知道在构建时要使用哪个版本的React和ReactDOM。你可以通过一个snowpack.deps.json来解决这个问题,它可以通过运行下面的程序自动创建。

./node_modules/.bin/snowpack add react./node_modules/.bin/snowpack add react-dom

这不会从npm下载包,但它会记录用于Snowpack构建所使用包的版本。

一个需要注意的是,我们会错过开发者的错误信息,因为Skypack会发布生产版本的包。

即使我们没有使用流式导入,Snowpack开发服务器也会将node_modules中的每个依赖关系打包成一个JavaScript文件,将这些文件转换为本地JavaScript模块,然后将其提供给浏览器。这意味着浏览器可以缓存这些脚本,只有在它们发生变化时才会重新请求它们。开发服务器会在保存时自动刷新,但不会保留客户端的状态。所有来自node的依赖关系似乎都能正常工作,不管它们是使用传统的模块格式还是node API(比如我们在esbuild中遇到的臭名昭著的process.env)。

在React中保存客户端状态需要react-refresh,它需要一些自己的Babel包作为依赖。这些包不是默认包含的,但可以使用更最大化的React模板。该模板拉入了react-refresh、Prettier、Chai和React Testing Library,总体的Node依赖包重达80MB。

npx create-snowpack-app my-react-project --template @snowpack/app-template-react
支持的文件

支持JSX,但同样,默认情况下只支持.jsx文件。Snowpack会自动检测是使用React还是Preact,并据此决定使用哪种渲染函数来进行JSX转换。但是,如果我们想进一步定制JSX,就需要通过他们的插件引入Babel。还有一个Snowpack插件可以用于Vue单文件组件,当然也可以用于Svelte组件。此外,Snowpack还可以编译TypeScript,但对于类型检查,我们需要TypeScript插件。

CSS可以导入到JavaScript中,并在运行时被扔到文档中。只要CSS模块的扩展名为.module.css,也支持开箱即用的scoping。

导入的JSON文件将被强制转换为一个JavaScript模块中,并以对象作为默认导出。Snowpack支持图片,并将其复制到生产文件夹中。为了配合它的非打包理念,Snowpack不将图像作为数据URL纳入捆绑中。

生产构建

默认的snowpack构建命令基本上是将源文件结构复制到一个输出文件夹中。对于编译成JavaScript的文件(例如TypeScript, JSX, JSON, .vue, .svelte),它将每个单独的文件转换成一个独立的浏览器友好的JavaScript模块。

这很好用,但对于生产来说并不是很好,因为如果源码被分割成很多文件,可能会引起大量的请求。在Snap Shot应用中,我最终得到了184KB的源文件,然后又从Skypack中请求了105KB的依赖关系,这就造成了一个非常大的请求。

然而,Snowpack将esbuild作为一个依赖项,我们可以通过在Snowpack配置中添加一个 "optimization "对象,使esbuild能够打包、最小化和编译我们的代码。

// snowpack.config.jsmodule.exports = {  optimize: {    bundle: true,    minify: true,    target:  es2018 ,  },

这样就可以使用esbuild提供的优化功能来运行代码,所以只要加入这些选项,我们就可以得到和之前使用esbuild一样的构建。

总结

Snowpack通过功能齐全的开发服务器、详细的文档和易于安装的模板提供轻量级的开发人员体验。你可以决定是否要打包你的应用程序以及如何打包。如果你想要一个既能提供开发服务器又能提供更有意见的构建步骤的工具,你可能会想看看我们列表中的下一个工具Vite。

查看更多文章分类,戳这里:point_down:

Vite

Vite是由Vue的创始人尤雨溪开发的。esbuild专注于构建步骤,Snowpack专注于开发服务器,而Vite则同时提供了这两点:一个完整的开发服务器和一个使用Rollup的优化构建命令。

用例

如果你想要一个严肃的create-react-app或Vue CLI的竞争对手,Vite是最接近的一个,因为它带有batteries-included的功能。快如闪电的开发服务器和零配置优化的生产构建意味着你可以在没有任何配置的情况下从零到生产。Vite可用于小型项目或大型生产应用程序,Vite的一个很好的用例是任何可观的单页应用。

你为什么不使用Vite?Vite是一个有成见的工具,你可能不同意它的意见。你可能不想使用Rollup来构建(我们一直在讨论esbuild有多快),或者你可能希望你的工具能够给你提供Babel、eslint和webpack加载器生态系统的全部功能。

另外,你想要零配置的服务器端渲染框架,你最好还是继续使用基于webpack的框架,比如Nuxt.js和Next.js,直到Vite服务器端渲染更加完善。

设置

Vite比esbuild和Snowpack有更多的默认值。它的文档清晰而详细。我们得到了对Vue的全面支持,尤雨溪是创建者,所以Vite是Vue开发者来说无疑是一条必经之路。也就是说,Vite可以和任何前端框架一起使用,甚至还提供了一个模板列表来帮助你入门。

用法

Vite的开发服务器非常强大。Vite通过esbuild将一个项目的所有依赖关系预先打包到一个单一的本地JavaScript模块中,然后用一个大量缓存的HTTP头来提供服务。这意味着在第一次页面加载后,不会在编译、服务或请求导入的依赖项上浪费时间。Vite还提供了清晰的错误信息,打印出准确的代码块和行号,以排除故障。同样使用Vite,我在引入使用node API或传统格式的依赖项时没有任何问题。它们似乎都被塞进了一个浏览器可接受的esmodule中。

Vite的React和Vue模板都引入了支持热模块替换的插件。Vue模板为一个用于单文件组件引入了Vue插件,以及一个用于JSX的Vue插件。React模板引入了react-refresh插件。无论哪种方式,都会给你提供热模块替换和客户端状态保存。当然,它们增加了一些依赖性,包括Babel包,但是,在Vite中使用JSX时,Babel其实并不是必须的。默认情况下,JSX的工作方式和esbuild一样--它转换为React.createElement。它不会自动导入React,但它的行为可以被配置。

同时,Vite并不像Snowpack和wmr那样支持流式导入。这意味着要像往常一样安装npm的依赖关系。

一个很酷的事情是,Vite包含了对服务器端渲染的实验性支持。挑选你所选择的框架,并生成直接运到客户端的静态HTML。目前,看起来我们需要自己构建这个架构,但这看起来还是一个很好的机会,元框架可以建立在Vite之上。尤雨溪已经有一个名为VitePress的作品正在进行中,它是VuePress的替代品,具有使用Vite的优点。而Sveltekit也已经将Vite加入了依赖列表。看来CSS代码拆分收录也是Sveltekit改用Vite的原因之一。

支持的文件

对于 CSS,Vite 提供的功能是我们所看到的所有工具中最多的。它支持打包CSS导入以及CSS模块。但我们也可以npm安装PostCSS插件,并创建一个postcss.config.js文件,Vite会自动开始将这些转换应用到CSS中。

我们可以安装和使用CSS预处理器--只需npm安装预处理器,并将文件重命名为正确的扩展名(如.filename.scss),Vite就会开始应用相应的预处理器。而且正如我们在概述中所说,Vite支持CSS代码分割。

图片导入默认为一个公共URL,但我们也可以通过使用URL字符串末尾的?raw参数将其作为字符串加载到捆绑中。

JSON文件可以在源代码中导入,并转换为esmodule导出单个对象。我们也可以提供一个命名的导入,Vite将在JSON文件的根字段中查找导入,并查找其余的treeshake。

生产构建

Vite使用Rollup进行预配置的生产构建,并进行了大量的优化。它有意提供了一个零配置的构建,这对大多数用例来说应该是足够的。

该构建包含了我们所期望的Rollup特性:打包、最小化和tree shaking。但我们也得到了一些额外的功能,比如代码分割动态导入和所谓的 "异步分块加载",这是一种花哨的说法,即如果我们请求导入另一个模块的JavaScript模块,构建将被预先优化,以同时加载这两个模块(异步)。

用Snap Shot应用运行Vite的默认构建,最终得到了一个5KB的JavaScript文件和一个160KB的JavaScript文件(总共165KB),项目中的所有CSS都被自动最小化为一个2.71KB的小文件。

总结

Vite的性质使其成为我们当前工具的严重竞争对手。许多工作已经完成,使开发人员的体验真正无缝,并使生产就绪的构建开箱即用。

wmr

和 Vite 一样,wmr 也是另一个成见的构建工具,它同时提供了开发服务器和构建步骤。它是由Preact的创建者Jason Miller打造的,所以对于Preact开发者来说,这绝对是一条幸福的道路。Jason Miller 在做客 JS Party 播客时解释了wmr背后的思路。

Preact很小,如果你想做一个轻量级的项目,它真的很好。我们的工具在哪里呢?我们有一个基于webpack的工具,在生产中被一堆高大上的网站所使用,但那是重量级的工具。原型开发工具在哪里?那是一方面。另一只手是我和一群碰巧在Preact团队里的人;我们已经在打包器生态系统的边缘徘徊了一段时间,鞭策人们,试图在一个方向上达成共识,我们可以朝着这个方向前进,以进一步推进这个编写现代代码和发布现代代码的想法。

这告诉我们,wmr就是要编写和发布现代化的代码,在项目中实现更轻的工具。

你可能想知道wmr代表什么?什么也不知道!wmr是什么意思?"Web Modules Runtime"和 "Wet Module Replacement"这两个名字被浮出水面,但这是一个假的缩写,类似于npm。

wmr和Preact一样采用了无情的bundle size purging,所以它的体积很小--重量只有2.6 MB--而且完全不包含任何npm依赖。不过,它还是设法打包了一大堆非常棒的功能,包括一个热模块替换开发服务器和一个优化的生产构建。

用例

如果我想用Preact尽快创建一个原型,我会用wmr。没有任何配置,下载只需要几秒钟。感觉就像在使用一个超强的静态文件服务器。通过TypeScript、优化的构建步骤和静态HTML渲染,wmr提供了发布中小型应用程序所需的一切。它的小尺寸也非常适合快速试用一个库或演示一个想法。

如果你不使用Preact、React或vanilla JavaScript,wmr可能不是你的工具。Preact团队还没有为其他框架提供模板。文档也没有我们看过的其他工具那么详细。这意味着你离开快乐的道路越远,你就会越深入地挖掘源头。所以,如果需要大量的定制,我不能推荐它。

设置

如果你使用的是Preact,除了快速安装npm之外,完全不需要任何设置。使用 React with wmr 而不是 Preact,目前有两个步骤。首先,在你的package.json中把htm/preact别名为htm/react,把react别名为es-react。

"alias": {  "htm/preact": "htm/react",  "react": "es-react"},

然后将引入es-react到你的组件中。

// ReactDOM only needed on root render(from code秘密花园)import { React, ReactDOM,} from  es-react ;

这意味着我们实际上并没有使用你可能习惯的普通React包,而是从es-react中引入React。这是因为wmr依赖于与本地JavaScript模块兼容的包。React默认不使用本地模块,而是使用一种称为UMD较老的模块样式。es-react是一个包,它可以拉入React,但提供与web平台兼容的导出。

这说明了wmr的理念,即使用web平台的原生基元,而不是使用工具来绕开和抽象掉。

另一种选择可以是在我们的应用中使用Skypack导入,这也是为了在浏览器中工作而预先优化的。

import React from  https://cdn.skypack.dev/react ;import ReactDOM from  https://cdn.skypack.dev/react-dom ;

wmr希望你写的是在浏览器中运行的现代代码,这可能意味着如果你引入使用node API或传统模块系统的依赖项,你需要做一些配置。为了让Snap Shot应用正常运行,我需要深入研究node模块,并将一两个库转换为使用本地JavaScript模块语法。如果你使用的是旧库,这可能会拖慢你的速度。Preact生态系统都经过优化,可以在浏览器中运行,应该不需要任何修改。这是在wmr中坚持Preact快乐之路的另一个原因。

wmr有插件,它公开了一个插件API,支持Rollup插件的构建步骤。docs上有越来越多的wmr专用例子,包括一个对HTML进行最小化的插件,还有一个基于文件系统的路由功能。

wmr支持不同的框架,但没有任何预先构建的模板。而且一开始我发现配置JSX变换相当困难。说到这里,Jason已经确认有计划让JJSX变得更可配置,而且wmr的目的是框架无关。JSX计划在普通JavaScript文件中开箱即用。

使用方法

要开始,你可以在命令行中运行这个命令。

npm init wmr your-project-name

或者,你也可以运行这些命令来手动构建你的应用程序。

npm init -ynpm install wmrmkdir publictouch public/index.htmltouch public/index.js

然后在index.html的正文中添加一个脚本导入(再次确保使用type="module")。

<script type="module" src="./index.js"></script>

现在你可以在你的index.js文件中写一个Preact hello world。

import { render } from  preact ;render(

Hello World ConardLi!

, document.body);

最后启动你的开发服务器。

node_modules/.bin/wmr

现在我们有了一个完整的热模块替换开发服务器,它会立即响应我们源代码的任何变化。

wmr在转换JSX时使用了一个叫htm的工具,它提供了一些很棒的好处。比方说,我们在wmr中使用Preact写一个计数器,却犯了一个错误。

import { render } from  preact ;import { useState } from  preact/hooks ;function App() {  const [count,setCount] = useState(0)  return <>   // HIGHLIGHT  

count: {count}

}render(, document.body);

count在onClick处理函数中拼写错误,所以运行这个函数会出现错误。通常情况下,我们必须依靠我们的工具和source map来收集关于错误所在的信息,但wmr采取了不同的解决方案。对于htm,通过使用标记的模板文本,这可以尽可能地接近浏览器中的原生JSX。所以,在哪里写React或Preact代码通常是这样的。

I am JSX. I am not actually valid Javascript

...htm看起来更像这样。

html`<${MyComponent}>I am about as close as it gets to JSX as you can get while being able to run in the browser`

现在,如果我们正在调试我们的代码,打开DevTools中的"Sources "面板,我们应该会看到一个脚本,它与源代码在编辑器中的样子几乎相同。

通过这种方式,我们就可以正确地调查错误在浏览器中的位置,而不必使用source map。当然,这个具体的例子是很造作的,但你可以看到这可能是非常有用的,因为这意味着wmr在你的开发环境中不需要source map。

wmr默认支持流式导入,所以裸露的导入将从npm注册表中拉下来。这是通过一个复杂的过程来完成的,这个过程会检查npm包中的所有源码,删除所有的测试和元数据,并将其转换为一个单一的本地JavaScript导入。与Snowpack类似,可以在不使用npm安装任何东西的情况下构建一个复杂的应用程序。事实上,wmr是第一个支持这种想法的工具。

支持的文件

至于wmr支持的其他类型的文件,CSS文件可以用JavaScript导入,CSS模块也支持。

Vue单文件组件和Svelte组件都没有内置支持。不过,wmr的构建步骤可以和Rollup插件一起使用,开发服务器也可以配置Polka/Express中间件,所以可以用这些来将导入的文件转换成Vue和Svelte组件。事实上,我为Vue单文件组件写了一个小插件来展示如何做到这一点。

在没有插件的情况下,我们不能在wmr中把图片作为数据URL导入到JavaScript中。相反,我们需要使用一个语法正确的JavaScript方法来导入它们。所以,如果我们在公共文件夹中有一张狗的图片,我们可能会把它包含在Preact组件中,比如这样。

function Dog() {  return dog hanging out}

而一旦构建步骤运行,图片就会被复制,并从分发文件夹中访问。开发服务器中的图片有热模块替换,所以有图片的变化会立即反映在浏览器中。

再来说说文件支持。JSON可以导入,并转换成JavaScript对象使用。但实际构建应用时,我们就需要Rollup JSON插件了。

生产构建

wmr提供了一个生产构建步骤,包括打包、小型化和tree-shaking,而不需要任何额外的依赖。看了一下wmr的源码,似乎在引擎盖下使用了rollup和terser,wmr包中包含了这些的minified版本。Snap Shot应用的wmr捆绑包是164KB,所以它创建的捆绑包只比Vite创建的两个JavaScript文件的总大小小一点点。

还有一种方法可以将wmr配置为这样一种方式,它使用preact-iso在浏览器上将一个应用程序渲染为静态 HTML 并加工。这意味着wmr可以作为Preact的元框架使用,类似于Next.js。

总结

我喜欢使用wmr来为React和Preact应用做原型的体验。使用一个小得离谱但却能提供开发者便利的工具,接近于匹配重量级打包器,感觉很棒。

特征比较

我们刚刚分析了很多地方! 与其在这篇文章中上下滚动比较结果,我已经将所有内容汇编在这里,以查看这些工具并排时的堆叠情况。我甚至为我们没有明确提到的特性添加了额外的比较。

用例设置开发服务器生产构建其他特性最后

我很高兴能够用我们刚刚看到的所有工具来构建JavaScript应用程序。无论我们是在编写一个小型的辅助项目还是一个大型的网站,所有这些工具都能加快反馈循环,提高生产力。它们已经打开了大门,问我们在JavaScript生态系统中需要什么,以及我们是否可以开始失去传统模块和浏览器带来的麻烦。这些工具将通过提供一个更精简、更快速的开发者环境,在编写的代码和运行在浏览器中的代码之抽象更少,从而降低了新开发人员的进入门槛。

如果你已经厌倦了等待下载依赖和运行构建步骤,我建议你尝试一下这种新一代的工具。

其他的 JavaScript 新工具Rome– 一个完整的工具链,包括linting、编译、捆绑、测试运行和格式化SWCRustJavaScript/TypeScriptDeno–JavaScript和TypeScript的运行时(类似于Node.js)

关键词: 应用程序 生态系统 提供了一个 秘密花园 我们需要

相关新闻

Copyright 2015-2020   三好网  版权所有