作为奇舞团的一个小小程序媛,每天都在不断地接受新知识,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领取资料,交流学习