rollup基本了解

43 阅读5分钟

文档地址:www.rollupjs.com/

是什么?

是一款ESM的打包器,它和webpack相比小巧的多,rollup旨在充分利用ESM的各项特性构建出结构比较扁平西功能比较出众的类库。

有什么用?

可以把项目中散乱的细小模块打包为整块的代码,使这些模块可以更好的运行在浏览器环境或node.js环境

本地安装

yarn add rollup --dev

快速开始

# 查看命令行参数
yarn rollup --help
# 以./src/index.js为入口 打包成iife格式(适合浏览器的自执行函数) 输出到dist/bundle.js
yarn rollup ./src/index.js --format iife --file dist/bundle.js 

可以观察到,rollup自动开启了Tree-Shaking,去除未引用到的代码(无用代码)

配置文件

rollup支持以配置文件的方式指定打包中的各个参数 默认会找 rollup.config.js作为配置文件

yarn rollup --config
等同于
yarn rollup --config rollup.config.js
* 执行时报一个错,需要在package.json中添加"type": "module"

简单的配置

rollup.config.js

export default {
  input: './src/index.js', // 指定入口
  output: {
    file: 'dist/bundle.js', // 指定出口
    format: 'iife', // 指定打包格式 rollup支持的打包格式有:amd(AMD标准)、cjs(CommonJS标准)、esm\es(ES模块标准)、iife(立即执行函数)、umd(同时支持amd、cjs、iife)
  }
}

使用插件

rollup自身的功能只是ESM模块的合并打包,如果项目有更高级的需求,比如想加载其它类型的资源文件、想在代码中导入commonjs模块、想编译ECMAScript的新特性等这些额外的需求,rollup支持用插件方式去拓展。 并且插件是rollup唯一的扩展方式。

支持导入json文件

yarn add rollup-plugin-json --dev

rollup支持用ESM的方式导入插件,插件导出的是一个函数,将这个函数的执行结果放到plugins中就可以了, 这样就可以直接在代码中导入json文件了。

# rollup.config.js

import json from 'rollup-plugin-json';

export default {
  input: './src/index.js', // 指定入口
  output: {
    file: 'dist/bundle.js', // 指定出口
    format: 'iife', // 指定打包格式
  },
  plugins: [
    json()
  ]
}

加载npm模块

rollup默认只能按文件路径去加载本地的文件模块,它并不能像webpack一样直接按文件名称去node_modules中导入对应的文件,为了抹平这个差距,可以用rollup-plugin-node-resolve插件导入对应的模块。

# 安装插件
yarn add rollup-plugin-node-resolve --dev

配置

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中的包

import _ from 'lodash-es'

导入commonJS

rollup只处理ESM的模块打包,如果在代码中导入commonJS模块,默认是不被支持的,但是目前还有大量的npm模块使用commonJS的方式导出的,这需要借助rollup-plugin-commonjs插件类实现对commonjs模块的导入。

# 安装插件
yarn add rollup-plugin-commonjs --dev

将插件放在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()
  ]
}

假如有一个commonjs模块 cjs-module.js

module.exports = {
  foo: 'bar'
}

在入口文件用import导入

import cjs from './cjs-module.js';

通过以上配置后,就可以用import成功导入commonjs模块了

代码拆分

新版本的rollup开始支持代码拆分了,支持按ESM标准的动态导入的方式去实现模块的按需加载,rollup内部也会自动处理代码拆分
文件入口

import('./logers').then(({ log }) => {
  log('code-splitting')
})

直接执行会报错,
1、这种代码拆分不支持iife的格式打包,原因是自执行函数会把所有的模块放在函数中,它并不像webpack一样有一些引导代码,没办法实现代码拆分,如果想用代码拆分,必须用amd、commonjs这些标准,在浏览器中只能用amd标准。 2、由于使用了代码拆分,配置出口时就不能用file这种方式,需要用dir格式

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', // 指定打包格式
    dir: 'dist',
    format: 'amd'
  },
  plugins: [
    json(),
    resolve(),
    commonjs()
  ]
}

这样打包后会在dist目录下生成一个入口的bundle,还有一个动态导入所对应的bundle

多入口打包

多入口打包内部会提取公共模块,内部会使用代码拆分,这里就不能使用iife格式,需要用amd格式

# ======入口文件1  index.js======
import { log } from './logers'
import featchApi from 'fetch'

featchApi('/posts').then(data => {
  data.forEach(item => {
    log(item)
  })
})
# ======入口文件2  album.js======
import { log } from './logers'
import featchApi from 'fetch'

featchApi('/photos?albumId=1').then(data => {
  data.forEach(item => {
    log(item)
  })
})
# ======共用模块1 fetch.js======
export default endpoint => {
  return fetch(`https://jsonplaceholder.typicode.com${endpoint}`)
  .then(response => response.json())
}
# ======共用模块2 loger.js======
export function log(msg) {
  console.log('-------info-------')
  console.log(msg)
  console.log('------------------')
}

export function error(msg) {
  console.error('-------error-------')
  console.error(msg)
  console.error('------------------')
}

配置

export default {
  // input: ['src/index.js', 'src/album.js'], // 配置多入口
  input: { // 配置多入口
    foo: "src/index.js",
    bar: "src/album.js"
  },
  output: {
    dir: 'dist',
    format: 'amd'
  }
}

可以在dist目录下创建一个html文件,引入支持amd的库,加载打包好的foo.js文件,运行http-server查看执行结果

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<script src="https://unpkg.com/requirejs@2.3.6/require.js" data-main="foo.js"></script>
</body>
</html>

打包结果:

image.png

rollup选用原则

1、加载非ESM模块的第三方模块比较复杂(需要配置各种插件)
2、模块最终都被打包到一个函数中,无法实现HMR
3、浏览器环境中,代码拆分依赖AMD库

但是在开发一些类库/框架时,很少加载第三方模块,选用rollup就很适合了。
webpack大而全、rollup小而美。
如果在开发vue、react这种类库时选用rollup,如果在开发应用时选用webpack,这并不是标准,是经验法则,因为rollup也可以满足大多的应用开发。

parcel

是什么?

零配置的前端应用打包器。只需要傻瓜式的执行命令就可以打包前端应用。

npm init -y
yarn add parcel-bundler --dev

parcel虽然可以以任何文件作为打包入口,但是推荐以html文件为打包入口,因为html是应用运行在浏览器端的入口。在这里引入的资源都会被parcel打包到一起,最后输出到输出目录。\

创建源代码
src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <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

import foo from './foo'
foo.bar()
if(module.hot){
  /**
   * parcel提供的hrm和webpack有些区别,webpack提供的hmr与两个参数,而parcel提供的hmr只有一个参数,
   * 只有当前模块的代码放生改变或者当前模块依赖的发生改变时,会触发hmr的回调
   */
  
  module.hot.accept(() => {
    console.log('hmr')
  })
}

src/foo.js

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

执行parcel的打包命令

yarn parcel src/index.html

这个命令执行后,会找到入口html里的main.js,然后把main.js使用到的资源都打包起来, 命令执行后,会发现parcel帮我们启动了个本地服务器,和webpack中的dev-server一样,可以用浏览器来查看这个地址。\

parcel支持的功能

1、parcel支持自动刷新,在源码中改变console.log的打印结果,浏览器会自动刷新。
2、parcel也支持模块热替换(HMR)。(改变源码,会自动更新代码)\
3、parcel也支持自动安装依赖。(手动写入import $ from 'jquery' 会自动安装jquery)。
4、在parcel中加入任意资源都是零配置的,(比如加入style.css,并在main.js中引入,添加一个图片在main.js中引入并用jquery添加到页面,无需手动添加任何loader和插件都可以自动完成并显示到页面)。
5、parcel也支持代码拆分,将jquery改成异步加载的方式,parcel会自动拆分代码,无需配置。

parcel以生产模式运行打包

yarn parcel build src/index.html

parcel是2017年出现的,它出现的原因是webpack的配置过于繁琐,文档也不清晰明了,所以parcel一出就被推上了风口浪尖,它最突出的特点是零配置。不过后来的webpack发展的越来越好,大多项目还是采用的webpack打包。