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
可以放在两个位置:
- 跟
input
output
同级
同级时插件会对所有的 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