Rollup 从入门到熟悉
如何使用 Rollup 编译 JavaScript 代码
tips: 本文带有强烈的个人理解,所以有些地方我理解可能有误,读者如有质疑不用怀疑,绝对是我的错,是我水平太次。
这篇文章我会分别讲讲怎么使用rollup编译JavaScript 代码和 使用rollup插件使用。
熟悉 rollup
先全局安装一下 rollup
npm install --global rollup
安装好之后我们执行下
rollup --help

很多的选项,不管他我们只需要使用 -c 这个属性即可,rollup 需要接收一个 默认名称为rollup.config.js文件(文件名称不固定,其返回的数据格式满足rollup的需求即可,其内容就是配置项了,OK,那么现在我们的目标是 rollup.config.js文件了。
如果不传递 -c 配置选项的话,rollup 会在当前执行命令的目录下寻找rollup.config.js文件。
rollup.config.js

注意看 Core functionality 核心功能,这个是我们需要注意的,可以多瞄几眼,以下的内容将会对核心功能进行大概的讲解。
配置项核心功能
external
如果我们做过webpack打包排除的话,应该对这个不陌生,就是在构建阶段哪些包不参与构建,下文会提及该配置项,请牢记!
import { fileURLToPath } from 'node:url';
export default {
//...,
external: [ // 不参与构建的包名称
'some-externally-required-library',
fileURLToPath(
new URL(
'src/some-local-file-that-should-not-be-bundled.js',
import.meta.url
)
),
'/node_modules/'
]
};
input
名称已经说明了,我们需要构建哪些代码,只需要把代码所在的路径写进去即可。
export default {
input: {
a: 'src/main-a.js',
'b/index': 'src/main-b.js'
},
};
output
output.dir
output.file
output.format
output.globals
output.name
output.plugins
有输入自然有输出, 其实常用的也就那么那么几个,来看一个案例代码
output: 可以是一个数组也可以是object对象。
-
name: 当format格式为iife umd时必传。 -
globals:format格式为iife umd amd时请务必设置globals,globals设置时请务必设置external, 这俩配置项需要相互配合。
export default {
input: "main.js",
external: ["jquery"],
output: [
{
file: "bundle.js", // 输入文件名称
format: "es", // 输出文件格式 https://rollupjs.org/configuration-options/#output-format
dist: "./dist", // 输出文件地址
},
{
file: "bundle.min.js",
dist: "./iife",
format: "iife", // format 格式为 iife umd amd 时请务必设置 globals
globals: { // globals 相对特殊需要与 extends 配合使用。
jquery: "$",
},
},
],
};
plugins
主角注定天生与众不同,plugins则是 Rollup的灵魂,plugins相对特殊,plugins先给大家看下怎么使用。
plugins 可以放在两个位置:
- 跟
inputoutput同级
同级时插件会对所有的 output 生效。
output对象/数组 中
对象/数组中时插件只会对当前的 output 生效。
import terser from '@rollup/plugin-terser';
export default {
input: "main.js",
plugins: [terser()],
output: [
{
file: "bundle.js",
format: "es",
},
{
file: "bundle.min.js",
format: "es",
plugins: [terser()], //就那么简单直接用就完事了
},
],
};
小结
rollup 一一拆解之后会发现rollup配置项并不多,可以分为三大块
input输入plugins插件output输出
input和 plugins比较简单直接写就完事了,output可能有不少需要注意的点,读者可以多看看官网文档。
rollup 实战
下面我就带着读者们来实践我们所学的知识点。
直接将项目克隆下来,现在我们已经实现了一个rollup打包代码工具,执行下 npm run build 试试。
你会发现在当前目录下,会生成 es 目录,es 目录中有index.js,index.js文件中的内容好像跟我们写的代码差不多呐。
async function getHaoKanVideo() {
return await axios.get("https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2")
}
export { getHaoKanVideo as default };
是的,因为我们使用的的格式化是 es模式
其他的输出格式文件
想要输出其他格式规范的JavaScript代码,我们只需要在 output数组中再加配置项即可。
那就在加俩格式的输出类型
import { defineConfig } from "rollup";
import { readFileSync } from "node:fs";
const packageJson = JSON.parse(
readFileSync(new URL("./package.json", import.meta.url))
);
export default defineConfig({
input: "./src/index.js",
external: ["axios"],
output: [
{
file: packageJson.module,
format: "es",
},
{
file: "cjs/cjs.js",
format: "cjs",
},
{
name: packageJson.name,
file: packageJson.main,
format: "umd",
globals: {
axios: "axios",
},
},
],
});
三种格式代码打包出来分别是咋样的呢?
es
async function getHaoKanVideo() {
return await axios.get("https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2")
}
export { getHaoKanVideo as default };
cjs
'use strict';
async function getHaoKanVideo() {
return await axios.get("https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2")
}
module.exports = getHaoKanVideo;
umd
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["rollup-use__plugins"] = factory());
})(this, (function () { 'use strict';
async function getHaoKanVideo() {
return await axios.get("https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2")
}
return getHaoKanVideo;
}));
那么我这个编译后的代码是不是能直接拿去用了?
如果不是通过cdn方式直接引入的,通过npm包或者直接在vue等项目中使用可以。
那么为啥不能通过cdn方式直接引入呢?
不知道读者有没有发现一个严重的问题,这个function用的怎么还是Es7语法,cjs和es用Es7语法没什么问题(cjs主要是给node使用的,es 则是我们常用的,umd 一般我们都是给浏览器环境使用的,Es7语法在低版本的浏览器无法解析。那不就坏大事了……
那么我们现在出现一个问题: rollup怎么配置才能编译出兼容低版本浏览器的代码?
Plugin 插件使用
承接上文,我们留下了一个疑问,不知道读者有没有发现以上的配置我们都没有使用插件,好像不使用插件我们也能编译 JavaScript代码呀,那么为啥还要插件呢?
这个说法没有错,rollup在不依赖任何插件的情况下是可以编译JavaScript代码。
请想想以下几个问题
-
我的项目非常大,最后打包出来的代码可能有 几十 kb 怎么办?
-
rollup怎么配置才能编译出兼容低版本浏览器的代码? -
我的项目编译成之后能不能自动上传到
cdn呐? -
我的项目里之前开发的时候写了几十个
console,我不想编译后代码里还有console怎么做呀?

大兄弟,你这个事情简单,插件就能解决!插件大哥解决你一切忧愁。
不信?那么一个个来。
我的项目非常大,最后打包出来的代码可能有 几十 kb 怎么办?
使用 @rollup/plugin-terser 插件来压缩代码
npm install @rollup/plugin-terser --save-dev
import terser from '@rollup/plugin-terser';
export default defineConfig({
input: "./src/index.js",
plugins: [terser()],
output: [
{
file: packageJson.module,
format: "es",
},
{
file: "cjs/index.js",
exports: "named",
format: "cjs",
},
],
});
我用Es6 Es7语法写的代码,我代码输出的格式是umd, rollup怎么没编译成es5的呀?
使用 babel 将Es6 Es7代码编译成Es5,用以兼容低版本浏览器。
import { defineConfig } from "rollup";
// import terser from '@rollup/plugin-terser';
import { getBabelOutputPlugin } from "@rollup/plugin-babel";
import commonjs from "@rollup/plugin-commonjs";
export default defineConfig({
external: ["axios"],
input: "./src/index.js",
plugins: [
commonjs(),
],
output: [
{
name: "rollupBuildTest",
file: "dist/bundle.js",
format: "umd",
exports: "named",
globals: {
axios: "axios",
},
plugins: [
getBabelOutputPlugin({
presets: ["@babel/preset-env"],
plugins: [["@babel/plugin-transform-runtime", { useESModules: false }]],
}),
]
},
],
});
我的项目编译成之后能不能自动上传到cdn呐?
这里我写了一个rollup插件,在rollup编译的完成时的阶段拿到需要上传的文件,传输至服务器。
我的项目里之前开发的时候写了几十个console,我不想编译后代码里还有console怎么做呀?
这里我也写了一个rollup插件,在编译的阶段通过分析AST匹配到console代码删除。
总结
大家应该明白了为什么我说插件是rollup的灵魂。
与其什么都干不如我只做最基础的事情,剩下的开放插件,你想做什么由你决定!
大概的给大家讲了讲 rollup相对基础的使用,下一篇文章来给大家讲讲怎么编写rollup插件。
转载自:https://juejin.cn/post/7252255755422875703