Web开发

首页 » 常识 » 诊断 » RollupvsParcelvswe
TUhjnbcbe - 2022/12/7 15:06:00
Rollupvs.Parcelvs.webpack

对于那些没有JavaScript背景的用户来说,打包工具可以从应用程序的入口文件递归地跟踪所有导入的文件,并将它们打包成一个文件。打包工具还可以通过删除不必要的空格,换行,注释,还可以切割成小块的文件而不会影响其功能。

让我们通过一个简单的例子来理解它:

vartest=[];for(vari=0;i;i++){test=i;}

我们创建了一个数组叫test,然后初始化它的值为从0到99。压缩后的代码如下:

for(vara=[i=0];++i20;a=i);

字符和行数更少。你可能要说代码不可读了,但是谁在乎呢?代码写完了然后打包,压缩后的代码更容易被浏览器加载和解析。

现在你很容易就理解了打包工具的重要性了,对吗?

假设你的代码未打包,然后以多个文件的形式托管在服务器上。代码运行时为了导入每个文件,浏览器必须为每个文件向服务器发送单独的HTTP请求。这种传输的效率与所请求文件的数量和大小成正比。对于诸如Facebook之类的大型应用程序,其性能和用户体验可能会是一场灾难。

但是,通过使用打包工具,应用程序的性能将大大提高,因为现在浏览器只需要请求一个文件即可向用户显示你的应用程序。此外,获取一个只有几KB的压缩文件比实际的文件要快,而实际的文件可能会有几MB,从而缩短了应用程序的加载时间。

既然我们可以自己做为什么还需要打包工具?

当然可以,但是你的代码库庞大时,手动压缩代码不是灵活的解决方案。让打包工具为你服务!

取决于具体的使用场景,选择正确的打包工具会极大改善你的应用程序。

打包工具的配置

Parcel胜出。因为它根本无需配置文件。只需要安装Parcel后然后编译,它开箱即用地为你完成一切工作。

webpack和Rollup都需要一个配置文件,用于指定入口,输出,加载器,插件,转换工具等。不过有点区别:

Rollup有import/export的node兼容库,但webpack没有。Rollup支持在配置中使用相对路径,但webpack不行—那就是为什么你需要使用path.resolve或者path.join

webpack配置可能会变得很复杂,但是支持第三方导入,图片导入,CSS预处理等众多功能。

我在用Rollup打包项目时遇到了困难,那个项目用到了axios,还有其他第三方库。我不得不搜索资料然后安装了许多Rollup插件才成功了,这还是在舍弃了一些文件导入的前提下。

死代码消除

死代码消除,也常称为Treeshaking,对于优化文件包大小和性能来说非常重要。

Parcel在这局是胜出者。它为ES6和CommonJS模块两者都支持treeshaking。这点是革命性的,因为npm中的大多数代码仍然在用CommonJS格式。

在消除死代码时Parcel的大部分工作利用了多个工作线程来并发运行,同时会缓存在文件系统里。这意味打包很快,重新打包超快。

Rollup在这项排名第二。开箱即用,它会静态分析要导入的代码,并将所有未使用的内容排除在外。这样可避免你在配置中写入更多代码,增加额外的依赖关系并增加应用程序的大小。

webpack做treeshaking需要额外的一些工作:

使用ES6句法(即import和export)在package.json中设置SideEffects引入一个支持删除死代码的工具(例如UglifyJSPlugin)

Rollup和webpack更加专注与为ES6做treeshaking,因为做ES6的静态分析容易很多,但是为了发挥更大作用,我们也需要分析CommonJS的依赖,这两个工具都需要导入插件。

但是,考虑到JavaScript是动态的,这门语言的每种结构在运行时会可以被修改。

这就意味着一个作为指针被导入的类,无法被静态分析以删除其没有用到的动态和静态属性。最好不要依赖于打包工具,最好在写代码之前先把组件关系图画一下,然后分析它们以获得最佳效果。

代码分拆

随着应用程序的增长,包的大小也会随之增加,导入的第三方包也会增多。应用程序的加载时间与包大小成正比。

代码拆分可帮助浏览器仅延迟加载使应用程序运行所需的内容,从而显著提高性能和用户体验。

webpack以最少的工作量和更快的加载时间在这方面成为赢家。它提供了三种方法来启用代码拆分:

定义入口文件-使用entry配置项手动拆分代码使用CommonsChunkPlugin动态导入-在模块内部使用行内函数调用在Rollup的代码分拆中,你的代码块自身就是标准的ES模块,使用浏览器内置的模块加载器,没有任何额外的开销,但是仍然能够充分利用treeshaking的功能。对于尚不支持ES模块的浏览器,你也可以用SystemJS或其他的AMD加载器。它是完全自动化的,并且代码重复为零。

Parcel支持零配置代码拆分。它的代码拆分是通过使用动态import()函数语法建议规范来控制的,该建议类似于常规的import语句或require函数,但是返回Promise。这意味着该模块是异步加载的。

使用Rollup和Parcel而不是webpack进行代码拆分看起来很有诱惑力,但是它们都只是在最近才引入了此功能,并且据说还有一些问题待解决。所以,可以安全地使用旧的Webpack。

我发现一个令人信服的事实是,对于启用了代码拆分的相同代码,使用webpack的构建时间最少,其次是Rollup,最后是Parcel。

实时重新加载

在开发阶段,你修改代码后应用自动实时重新加载这点很棒。一个有实时重新加载功能的打包工具可以自动帮你完成这个操作。

除其他对于调试和开发必不可少的工具外,打包工具还以开发服务器的形式为您提供了一个运行时环境。

通过内置开发服务器,Parcel考虑得很周到,当你更改文件时,该服务器会自动重新打包你的应用程序。但是在使用HTTP日志记录,挂钩和中间件时,存在一些问题。

在使用Rollup时我们需要安装并配置rollup-plugin-serve,它提供了实时重新加载的功能。不过它需要另一个插件rollup-plugin-livereload才能工作,也就是说它不是一个独立的插件,需要另外的依赖才能工作。

使用webpack,你只需要添加一个名为webpack-dev-server的插件,它提供了一个默认开启了实时重新加载功能的简单版开发服务器。更好的是什么呢?你可以在开发服务器启动并运行后使用Hooks进行某些操作,添加中间件,还可以指定运行我们的开发服务器时要使用的文件。Webpack的这种可定制性胜过Rollup和Parcel。

热模块替换

热模块替换(HMR)通过在运行时自动更新浏览器中的模块而无需刷新整个页面,从而改善了开发体验。在代码中进行少量更改时,可以保留应用程序状态。

你可能会问热模块加载与实时重新加载有何不同。

是这样的,当一个文件更改时实时重新加载会重新载入整个应用程序。例如,如果你位于应用程序的第五个访问层级,然后保存一处修改,这时实时重新加载会重启整个应用,加载后回到落地页/首页。

对应的是,热模块替换仅刷新已更改的文件,同时仍保持应用程序的状态。例如,如果你位于应用程序的第五个访问层级并保存了CSS的修改,则状态不会更改:你仍在同一页面上,但是新样式将会应用。

webpack拥有自己的Web服务器,称为webpack-dev-server,通过它可以支持热模块替换。它可以在开发中用作实时重新加载的替代品。

Parcel已经内置了对热模块替换的支持,Rollup上个月发布了一个插件rollup-plugin-hotreload来支持热加载。

由于在Rollup和Parcel这类打包工具中是新功能,安全起见我仍然选择webpack,因为我在开发时不想遇到能避免的问题。

模块转换

打包工具通常只知道如何读取JS文件。转换器(transformer)本质上是老师,告诉打包工具如何处理JS之外的文件,如何把它们添加到应用程序的依赖图表中然后打包。

例如,在上图中你可以看到一份webpack配置,它在第13行到15行描述了如何读取CSS文件。它的基本内容是“webpack,当你遇到一个解析为.css的文件时,使用上面导入的css-loader读取它然后导出为一个字符串。”类似的,HTML加载器会告诉webpack在应用遇到.html文件时如何读取并导出为字符串。

Parcel非常巧妙地处理转换过程。Rollup和webpack需要你指定要转化的文件类型,安装并配置插件来转换它们。但Parcel和它们不同,它为许多常见的转换和编译器提供了内置的支持。

当在模块中找到配置文件(例如.babelrc,.postcssrc,.posthtml等)时,Parcel会自动运行对应的转换器。除了.babelrc中指定的任何转换之外,Parcel始终在所有模块上使用Babel将现代JavaScript句法编译为浏览器支持的格式。

总结

如下是我实验得出的结论:

构建一个简单的应用并让它快速运行起来?使用Parcel。

构建一个类库只需要导入很少第三方库?使用Rollup。

构建一个复杂的应用,需要集成很多第三方库?需要代码分拆,使用静态资源文件,还有CommonJS依赖?使用webpack。

1
查看完整版本: RollupvsParcelvswe