美文网首页
一个比 webpack 快10倍的打包工具

一个比 webpack 快10倍的打包工具

作者: 美洋洋_4f15 | 来源:发表于2017-12-18 16:46 被阅读0次

    作为奇舞团的一个小小程序媛,每天都在不断地接受新知识,PostCSS刚学完,PostHTML又出来了。刚研究明白Rollup的配置,又有一个横空出世的打包工具——Parceljs。

    我本来是拒绝的,毕竟在这个充满诱惑的年代,我要维持自己内心的纯洁,但当我打开Parcel的官网,看到下面的benchmark数据,我就不淡定了。

    居然带缓存的时候比webpack快10倍!!!

    虽然是官方给出的单例测试,但是在4个CPU的2016年MPB,拥有1726个模块, 6.5M的未压缩文件的app上跑出这个成绩,简直是令人心动不已!

    虽然“又小又快又容易”在自然界中某些场合下并不见得是什么好事,但是在如今的前端领域,这个词简直是对这种解放人类天性的打包产品最好的褒奖!

    parcel可以说是将贯彻到极致。一个月前,我由于无法忍受(实际上是因为看不懂记不住)webpack繁复的配置,而拥抱了Rollupjs,然后看到了Parcel之后,估计我又该”移情别恋“了!

    据官方介绍,Parceljs拥有这样超快打包速度的原因得益于它开启了多进程打包,并使用文件系统缓存机制,从而提升了重启后重打包的速度。

    开始入手

    对于parcel,入手过程堪称傻瓜式~

    可以使用 Yarn 或者 npm进行安装,对于我们这些年轻的FEer,当然是选择npm了

    JavaScript

    1

    2

    3

    // 全局安装 parcel

    $npminstall-gparcel-bundler

    下面就可以开始尝试文件打包了.

    Parcel与众不同的一点是,它可以使用任何类型的文件作为入口文件,但是官方推荐是用HTML文件或者是JavaScript文件,如果你在HTML文件中引入了一个相对地址的JavaScript文件,Parcel也会自动给将相对于HTML的地址替换为相对于输出文件的地址,真是超级贴心!

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    // index.html文件

    // index.js 文件

    console.log("hello world");

    如果你的项目没有自己的服务端,感谢Parcel有一个内置的Dev Server👏,你可以使用Parcel提供的这个Dev Server,它会在你修改文件之后自动兼听你的文件改变进行重打包,同样可以配置HMR来加快开发速度。

    但是具体怎么添加HMR,这就是后话了,大家收!

    当然,如果你的项目有自己的服务端,你可以不使用这个Dev Server,而文件自动监听重打包和HMR也不会受影响。运行下面的代码,你就会在自己目录里面看到一个装满打包好文件的/dist文件夹。

    如果你已经为上线做最后一次打包的准备,你可以直接用build模式,Parcel将不会开启监听,只会编译一次!而且Parcel会在生产模式的时候使用 uglify-js ( JavaScript), cssnano ( CSS), 和 htmlnano ( HTML)进行压缩混淆处理。

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    // 没有服务端的时候,启动一个dev server,运行在10086端口

    parcelindex.html-p10086

    // 开启服务端的时候,开启watch模式

    parcelwatchindex.html

    // production 模式,没有比上线更令人开心而恐惧的事情了

    parcelbuildindex.html

    Parcel的食物——Assets

    如果说打包工具是一个人的话,那么他吃进去了一堆文件,又输出了一堆文件(这里我用的是输出。。。)。

    对于Parcel来说,他的食物其实可以是任何类型的文件,但是Parcel对于JavaScript、CSS和HTML文件有着天生的优秀的支持度。Parcel可以自动分析文件中的依赖,然后将这些依赖打包到最终的输出文件中。

    JavaScript

    对于最好吃的JavaScript来说,Parcel支持cjs和es6两种语法,他同样可以支持动态import()来异步加载文件,这一点对于之后会谈到的代码分割来说很重要。

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    // 使用Cjs引入module

    constdep=require('./path/to/dep');

    // 使用es6引入module

    importdepfrom'./path/to/dep';

    对于在JavaScript文件中引入的非JavaScript资源来说,比如CSS,你可以使用import将其引入,他会将所有的同类型文件放在一个另外的单独的打包文件内。对于最终的输出文件来说,这些资源就是一个一个的URL,直接引用就好了,其他的文件类型也是一样的。

    而如果你非要坚持inline一个文件的话,就需要你去使用Node.js的fs.readFileSyncAPI了。注意,所用的URL是静态分析的,意味着你不能在URL中拼接变量了,当然__dirname和 __filename除外,对于这些“内部员工”你也没啥办法了!

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    // index.js 中可以这样引入css和其他资源

    // 引入CSS文件

    import'./test.css';

    // 从CSS文件中引入一个CSS模块

    importclassNamesfrom'./test.css';

    // 引入一个图片文件

    importimageURLfrom'./test.png';

    // 如果你非要坚持用inline,你只能这么做

    importfsfrom'fs';

    // 以字符串形式读取内容

    conststring=fs.readFileSync(__dirname+'/test.txt','utf8');

    // 以buffer形式读取内容

    constbuffer=fs.readFileSync(__dirname+'/test.png');

    CSS

    对于CSS来说,她不光可以被JavaScript和HTML引用,自己也可以使用@import引入其他的CSS资源,这样引入CSS资源的时候,Parcel会将其inline进来。

    而在CSS中引入的其他资源,要使用url(),比如图片和字体神马的,Parcel就会将其改为相对于输出文件的路径,但是你写的时候还是要相对于当前的CSS路径的。

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    /* 引入其他css */

    @import'./other.css';

    .test{

    /* 引入一个图片 */

    background:url('./images/background.png');

    }

    对于Parcel来说无论你是炒CSS还是煮CSS。。。我是说无论是LESS, SASS 还是Stylus,他都一视同仁,采取同样的处理方法,从不挑食。

    HTML

    你可以将HTML视为Parcel的入口,但是他也可以被引入一个JavaScript文件中。对于其中的各种scripts, style, media 的URL,与上面的处理方式是一样的,但是一定要注意,路径是相对于当前文件的!!

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    Linktoanotherpage

    各种转换工具

    与很多(你知道的,例如webpack,rollup这样的)打包工具不同,Parceljs天生集成了Babel,PostCSS,PostHTML,只要Parcel发现了这些的配置文件,他就会自动run这些转换工具。

    另外一个神奇之处在于,对于一些第三方的node_modles里面发布时带的配置文件,Parcel都可以为他自动开启编译程序,而且只会加载有用东西,所以当你引入一些特定的文件的时候,无需手动而配置和了解他是怎么样子build的,也可愉快地使用了。

    代码分割技术

    上文中我们提到的动态加载,也就是使用import()来加载依赖,这种新奇的写法在Parcel上有了用武之地。Parcel不需要额外配置,只要他发现代码中有使用import()引入的模块,就会自动的进行代码分割。最终生成的打包文件夹中,就会将这些模块打包成独立的文件,而在主文件中使用URL的形式引入,最后的主文件打包体积更小、加载速度更快~

    如果你已经习惯了之前在文件顶部去集中import的话,也不用担心。在Parcel中动态加载是可以进行懒加载的,你可以使用下面的写法。事实上,这些子打包文件,只会在你使用的时候才加载进来,四不四很开心啊!

    JavaScript

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    // 建立一个要动态加载的页面名字的索引地图

    // 这些页面实际上只会在真正使用的时候去加载

    constpages={

    about:import('./pages/about'),

    blog:import('./pages/blog')

    };

    asyncfunctionrenderPage(page){

    // 懒加载请求页面

    constrender=awaitpages[page];

    returnrender();

    }

    想要对动态加载有更深入的了解,可以回翻我们之前的文章,《 chrome63支持动态 import() 》。

    🌟注意哦!因为动态加载返回的是一个Promise,所以你是可以用async/await的,但是如果你的浏览器是不支持这个写法的话,一定要使用bable-polyfill(app)或 babel-runtime& babel-plugin-transform-runtime(library)

    HMR 模块热替换

    HMR(Hot Module Replacement)模块热替换可以说是改变FE生活,拯救懒癌末期患者的福利技术。他会自动更新浏览器端的改变的模块,而不需要重新去reload整个页面,大大提升了开发速度。     据官方称, Parcel的HMR实现支持JavaScript和CSS,而且会在生产模式的时候自动禁止掉。当改动保存后,Parcel会将改变的内容重新打包,并发送一个update的信号通知所有运作的端,比如说你的浏览器。     但是实际我测试结果发现,js的改变应该是可以进行热替换的,但是CSS改变之后,页面并没有反应,如果我想让他有反应的话,就需要配置PostCSS。蜜汁尴尬啊,人家只是想单纯地写一个css而已。。。。

    更友好的日志信息

    当运行Parcle的时候,终端里面打印的日志中会显示目前打包的进度,以及打包完成所耗费的时间。Mac用户还有一些惊喜的福利,就是会出现一些很可爱的emoji,让等待也不会无聊,比如这样:

    当打包遇到问题的时候,Parcel会打印出来带有语法高亮的代码,让你更容易的去进行排错。

    总结

    总之,Parcel对于一些希望快速搭建项目的人来说,是一个节省时间的方式,这种0配置的打包工具可以极大减轻项目搭建初期的工作,私下称它是“打包保姆”也不为过。

    但是如果你想要有些个性化的处理,比如说在rollup中就提供了一个可以将打包文件中的代码排成想要的形状的插件,Parcel可能就无法帮你实现了。想知道我说的这个插件什么,并且对Rollup有更深入的了解的话,你可以去我的PPT看一看,rollup 小巧又有趣打包工具-声享: https://ppt.baomitu.com/d/e0af330f

    下面我精选了一些知乎上对于Parcel的评价,如果侵犯了答主的著作权,可以在奇舞周刊的后台联系我~

    陈成

    链接:https://www.zhihu.com/question/263676981/answer/272172727

    看到 ParcelJS 还是眼前一亮的。新建 index.html、index.js 和 index.css,然后 parcel index.html,就能拿到可运行的 html、js 和 css 组合。html 可以作为入口正是我期望的,这让前端开发回归到本来的状态,很舒服。

    ParcelJS 是以 assets 方式组织的,assets 可以是任意文件,所以你可以构建任意文件。而在 webpack 中,只有 JS 是一等公民(webpack@4 会增加 CSS 为一等公民),所以必须是以 JS 为入口去组织其他文件,这很别扭。

    速度是 ParcelJS 主要卖点。体验下来确实快,原因是多核(通过 worker 平行构建)和文件系统缓存(二次构建会快,和 webpack 的 dll 异曲同工)。不过 webpack 也有多核处理 loader 和压缩的插件,没对比过,不知道差异如何。另外 webpack 的构建速度慢在 dev 模式下还是可以的,主要还是压缩慢,在压缩速度上没有突破,仅提升编译速度,只能解决一部分问题。

    关于 0 配置。ParcelJS 本身是 0 配置的,但 HTML、JS 和 CSS 分别是通过 posthtml、babel 和 postcss 处理的,所以我们得分别配 .posthtmlrc、.babelrc 和 .postcssrc。功能上,Code Splitting 和 Hot Module Replacement 没啥新的,和 webpack 等工具相同。

    对于我来说,功能目前还缺 SourceMap、公共文件提取、publicPath 配置(Code Splitting 需要)、Tree Shake 和 Scope Hoist 等。很好的开始,持续维护的话应该不缺用户。

    周左左

    链接:https://www.zhihu.com/question/263676981/answer/271919415

    但是对于打包工具来说速度不是最首要的,生态才是。

    下面从实践出发谈谈我个人对打包工具的理解

    曾经

    打包工具的出现,很大程度上缓解了传统的手动引入资源文件(css, js等)到html带来的不便。从。从最初的require.js模块加载库以及相关规范出现开始,社区就开始进行各种尝试。到gulp利用pipe以及watch概念来构建前端自动化流程,之后引入了browserify打包作为构建工具中的一环,最终到了现在webpack集大成者。

    webpack当年首先是作为一款与browserify功能相当的打包工具/库,出现在社区中的。所以你会常常看见社区里的教程/问答贴:gulp + webpack或是gulp + browserify。当然还有但是风韵犹存的grunt,以上组合可以自行想象。

    之后webpack重点开发了自身作为一个构建工具的作用,而不是仅仅作为一个打包库寄人篱下。在这之前,我们都没见过打包工具需要去监听文件变动而触发打包动作(例子一个),他们都只是从gulp/grunt这种构建工具的pipe来获取到具体变化,再去执行打包动作。所以一句话,像监听变化、assets资源优化等等这种事情,在以往打包工具/库是触及不到的。打包工具只针对js作为入口文件,递归获取依赖,建立依赖树,逐个利用自带的或第三方的中间件来最终输出bundle js。

    当下

    刚刚提到webpack不满足于自己仅仅只是一介打包工具而存活于世,或是说社区本意就是将它打造成为一款前端项目构建工具。webpack推出了一系列的功能,渐渐发觉,gulp能做的事情,现在webpack都能做到了,甚至还多了一系列的gulp配合打包库才能做到的功能。Parcel无配置,从assets出发的构建工具,崭露头角。

    我超喜欢在webpack的 个个loader、plugin都是人才说话又好听

    未来

    未来肯定是属于操作简单便捷的构建工具的,它要能支持js、html、css三剑客的打包,速度足够快,生态够好。但是依然要有定制性:

    1.一半是传统多页面应用,一半是SPA的业务场景。

    2.添加各种稀奇古怪的js语言。

    3.针对css进行优化,像js那样能够提取出common chunk。webpack 4添加了许多特性对css打包进行了支持。我们拭目以待。

    4.针对业务进行分组打包,而不是所有的entry都要强制打包(目前可以利用多config特性来解决,但是要小心webpack-dev-server的坑)。

    思考:针对场景的配置成本

    如果你要使用react,就用create-react-app,如果你要使用angular,就用angular-cli。

    但是如果你不用前端框架,或者嫌这些cli太重了,或不透明(其实不然),当然可以用parcel。

    但是如果你又要引入typescript或者一些其他神奇的plugin到parcel中,那么又成了铁头娃、填坑侠。

    +群289683894领取资料,交流学习

    相关文章

      网友评论

          本文标题:一个比 webpack 快10倍的打包工具

          本文链接:https://www.haomeiwen.com/subject/cdbabxtx.html