Parcel前端部署打包我爱编程

初探parcel及如何简单写plugin

2018-01-15  本文已影响112人  Gary嘉骏

前言

入了前端坑,哪有不研究下打包工具的。但本人还是拖了好久才把webpack作了较全面的了解,webpack确实是十分灵活,这得益于其较多的配置项,特别在resolve里,能达成某些奇特的结果。其外,loader解析文件,plugin注入钩子,修改打包过程。可以说,webpack是十分万能,再复杂的项目也能够驾驭。但是,这些复杂的配置,对于初学者是十分不友好的,即使是再简单的项目,还是要写出一个基本的配置项,这时候往往要到官网去复制粘贴,有时忘记的某个配置项的作用,又要重新找(2018/1/15了解到webpack4.0终于要增加默认配置了issue)。即使你是较了解webpack了,但还有各种优化坑等你,不然开发构建慢、打包出来的js块十分大,没有懒加载、无法清理缓存。

前一段时间,parcel出来,号称零配置,开箱即用(其实有时还是要写配置文件,不过是主要是针对某些plugin,如:typescript)。除零配置之外,还号称在某些情况能大大加快打包速度,理由是针对一个文件只会编译一次,即使是由多个plugin,这是使用的AST的好处。还有一个比较符合我们前端的设计,入口文件就是html。

使用

node的版本请必须的8以上,在源码及其他人提供的plugin源码中,都能容易看到对node是否8以上的版本的判断,低于8的话往往是会报错的,因为基本都使用了async的语法。

使用parcel,开发时就基本只需要使用以下两个命令:

parcel index.html
parcel build index.html

目前官方已针对各大框架写了例子,还有推荐的各种plugin,地址:awesome-parcel

各例子其实也十分简洁,没有配置项,只是在package.json里帮你加好打包需要的plugin。

再复杂的例子的话,如vue+typescript的话要自己去加plugin,这个我刚好找到一个vue+typescript

想自己从头敲学习的话,可以看这个all-you-need-to-know-about-parcel

编译过程及plugin

对于如此友好的打包文件,当然是要了解下其过程,还有plugin的编写,方便以后确实需要自己去修改plugin或写自己的plugin的时候。

在源码的src里,cli.js是脚本命令入口,在里面会导入真正的编译入口Bundler.js,并构建对象

const bundler = new Bundler(main, command);

打包前bundler.start是一定会运行的,其中就会加载并注册plugin,怎么加载的呢?就是把package.json的plugin依赖都加载了。

let deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
      for (let dep in deps) {
        if (dep.startsWith('parcel-plugin-')) {
          let plugin = await localRequire(dep, this.mainFile);//加载
          await plugin(this);//注册
        }
      }

所以我们需要什么plugin,只要把其加入到package.json里就好,虽然可以发现放在生产依赖里也行,但这些明显是开发使用的,还是放在开发依赖中比较好,而且优先级也更高,不会被覆盖。

接着我们进入到plugin,官网内置的plugin其实都在parcel-bundler\src\assets里,只是不叫plugin,他们都继承于parcel-bundler\src\Asset.js里的Asset,其中parse方法就给用来自定义编译内容的。

默认会注册以下插件(是根据文件扩展名去使用对应的插件):

this.registerExtension('js', './assets/JSAsset');
    this.registerExtension('jsx', './assets/JSAsset');
    this.registerExtension('es6', './assets/JSAsset');
    this.registerExtension('jsm', './assets/JSAsset');
    this.registerExtension('mjs', './assets/JSAsset');
    this.registerExtension('ml', './assets/ReasonAsset');
    this.registerExtension('re', './assets/ReasonAsset');
    this.registerExtension('ts', './assets/TypeScriptAsset');
    this.registerExtension('tsx', './assets/TypeScriptAsset');
    this.registerExtension('coffee', './assets/CoffeeScriptAsset');
    this.registerExtension('json', './assets/JSONAsset');
    this.registerExtension('yaml', './assets/YAMLAsset');
    this.registerExtension('yml', './assets/YAMLAsset');
    this.registerExtension('gql', './assets/GraphqlAsset');
    this.registerExtension('graphql', './assets/GraphqlAsset');

    this.registerExtension('css', './assets/CSSAsset');
    this.registerExtension('pcss', './assets/CSSAsset');
    this.registerExtension('styl', './assets/StylusAsset');
    this.registerExtension('less', './assets/LESSAsset');
    this.registerExtension('sass', './assets/SASSAsset');
    this.registerExtension('scss', './assets/SASSAsset');

    this.registerExtension('html', './assets/HTMLAsset');

这样就比较明白如何简单写出一个plugin了,首先项目名需要parcel-plugin-
来作开头。

新建自己的asset文件,并导入继承Asset的对象,并编写parse方法;

最后plugin入口index.js:

module.exports = function (bundler) {
    bundler.addAssetType('你针对的文件扩展名', require.resolve('你的asset文件'));
};

最后

parcel的热度确实比当年的webpack高,但目前来看,其生态还不完善,即使是官网推荐的plugin,里面的某些功能也是表示在实验中的,不建议现有比较复杂的项目从webpack迁移到parcel里。比较简单的起始项目推荐去尝试。

你们的赞赏是我的无限动力

上一篇 下一篇

猜你喜欢

热点阅读