likes
comments
collection
share

Rollup 从入门到熟悉

作者站长头像
站长
· 阅读数 9

如何使用 Rollup 编译 JavaScript 代码

tips: 本文带有强烈的个人理解,所以有些地方我理解可能有误,读者如有质疑不用怀疑,绝对是我的错,是我水平太次。

这篇文章我会分别讲讲怎么使用rollup编译JavaScript 代码和 使用rollup插件使用。

熟悉 rollup

先全局安装一下 rollup

npm install --global rollup

安装好之后我们执行下

rollup --help

Rollup 从入门到熟悉

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

如果不传递 -c 配置选项的话,rollup 会在当前执行命令的目录下寻找rollup.config.js文件。

rollup.config.js

配置API

Rollup 从入门到熟悉

注意看 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对象。

  1. name: 当format格式为 iife umd 时必传。

  2. globals: format 格式为 iife umd amd 时请务必设置 globalsglobals设置时请务必设置 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 可以放在两个位置:

  1. input output 同级

同级时插件会对所有的 output 生效。

  1. 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配置项并不多,可以分为三大块

  1. input 输入
  2. plugins 插件
  3. output 输出

inputplugins比较简单直接写就完事了,output可能有不少需要注意的点,读者可以多看看官网文档。

rollup 实战

下面我就带着读者们来实践我们所学的知识点。

直接将项目克隆下来,现在我们已经实现了一个rollup打包代码工具,执行下 npm run build 试试。

你会发现在当前目录下,会生成 es 目录,es 目录中有index.jsindex.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语法,cjsesEs7语法没什么问题(cjs主要是给node使用的,es 则是我们常用的,umd 一般我们都是给浏览器环境使用的,Es7语法在低版本的浏览器无法解析。那不就坏大事了……

那么我们现在出现一个问题: rollup怎么配置才能编译出兼容低版本浏览器的代码?

Plugin 插件使用

承接上文,我们留下了一个疑问,不知道读者有没有发现以上的配置我们都没有使用插件,好像不使用插件我们也能编译 JavaScript代码呀,那么为啥还要插件呢?

这个说法没有错,rollup在不依赖任何插件的情况下是可以编译JavaScript代码。

请想想以下几个问题

  1. 我的项目非常大,最后打包出来的代码可能有 几十 kb 怎么办?

  2. rollup怎么配置才能编译出兼容低版本浏览器的代码?

  3. 我的项目编译成之后能不能自动上传到cdn呐?

  4. 我的项目里之前开发的时候写了几十个console,我不想编译后代码里还有console怎么做呀?

Rollup 从入门到熟悉

大兄弟,你这个事情简单,插件就能解决!插件大哥解决你一切忧愁。

不信?那么一个个来。

我的项目非常大,最后打包出来的代码可能有 几十 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的呀?

使用 babelEs6 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插件。