Rollup 概述

Rollup同样是一块ES Module的打包器,那他也可以将我们项目当中散落的细小模块打包为整块的代码,从而使这些划分的模块可以更好的运行在浏览器环境,或者是nodeJs环境。

那从作用上来看Rollup与webpack非常类似,不过相比于webpack,Rollup要小巧的多。

因为webpack再去配合一些插件的使用时几乎可以完成我们开发过程中前端工程化的绝大多数工作,而Rollup他仅仅可以说是一个ES Module的打包器,并没有其他额外的功能。

那例如webpack中有对于我们开发者十分友好的hmr也就是模块热替换这样的功能,在Rollup中就没办法支持。

那Rollup诞生的目的呢并不是要与webpack之类的工具去全面竞争,他的初衷只是希望能够提供一个高效的ES Module的打包器,然后充分利用ES Module的各项特性构建出结构比较扁平,性能比较出众的类库。

至于他其他的一些特点和优势,我们需要上手过后,才能了解。

Rollup 快速上手

这里我们准备了一个简单的示例,在这个示例中我们使用的是ES Module的方式组织的代码模块化,在这个示例的源代码当中准备了三个文件,其中message.js中以默认导出的方式导出了一个对象。

export default {
    hi: 'Hey Guys, I am yd~'
}

而logger.js当中导出了两个函数成员。

export const log = msg => {
    console.log(msg);
}

export const error = msg => {
    conole.log('------ ERROR ------')
    console.log(msg);
}

在index.js中导入这两个模块,并且使用了他们。

import { log } from './logger';
import message from './message';

const msg = message.hi;
log(msg);

接下来我们尝试使用rollup对这个示例应用打包,我们需要先安装这个模块, 通过开发模式安装。

yarn add rollup --dev

安装完成过后rollup自带了cli程序,我们可以通过cli去使用rollup打包。

我们这里通过yarn rollup运行rollup程序。因为yarn可以自动找到node_modules当中给的cli程序。避免我们手动通过路径去查找cli。

执行过户我们可以发现,在不传递任何参数的情况下,rollup会自动打印出帮助信息,在帮助信息一开始的位置就已经告诉我们rollup的正确用法。我们这里应该通过参数去指定一个打包入口文件。

我们再次执行这个命令, 我们这里的打包入口应该是src下面的index.js文件。

yarn rollup ./src/index.js

此时我们的命令行会报出一个错误,大概的意思是说应该指定一个代码的输出格式,那输出格式的概念我们应该并不陌生,意思就是希望吧ES Modules的代码转换过后,以什么样的格式去输出。

我们这里可以使用--format参数指定输出的格式,这里我们先选择最适合浏览器端的iife 也就是自执行函数的格式。

yarn rollup ./src/index.js --format iife

此时我们打包的结果就被打印到控制台当中了,我们还可以通过--file指定文件的输出路径,我们这里指定到dist文件夹下的bundle.js,这样的话我们的打包结果就会输出到文件当中。

yarn rollup ./src/index.js --format iife --file dist/bundle.js

完成以后我们找到rollup的输出文件,打开这个文件我们第一印象就是rollup他的打包结果惊人的简洁,基本上和我们以前手写的代码是一样的,相比于webpack当中那些大量的引导代码,还有一堆的模块函数,这里的输出结果几乎没有任何的多与代码。

他就是把我们打包过程中各个模块按照模块的依赖顺序先后的拼接到一起,而且此时我们仔细去观察打包结果,你会发现,在我们的输出结果当中他只会去保留那些用到的部分,对于未引用的部分都没有输出。

这是因为rollup默认会自动开启tree-shaking去优化输出的结果,那tree-shaking这样一个概念,最早也就是在rollup这样一个工具中提出的。

(function () {
    'use strict';

    const log = msg => {
        console.log(msg);
    };

    var message = {
        hi: 'Hey Guys, I am yd~'
    };

    const msg = message.hi;
    log(msg);

}());

Rollup 配置文件

rollup同样支持以配置文件的方式去配置我们打包过程中的各项参数,我们可以在项目的跟目录下去新建一个,rollup.config.js的配置文件。

那这个文件同样是运行在node环境中,不过rollup他自身会额外处理这个配置文件,所以这里我们可以直接使用ES Modules。

那在这个文件中他需要导出一个配置对象,那在这个对象中我们可以通过input属性指定我们打包的入口文件路径。

然后通过output去指定输出的相关配置,那output属性要求是一个对象,在output对象中我们可以使用file属性去指定我们输出的文件名。然后format属性可以用来指定我们输出格式。

export default {
    input: 'src/index.js',
    output: {
        file: 'dist/bundle.js',
        format: 'iife'
    }
}

我们可以运行rollup命令来测试配置,不过需要注意的是这里我们需要通过--config参数来去表明我们这去使用项目中的配置文件,默认的话他是不回去读取配置文件的,我们必须要使用这样一个参数。

yarn rollup --config rollup.config.js

那你也可以通过这样一个参数去指定不同配置文件的名称,例如我们可以有rollup.production.js或者rollup.development.js这样的对于开发和生产不同的配置文件。

Rollup 使用插件

rollup自身的功能就是ES模块的合并打包,那如果我们的项目有更高级别的需求,例如我们想去加载其他类型的资源文件,或者是我们要在代码当中导入CommonJS模块,又或者是想要他帮我们编译ECMAScript的新特性。

那这些额外的需求,rollup同样支持使用插件的方式去扩展实现,而且插件是rollup唯一的扩展方式,他不像webpack中划分了loader,plugin和minimize这三种扩展方式。

那这里我们先尝试使用一个可以让我们在代码当中导入JSON文件的插件,那通过这样一个过程我们去了解如何在rollup当中使用插件。

那我们这里使用的插件名字叫做rollup-plugin-json,我们需要先安装这个插件。

yarn add rollup-plugin-json --dev

安装完成过后我们打开配置文件,由于rollup的配置文件可以直接使用ES Modules所以我们这里直接使用import的方式去导入这个插件模块。

那这个模块默认导出的是一个插件的函数,我们可以将这个函数的调用结果添加到配置对象的plugins数组当中。需要注意的是这里我们是将调用的结果放在数组当中,而不是直接将这个函数放进去。

import json from 'rollup-plugin-json';

export default {
    input: 'src/index.js',
    output: {
        file: 'dist/bundle.js',
        format: 'iife'
    },
    plugins: [
        json()
    ]
}

那配置好这个插件过后我们就可以在代码中通过import方式导入json文件了,我们回到index.js当中,那这里我们通过import去导入项目根目录下的package.json文件。

那这个package.json当中的每一个属性呢就会作为一个单独的导出成员,我们这里可以提取一下json当中的name和version。然后我们通过log函数把他们打印出来。

import { log } from './logger';
import message from './message';
import { name, version } from '../package.json';

const msg = message.hi;
log(msg);

log(name);
log(version);
yarn rollup --config rollup.config.js

我们回到命令行打包完成之后,我们找到输出的bundle.js, 那此时就能看到json当中的name和version正常被打包进来了,而json当中那些没有用到的属性也都会被tree-shaking移除掉。

(function () {
    'use strict';

    const log = msg => {
        console.log(msg);
    };

    var message = {
        hi: 'Hey Guys, I am yd~'
    };

    var name = "rollup_p";
    var version = "1.0.0";

    const msg = message.hi;
    log(msg);

    log(name);
    log(version);

}());

那这就是我们在rollup中如何去使用插件。

Rollup 加载NPM模块

rollup默认只能按照文件路径的方式去加载本地的文件模块,那对于node_modules当中那些第三方的模块,他并不能够像webpack一样直接去通过模块的名称去导入对应的模块。

那为了抹平这样的一个差异,rollup官方给出了一个rollup-plugin-node-resolve这样一个插件。

通过使用这个插件我们就可以在代码当中直接去使用模块名称导入对应的模块了,首先我们需要安装这个插件。

yarn add rollup-plugin-node-resolve --dev

在配置文件中,我们需要先将这个模块导入进来,然后我们将这个插件函数的调用结果配置到plugins数组中。

import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve'

export default {
    input: 'src/index.js',
    output: {
        file: 'dist/bundle.js',
        format: 'iife'
    },
    plugins: [
        json(),
        resolve()
    ]
}

完成以后我们就可以回到代码当中直接去导入node_modules当中的那些第三方的npm模块了。这里我们导入一个loadash-es模块,需要提前安装。那这个模块就是我们非常常见的loadash的ES Modules版本。

导入过后我们就可以使用和这个模块所提供的一些工具方法了。

import _ from 'loadash-es';
import { log } from './logger';
import message from './message';
import { name, version } from '../package.json';

const msg = message.hi;
log(msg);

log(name);
log(version);
log(_.camelCase('hello world'))

此时loadash那些代码就能被打包到bundle.js当中了。这里我们使用的loadsh ES Module的版本而不是使用普通版本的原因是因为rollup默认只能取处理ES Module模块,如果说我们需要去使用普通版本我们需要做额外的处理。

Rollup 加载CommonJS模块

正如我们刚刚所看到的一样,rollup设计的就是只处理ES Module的模块打包,那如果我们在代码当中去导入CommonJS模块,默认是不被支持的,但是目前还是有大量的npm模块使用CommonJS方式去导出成员。

所以为了兼容这些模块,官网又给出了一个插件,叫做rollup-plugin-commonjs, 我们需要先安装这个模块。

yarn add rollup-plugin-commonjs --dev

在rollup配置文件中,导入这个插件,然后把他配置在plugins中。

import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';

export default {
    input: 'src/index.js',
    output: {
        file: 'dist/bundle.js',
        format: 'iife'
    },
    plugins: [
        json(),
        resolve()
    ]
}

配置过后我们就可以回到代码当中去使用commonjs模块了,我们先在src下添加一个commonjs模块,cjs.module.js

module.exports = {
    foo: 'bar'
} 

我们回到index.js当中我们尝试通过import去导入这个commonjs模块,那commonjs他的导出整体会作为一个默认导出,我们这里打印出这个默认导出。

import _ from 'loadash-es';
import { log } from './logger';
import message from './message';
import { name, version } from '../package.json';
import cjs from './cjs.module';

const msg = message.hi;
log(msg);

log(name);
log(version);
log(_.camelCase('hello world'));
log(cjs);

打包之后我们可以发现这个commonjs也被打包进bundle.js里面了。

Rollup 代码拆分

在rollup最新的版本中也进行开始支持代码拆分了,我们同样可以使用符合ES Module标准的动态导入的方式(Dynamic Imports)去实现模块的按需加载,rollup内部也会自动取处理代码的拆分,也就是我们说的分包。

我们在打包入口文件当中一起来尝试一下,我们先注释掉之前的代码,然后我们使用动态导入的方式去导入一下logger对应的这个模块,那这里import方法同样返回的是一个promise对象,在这个promise的then方法里面我们就可以拿到模块导入过后的对象。

由于这里模块导出的成员都会放在这个对象当中,所以我们这里可以使用解构的方式提取出里面的log方法,然后我们使用log方法打印一个日志消息。

// import { log } from './logger';
// import message from './message';

// const msg = message.hi;
// log(msg);

import('./logger').then(({ log }) => {
    log('code splitting');
});
yarn rollup --config

我们打开命令行终端尝试打包,这里我们直接运行打包会报出一个错误,说的是我们使用代码拆分这种方式去打包,他要求我们的format也就是输出格式不能是iife也就是自执行函数这种形式。

原因也很简单,因为自执行函数他会把所有的模块都放到同一个函数当中,他并没有像webpack一样有一些引导的代码,所以说他没有办法实现代码拆分。

那你要想使用代码拆分的话就必须要使用amd或者是commonjs这样一些其他的标准,那我们再浏览器环境中我们只能使用amd标准,所以说我们这里需要使用amd的格式去输出打包结果。

那我们这里继续使用打包命令,我们这里使用--format这样一个参数去覆盖住配置文件当中的format设置。我们把它设置为amd。

再次运行打包这里同样报出的一个错误,说的是我们这里code splitting输出输出多个文件,因为输出多个文件,我们这里就不能在使用file的这种配置方式,因为file是执行一个单个文件输出的文件文件名。

我们如果需要输出多个文件我们可以使用dir的参数。这里我们回到配置文件当中,注释掉原本配置文件当中的file和format,我们添加一个dir属性和一个format属性,我们将输出的目录设置为dist,将输出的格式设置为amd。

export default {
    input: 'src/index.js',
    output: {
        // file: 'dist/bundle.js',
        // format: 'iife'
        dir: 'dist',
        format: 'amd'
    },
}
yarn rollup --config

打包完成过后我们就可以看到dist目录中,这里他就会根据我们刚刚的动态导入生成一个入口的bundle.js以及我们动态导入的那个bundle。他们都是采用amd的标准输出的。

Rollup 多入口打包

rollup同样支持多入口打包,而且对于不同入口当中那些公共的部分,也会自动提取到单个文件当中,作为独立的bundle,那我们具体来看如何去配置。

在我们的实例中分别有两个入口,分别是index和album, 他们共用的fetch.js和logger.js这两个模块。

index.js

import fetchApi from './fetch';
import { log } from './logger';

fetchApi('/posts').then(data => {
    data.forEach(item => {
        log(item);
    })
})

album.js

import fetchApi from './fetch';
import { log } from './logger';

fetchApi('/photos?albumId=1').then(data => {
    data.forEach(item => {
        log(item);
    })
})

fetch.js

export default endpoint => {
    return fetch('xxxxx').then(response => response.json())
}

logger.js

export const log = msg => {
    console.log(msg);
}

export const error = msg => {
    conole.log('------ ERROR ------')
    console.log(msg);
}

我们在配置文件当中配置多入口打包的方式非常简单,我们只需要将input属性修改为一个数组就可以了,也可以使用与webpack相同的对象配置方式,不过这里我们需要注意,因为多入口打包,内部会自动提取公共模块,也就是说我们内部会使用代码拆分。

那这里我们就不能再去使用iife这种输出格式了,我们需要将输出格式修改为amd。

export default {
    // input: ['src/index.js', 'src/album.js'],
    input: {
        foo: 'src/index.js',
        bar: 'src/album.js'
    },
    output: {
        dir: 'dist',
        // format: 'iife',
        format: 'amd'
    },
}

打包过后我们dist目录下就会多出三个js文件,分别是两个不同打包入口的打包结果和我们公共提取出来的公共模块。

另外我们需要注意一点的是,对于amd这种输出格式的js文件, 我们不能直接去引用到页面上,而必须要去通过实现amd标准的库去加载,那这个我们之前在介绍amd标准的时候就应该有所了解了。

我们这里在dist目录下手动去创建一个html文件。然后尝试在html当中去使用打包生成的bundle.js, 我们这里采用requirejs的库去加载以amd标准输出的bundle。

require可以通过data-main这样一个参数来去制定我们require他去加载的模块的入口模块路径。我们这里就是foo.js

<body>
    <script src="...require.js" data-main="foo.js"></script>
</body>

完成以后我们启动一个服务,打开浏览器查看,你就可以看到我们的打包结果正常的加载进来了,也正常的工作了。

Rollup 选用原则

通过以上的探索和尝试我们发现,rollup确实有他的优势,首先就是他输出的结果会更加扁平一些,执行效率自然就会更高。

其次就是他会自动取移除那些位引用代码,也就是tree-shaking。

在一个就是他的打包结果基本上跟我们手写的代码是一致的,也就是打包结果对于开发者而言是可以正常阅读的。

但是他的缺点同样也很明显,首先就是我们去加载一些非ES Module的第三方模块就会比较复杂,我们需要配置一大堆插件。

因为这些模块最终都被打包到一个函数当中了,所以说我们没有办法像webpack一样去实现HMR这种模块热替换的这种开发体验。

在一个就是在浏览器环境中,代码拆分必须要使用像requireJS这样的amd库,因为他的代码拆分就必须要使用像amd这样的输出格式。

那综合以上的这些特点,我们发现,如果我们是正在开发一个应用程序,那我们肯定要面临大量引入第三方模块这样的需求。同时我们又需要像HMR这样的功能去提升我们的开发体验。而且我们应用一旦大了以后还需要必须要去分包。

那这些需求呢rollup他在满足上都会有一些欠缺。

如果我们正在开发的是一个js的框架或者是一个类库,那这些优点就特别有必要,而这些缺点基本可以忽略。

我们就拿加载第三方模块来说,在我们开发类库的时候会很少的在我们代码当中去依赖一些第三方模块。

所以说很多像react或者vue之类的框架中他都是使用rollup作为模块打包器,而并非是webpack。

但是到目前为止,开源社区中大多数人还是希望这两个工具可以共同存在共同发展,并且能够相互支持和借鉴。原因也很简单,就是希望能够让更专业的工具去做更专业的事情。

总结一下就是Webpack他的感觉是大而全,而Rollup是小而美。

在对他们两者之前的选择上,我们基本的原则就是如果我们正在开放应用程序,我们建议大家使用Webpack, 如果你是正在开发类库或者开发框架的话那我们建议选择Rollup。不过这也并不是一个绝对的标准。只是一个经验法则。

因为Rollup他同样也可以去构建绝大多数的应用程序,而Webpack也同样可以去构建类库或者是框架。只不过相对来讲的话术业有专攻的感觉。

另外一点就是随着近几年Webpack的发展Rollup中的很多优势几乎已经被抹平了,例如像我们Rollup当中这种扁平化输出,我们在Webpack中就可以死使用concatenateModules这样一个插件去完成。也可以实现类似的这样一个输出。

Parcel

Parcel是一款完全零配置的前端打包器,那他提供了近乎傻瓜式的使用体验,我们只需要了解他所提供的几个简单的命令就可以直接使用他去构建我们前端应用程序了。

那下面我们就来直接去看具体如何去使用Parcel。

Parcel 使用

首先我们有一个空的项目,我们先通过yarn init去初始化一个项目中的package.json文件。

完成以后我们就可以去安装Parcel所对应的模块,不过这里注意,Parcel的npm模块叫做parcel-bundler,我们这里同样应该将它安装到项目的开发依赖当中。

yarn add parcel-bundler --dev

安装完成过后呢,parcel-bundler这个模块在node_modules的bin目录里面就为我们提供了parcel的cli程序,那后续我们就可以使用这个cli去执行对我们整个应用的打包。

那既然是打包我们的应用代码,那这里我们就得先有代码,我们在项目的跟目录下新建一个src目录,用于存放开发阶段所编写的源代码。同时我们创建一个/src/index.html文件。这个文件会是我们parcel打包的入口文件。

虽然parcel和webpack一样都支持以任意类型的文件作为打包入口,不过parcel的官方建议我们使用html文件作为打包入口,官方所给出的理由是因为html是应用运行在浏览器端时的入口。所以我们应该使用html文件作为打包入口。

在这个入口文件当中我们可以正常像平常一样去编写,也可以在这去引用一些资源文件。那在这里被引用的资源最终都会被parcel打包到一起。最终输出到输出目录。

我们这里先引入一个main.js的脚本文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Parcel Tutorials</title>
</head>
<body>
    <script src="main.js"></script>
</body>
</html>

然后我们新建一个/src/main.js文件,除此之外我们再新建一个/src/foo.js文件。

然后我们再foo.js当中以ES Module的方式去默认导出一个对象,而且我们在这个对象中去定义一个bar方法。

export default {
    bar: () => {
        console.log('hello parcel~')
    }
}

然后我们在main.js当中通过import去导入刚刚这个foo模块,并且我们使用它导出对象当中的bar方法。

import foo from './foo';

foo.bar();

那parcel同样支持对ES Module模块的打包,完成以后我们再命令行中执行打包。

这个命令需要我们传入打包入口的路径,在我们这里就是src/index.html文件,

yarn parcel src/index.html

那此时如果我们执行这个命令,parcel就会根据我们这所传入的参数,先去找到index.html文件,然后根据index.html当中的script标签去找到他所引入的main.js文件,最后再顺着import语句找到foo模块,从而去完成整体项目的打包。

执行之后我们可以发现,parcel这个命令他不仅仅帮我们打包的应用而且他同时还开启了一个开发服务器。

那这个开发服务器就跟webpack当中的dev-server一样,我们可以打开这里所提供的地址。

我们在浏览器当中打开开发人员工具(控制台F12),那此时我们就可以使用自动刷新的功能了。

这里我们可以尝试修改一下源代码当中console.log中内容。

export default {
    bar: () => {
        // console.log('hello parcel~');
        console.log('hello parcel11~');
    }
}

保存过后你就会发现, 浏览器会自动刷新一下,从而去执行最新的打包结果。

那如果说我们需要的是模块热替换的体验,那parcel当中同样也支持,我们可以回到main.js当中,这里我们同样需要使用hmr所提供的api。

我们这里先去判断一下module.hot对象是否存在,如果存在这个对象的话就证明当前这个环境可以使用hmr的api。然后我们就可以使用module.hot.accept方法去处理模块热替换的逻辑了。

不过这里的accept和webpack提供的api有一点不太一样,webpack当中的api他支持接收两个参数,用来去处理我们指定模块更新过后的逻辑。

而这里parcel提供的accept他只可以接收一个参数也就是这个回调函数,作用呢就是当我们当前这个模块更新或者是当前这个模块所依赖的模块更新过后他会自动执行。

我们可以尝试先在这里打印HMR

import foo from './foo';

foo.bar();

if (module.hot) {
    module.hot.accept(() => {
        console.log('hmr');
    })
}

然后我们回到foo.js当中,尝试再次修改源代码。那此时我们就可以看到我们代码会自动被热替换到浏览器当中自动执行了。

那除了热替换,parcel还支持一个非常友好的功能,就是自动安装依赖。

那试想一下你正在开发一个应用的过程中,那突然间你想要去使用某个第三方的模块,那你此时就需要先停止正在运行的dev-server然后去安装这个模块,安装完成过后再去重新启动dev-server。

那有了自动安装依赖这个功能过后我们就不必要再这样麻烦了,我们可以回到main.js当中。

假设我们这里想要去使用一下jQuery, 虽然我们这里并没有安装这个模块,但是因为有了自动安装依赖这样的功能的缘故。我们这里只管正常导入就可以了。

那导入完成之后我们使用一下jQuery提供的api, 在文件保存过后, parcel会自动取安装我们刚刚所导入的这个模块。极大程度避免了我们额外的一些手动操作。

import $ from 'jquery';
import foo from './foo';

foo.bar();

$(document.body).append('<h1>Hello Parcel</h1>');

if (module.hot) {
    module.hot.accept(() => {
        console.log('hmr');
    })
}

除此之外,parcel同样支持加载其他类型的资源模块,而且相比于其他的模块打包器,在parcel当中去加载任意类型的资源模块同样还是零配置的。

例如我们这里添加一个/src/style.css的样式文件。然后我们在这个文件当中添加一些简单的样式。

body {
    background: red;
}

回到main.js当中通过import去导入这个样式文件,保存过后这个样式就可以立即生效。了。

import $ from 'jquery';
import foo from './foo';
import './style.css';

foo.bar();

$(document.body).append('<h1>Hello Parcel</h1>');

if (module.hot) {
    module.hot.accept(() => {
        console.log('hmr');
    })
}

整个这个过程我们并没有安装额外的插件,我们还可以随意添加一个图片,到我们的项目当中,然后我们回到代码当中导入这张图片,最后我们再通过jQuery将它显示到我们的页面当中。同样也是可以的。

import $ from 'jquery';
import foo from './foo';
import './style.css';
import logo from './icon.png';

foo.bar();

$(document.body).append('<h1>Hello Parcel</h1>');

$(document.body).append(`<img src=${logo} />`);

if (module.hot) {
    module.hot.accept(() => {
        console.log('hmr');
    })
}

那总之呢,parcel他希望给开发者的体验就是,你想要做什么你就只管去做,额外的事情呢就由工具去负责处理。

另外parcel同样支持使用动态导入,那内部如果你使用了动态导入的话,他也会自动拆分我们的代码,我们也一起来尝试一下。

这里我们先将静态导入的jQuery注释掉,然后我们使用动态导入的方式去导入jQuery模块,那在这个import所返回的promise对象的then方法当中,我们就可以拿到所导入的jquery对象了。

然后我们把使用了jquery的代码移到then方法里面。

// import $ from 'jquery';
import foo from './foo';
import './style.css';
import logo from './icon.png';

foo.bar();

import('jquery').then($ => {
    $(document.body).append('<h1>Hello Parcel</h1>');

    $(document.body).append(`<img src=${logo} />`);
})

if (module.hot) {
    module.hot.accept(() => {
        console.log('hmr');
    })
}

我们回到浏览器,刷新一下页面,然后再network面板,在这个面板当中我们就能看到刚刚所拆分出来的jquery所对应的bundle文件请求。

那以上基本上就是Parcel当中最常用的一些特性了。在使用上Parcel几乎没有任何难度,从头到尾我们只是执行了一个Parcel命令。所有事情都是Parcel内部自动帮我们完成的。

那我们再回到命令行,这里我们结束掉Parcel命令。

Parcel 部署生产

然后我们再看一下Parcel如何以生产模式去运行打包。

我们需要执行parcel这个cli所提供的build命令,然后跟上我们打包入口文件的路径就可以以生产模式运行打包了。

parcel build src/index.html

那这里额外补充一点,对于相同体量的项目打包,Parcel的构建速度会比Webpack快很多。

因为在Parcel的内部他使用的是多进程同时去工作,充分发挥了多核CPU的性能,那Webpack当中也可以使用一个叫做happypack的插件来去实现这一点。

那我们这里看一下输出的结果,那这里我们所输出的一些文件都会被压缩,而且样式代码也都单独提取到单个单间当中了,那这就是Parcel的一个体验。

Parcel 总结

那整体我们体验下来就是一个感觉,舒服。

因为他在使用上真的太简单了,设想一下我们之前用的Webpack我们都需要做很多额外的配置,安装很多的插件,在Parcel当中其实也有这样的插件,只不过他是自动帮我们去安装的。

我们整体是不需要关心这些东西的,所以他在使用上就给了一种非常舒服的感觉。

那Parcel是2017年发布的,那出现的原因呢也就是因为当时Webpack在使用上过于繁琐,而且官网的文档也不是很清晰明了。

所以说Parcel他一经推出就迅速被推上了风口浪尖,那其核心特点呢就是真正意义上做到了完全零配置。那对我们的项目没有任何的侵入。

而且整个过程我们会有自动安装依赖的这样一个体验,让我们开发过程可以更加专注编码。

除此之外呢还有一个就是Parcel他一开始提供的这种构建速度就非常快,因为他内部使用了多进程同时工作,所以相比于Webpack的打包,他的速度要更快一些,但是这个刚刚我们也说了,Webpack也可以借助于插件去解决这样的问题。

那Parcel的优点固然很明显,但是目前实际上你去观察使用情况你会发现,绝大多数的项目打包还是会选择使用Webpack,那我个人认为原因可能有两点。

第一点呢就是Webpack他的生态可能会更好一些,扩展也就会更丰富,而且出现问题我们也可以很容易去解决。

第二点就是随着这两年的发展,Webpack也越来越好用,开发者随着不断去使用他也越来越熟悉,所以要是我个人选择的话我可能也会选择Webpack。

那Parcel这样的工具对于开发者而言,我们去了解他其实也就是为了保持对新鲜技术和工具的敏感度。从而更好的把握技术的趋势和走向,仅此而已。