Rollup打包学习

317 阅读4分钟

1. 简介

Rollup 是一个 JavaScript 模块打包工具,可以将多个小的代码片段编译为完整的库和应用。与传统的 CommonJS 和 AMD 这一类非标准化的解决方案不同,Rollup 使用的是 ES6 版本 Javascript 中的模块标准。小巧,一个ESM打包器,不支持HMR,利用ESM特性的高效打包器。

2. 上手

新建文件

src/index.js
import { log } from './logger'

import messages from './messages'

const msg = messages.hi

log(msg)

src/messages.js 

export default {
	hi: 'I am msg'
}

src/logger.js
export const log = msg => {
	console.log('打印***msg====> info', msg)
}

export const error = msg => {
	console.log('打印***msg====> error', msg)
}

安装rollup yarn add rollup -D 3.14.0

yarn rollup 出现帮助信息  
yarn rollup ./src/index.js 打印结果  
yarn rollup ./src/index.js --format iife 输出立即执行函数到文件 iife esm cjs amd...
yarn rollup ./src/index.js --format iife --file=dist/bundle.js输出到文件  
打包结果如下,默认tree-sharking

image.png

配置文件

根目录 rollup.config.js 默认是commonjs ,自身会处理,可以使用esm语法导出个默认对象。不会自己处理 需要type或者mjs结尾。

yarn rollup —config命令

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

加载资源文件

支持使用插件 是唯一扩展途径,导入json文件的。

安装插件rollup-plugin-json 4.0.0

配置文件

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

在scr/index.js中使用

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

const msg = messages.hi
console.log('打印***name,version', name, version)
log(msg)

打包后结果:没有用到的属性不会被打包

image.png

加载npm模块

解析 npm 包
默认 rollup 是不解析 npm packages 里面的库的
是只用一个 require 来加载的
```js
var answer = require('the-answer');

如果想也解析 npm packages 里面的库的话 就需要使用 @rollup/plugin-node-resolve 因为 rollup 是只支持 esm 的,但是有的库是使用的 commonJs 规范,所以 rollup 是理解不了的 需要把 commonJs 转换成 ES2015 使用 @rollup/plugin-commonjs 来处理 请注意,大多数情况下 @rollup/plugin-commonjs 应该在转换模块的其他插件之前 - 这是为了防止其他插件进行破坏 CommonJS 检测的更改。 这个规则的一个例外是 Babel 插件,如果你正在使用它,那么把它放在 commonjs 插件之前。


rollup不支持import 引入node_modules下面的模块,需要使用rollup-plugin-node-resolve进行解析。

yarn add rollup-plugin-node-resolve -D  5.2.0

```jsx
import { log } from './logger'
import messages from './messages'
import { version, name } from '../package.json'
import _ from 'lodash-es'

const msg = messages.hi
console.log('打印***name,version', name, version)
log(msg)

console.log('打印***_', _.camelCase('hello'))

rollup.config.js

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()]
}

未使用 lodash-es未打包进去

image.png

image.png

加载commonJS模块

兼容cjs的导出 rollup-plugin-commonjs 10.1.0

// 新建一个cjs-module.js
module.exports = {
	foo: 'foo'
}
// src/index.js
import cjs from './cjs-module'

console.log('打印***cjs', cjs)

rollup.config.js

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()]
}

打包后

image.png

代码拆分

动态导入,自动进行分包。

// src/index.js

import('./logger').then(({ log }) => {
	log('code,splitting')
})

//rollup.config.js
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: {
		dir: 'dist',
		format: 'amd'
	},
	plugins: [json(), resolve(), commonjs()]
}

导出格式不能是iife,会默认放在一起。amd

image.png

输出多个文件 dir

image.png

输出的文件

image.png

多入口打包

公共的模块

// src/logger.js
export const log = msg => {
	console.log('打印***msg====> info', msg)
}

export const error = msg => {
	console.log('打印***msg====> error', msg)
}
// 多入口 src/index.js
import('./logger').then(({ log }) => {
	log('code,splitting')
})

// src/album.js
import fetchApi from './fetch'
import { log } from './logger'

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

// src/fetch.js

export default endpoint => {
	return fetch(`https://jsonplaceholder.typicode.com${endpoint}`).then(response => response.json())
}

rollup.config.js

export default {
	input: ['src/index.js', 'src/album.js'],
	output: {
		dir: 'dist',
		format: 'amd'
	}
}
// ================================== 打包后文件名称
input: {
		main: 'src/index.js',
		main2: 'src/album.js'
	},

image.png

dist文件下使用index.js文件,使用require.js进行解析,data-main指定引入文件 ,本地启动服务

<!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></body>
	<script src="<https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js>" data-main="./index.js"></script>

</html>

image.png

Peer dependencies

把对应的库写到 external 内 ,就不会打包到 bundle

external: ['lodash-es']

image.png

使用babel

yarn add @babel/core @babel/preset-env @rollup/plugin-babel -D

Babel 插件,放在 commonjs 插件之前

import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs
import babel from '@rollup/plugin-babel'

export default {
	input: 'src/index.js',
	output: {
		dir: 'dist',
		format: 'cjs'
	},
	plugins: [
		resolve(),
		babel({
			babelHelpers: 'bundled'
		}),
		commonjs()
	],
}

压缩文件

@rollup/plugin-terser


import terser from '@rollup/plugin-terser'

export default {
	input: 'src/index.ts',
	output: {
		dir: 'dist/',
		format: 'esm'
	},
	plugins: [ terser()]
}

打包ts文件

import typescript from '@rollup/plugin-typescript'

plugins: [typescript({ tsconfig: './tsconfig.json' })

选用原则

  • 输出结果更加扁平
  • 自动移除未引用代码
  • 打包结果依然可读

缺点

  • 非esm加载复杂,
  • 无法实现hmr
  • 浏览器开发依赖requirejs 输出amd,esm可以支持