《三十》模块化打包构建工具 Rollup

基于 Rollup4。

Rollup 是一个 JavaScript 的模块化打包工具,可以帮助编译微小的代码到庞大的复杂的代码中(例如一个库或者一个应用程序)。

Rollup 和 Webpack 的区别:

  1. Rollup 也是一个模块化的打包工具,但是它主要是针对 ESModule 进行打包的(当然也有解决办法可以处理其他模块化代码);Rollup 更多时候是专注于处理 JavaScript 代码(当然也可以处理其他文件);配置理念相对于 Webpack 来说更加简洁和容易理解。

    Rollup 中处理任何文件都是使用对应的插件。

  2. Webpack 是一个模块化的打包工具,可以针对各种模块代码;可以通过 Loader 处理各种类型的文件以及它们之间的依赖关系。

    Webpack 中是通过 Loader 来转换文件,通过 Plugin 来执行其他的逻辑。

通常在实际开发中都会使用 Webpack,例如 React、Vue、Angular 项目都是基于 Webpack 的;在对库文件进行打包时,通过会使用 Rollup,例如 React、Vue、dayjs 源码本身都是基于 Rollup 的。

Rollup 的基本使用:

在命令行中使用 Rollup:

  1. 新建一个 rollup-demo 文件,运行 npm init -y 对其进行初始化。
  2. 安装 Rollup:npm install rollup -D
  3. 新建 src/index.js 文件,并编写代码。
    const sum = (num1, num2) => {
      console.log(num1 + num2)
    }
    export {
      sum
    }
    
  4. 运行 npx rollup ./src/index.js -o dist/index_esmodule.js 命令对 src/index.js 进行打包,输出到 dist//index_esmodule.js 中。
    请添加图片描述
  5. 运行 npx rollup ./src/index.js -f cjs -o dist/index_commonjs.js 命令,使用 CommonJS 的格式对 src/index.js 进行打包,输出到 dist/index_commonjs.js 中。
    请添加图片描述
  6. 运行 npx rollup ./src/index.js -f amd -o dist/index_commonjs.js 命令,使用 AMD 的格式对 src/index.js 进行打包,输出到 dist/index_amd.js 中。
    请添加图片描述
  7. 运行 npx rollup ./src/index.js -f iife -o dist/index_browser.js 命令,使用 AMD 的格式对 src/index.js 进行打包,输出到 dist/index_browser.js 中。
    请添加图片描述

使用 Rollup 的配置文件:

rollup.config.js 配置文件中可以使用 CommonJS 语法;也可以使用 ESModule 语法,如果要使用 ESModule 语法的话,需要给 package.json 添加 "type": "module" 来告知 Node 使用 ES 模块解析脚本。

由于 Rollup 最主要是针对 ESModule 来进行打包的,因此 rollup.config.js 配置文件中更常使用 ESModule 语法。

  1. 在项目的根目录下创建 rollup.config.js 配置文件,并编写配置。
    module.exports = {
      // 入口
      input: './src/index.js',
      // 出口。属性值可以是一个对象类型的数组,将会输出多个结果;也可以是一个对象,只输出一个结果
      output: [
        {
          file: 'dist/index_esmodule.js'
        },
        {
          format: 'umd',
          // 一旦导出为 UMD 格式,就必须指定 name 名称
          name: 'utils',
          file: 'dist/index_umd.js'
        },
      ]
    }
    
  2. 运行 npx rollup -c 进行打包,会发现打包输出出了两种格式的文件。
    请添加图片描述

使用 Rollup 打包 CommonJS 语法的代码:

Rollup 主要是针对 ESModule 的,如果代码存在 CommonJS 语法,虽然仍然可以打包成功,但是无法识别并对其进行处理。

  1. 新建 src/js/format.js 文件并编写代码。
    const dateFormat = () => {
      return '2000-10-10'
    }
    
    module.exports = {
      dateFormat
    }
    
  2. 新建 src/index.js 文件并编写代码。
    const {dateFormat} = require('./js/format')
    console.log(dateFormat())
    
  3. 新建 src/index.html 文件并编写代码。
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <!-- 引入打包后的 JavaScript 文件 -->
      <script src="../dist/index.js"></script>
    </body>
    </html>
    
  4. 新建 rollup.config.js 文件并编写配置信息。
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      }
    }
    
  5. 运行 npx rollup -c 命令进行打包,会发现,rollup 仍然可以打包成功,但是在浏览器中运行会报错,因为浏览器不认识 require() 语法。
    请添加图片描述
    请添加图片描述
  6. 安装 @rollup/plugin-commonjs 插件使 Rollup 能够识别并转换代码中的 CommonJS 语法:npm install @rollup/plugin-commonjs -D
  7. rollup.config.js 文件中修改配置信息。
    // 引入 commonjs 插件
    const commonjs = require("@rollup/plugin-commonjs")
    
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      // 使用 commonjs 插件
      plugins: [
        commonjs()
      ]
    }
    
  8. 修改 src/index.js 文件中的导入语法,导入时仍然需要使用 ESModule 语法,否则还是会报错。

    目的是为了保证开发者自己编写的代码仍然使用 ESModule 语法,同时兼容第三方库中使用 CommonJS 语法。因此导出允许使用 CommonJS,但是导入必须使用 ESModule。

    import {dateFormat} from './js/format.js'
    
    console.log(dateFormat())
    
  9. 运行 npx rollup -c 命令进行打包,会发现,rollup 可以打包成功,并且在浏览器中也可以成功运行。
    请添加图片描述
    请添加图片描述
  10. npm install lodash -D 安装 lodash,并在 src/index.js 文件中引入使用。会发现使用第三方库还是有问题,lodash 的源码并没有被打包进输出的文件中,在浏览器中运行也报错了。这是因为如果导入的库来自 node_modules 的话,还需要使用另一个插件。
    请添加图片描述
    请添加图片描述
  11. 安装 @rollup/plugin-node-resolve 插件来处理导入来自 node_modules 的依赖:npm install @rolluop/plugin-node-resolve -D
  12. rollup.config.js 文件中修改配置信息。
    const commonjs = require("@rollup/plugin-commonjs")
    // 引入 resolve 插件
    const resolve = require('@rollup/plugin-node-resolve') 
    
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      // 使用 resolve 插件
      plugins: [
        commonjs(),
        resolve()
      ]
    }
    
  13. 运行 npx rollup -c 命令进行打包,会发现,rollup 可以打包成功,并且在浏览器中也可以成功运行。
    请添加图片描述

请添加图片描述

使用 Rollup 转换 ES+ 语法的代码:

  1. 新建 src/index.js文件,并编写代码。

    const fn = () => {
      console.log('index')
    }
    fn()
    
  2. 新建 rollup.config.js文件,并编写配置信息。

    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
    }
    
  3. 运行 npx rollup -c 命名进行打包,会发现,打包输出的文件中并没有对 ES6+ 语法进行转换。
    在这里插入图片描述

  4. 安装 @rollup/plugin-babel 插件对 ES6+ 代码进行转换:npm install @rollup/plugin-babel -D

  5. 安装 Bable 的核心:npm install @babel/core -D

  6. 安装 Bable 中的预设:npm install @babel/preset-env -D

  7. 修改 rollup.config.js 文件中的配置信息。

    // 引入 Babel 插件
    const babel = require('@rollup/plugin-babel')
    
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        // 使用 Babel 插件
        babel({
          babelHelpers: 'bundled',
        }),
      ]
    }
    
  8. 新建 babel.config.js 文件,并编写 Babel 的配置信息。

    module.exports = {
      presets: [
        '@babel/preset-env',
      ]
    }
    
  9. 运行 npx rollup -c 命名进行打包,会发现,打包输出的文件中对 ES6+ 语法进行了转换。
    在这里插入图片描述

使用 Rollup 对打包后的 JavaScript 代码进行压缩:

  1. 新建 ·src/index.js 文件,并编写代码。

    const fn = (num1, num2) => {
      console.log(num1, num2)
      return num1 + num2
    }
    const result = fn(10, 20)
    console.log(result)
    
  2. 新建 rollup.config.js 文件,并编写配置信息。

    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
    }
    
  3. 运行 npx rollup -c 命名进行打包,会发现,打包输出的文件中并没有对 JavaScript 代码进行压缩。
    在这里插入图片描述

  4. 安装 @rollup/plugin-terser 插件用来对打包后的 JavaScript 代码进行压缩 :npm install @rollup/plugin-terser -D

  5. 修改 rollup.config.js 文件中的配置信息。

    // 引入 terser 插件
    const terser = require('@rollup/plugin-terser')
    
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        // 使用 terser 插件
        terser()
      ]
    }
    
  6. 运行 npx rollup -c 命名进行打包,会发现,打包输出的文件中对 JavaScript 代码进行了压缩。
    在这里插入图片描述

使用 Rollup 处理 CSS 文件:

  1. 新建 src/css/index.css 文件,并编写代码。
    body {
      background-color: red;
    }
    
  2. 新建 src/index.js 文件,并编写代码。
    import './css/index.css'
    
  3. 新建 rollup-config.js 文件,并编写配置信息。
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      }
    }
    
  4. 运行 npx rollup -c 命令进行打包,会发现,报错了,Rollup 无法处理 CSS 文件。
    在这里插入图片描述
  5. 安装 rollup-plugin-postcss 插件处理 CSS 文件:npm install rollup-plugin-postcss -D
  6. 安装 PostCSS:npm install postcss -D
  7. 修改 rollup.config.js 文件的配置信息。
    // 引入 postcss 插件
    const postcss = require('rollup-plugin-postcss')
    
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        // 使用 terser 插件
        postcss()
      ]
    }
    
  8. 运行 npx rollup -c 命令进行打包,会发现,打包成功了,CSS 被打包进了输出文件中。
    请添加图片描述

使用 Rollup 处理 Vue 文件:

  1. 安装 Vue2:npm install vue@2
  2. 新建 src/js/App.vue 文件,并编写代码。
    // src/js/App.vue
    <template>
    	<div>{{title}}</div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            title: 'Hello Vue'
          }
        }
      }
    </script>
    
    <style scoped></style>
    
  3. 新建 src/index.js 文件,并编写代码。
    // src/index.js
    import Vue from 'vue'
    import App from './js/App.vue'
    
    new Vue({
      render: h => h(App)
    }).$mount('#app')
    
  4. 运行 npx rollup -c 命令,会发现报错了,Rollup 无法处理 Vue 文件。
    在这里插入图片描述
  5. 安装 rollup-plugin-vue 插件用来处理 Vue 文件:npm install rollup-plugin-vue -D

    可以使用 rollup-plugin-vue@4.6.1 来处理 Vue2。如果是 Vue3,需要使用比较新的版本。

  6. 安装 vue-template-compiler 用来处理 Vue 中的模板语法:npm install vue-template-compiler -D
  7. 新建 rollup.config.js 文件,并编写配置信息。
    const vue = require('rollup-plugin-vue')
    module.exports = {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        vue()
      ]
    }
    
  8. 运行 npx rollup -c 命令,会发现打包成功了。
    在这里插入图片描述

使用 Rollup 开启一个本地服务:

  1. 新建 src/index.js 文件,并编写代码。
    console.log('index')
    
  2. 新建 index.html 文件,并编写代码。
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <script src="./dist/index.js"></script>
    </body>
    </html>
    
  3. 安装 rollup-plugin-serve 插件开启一个本地服务:npm install rollup-plugin-serve -D
  4. package.json 文件添加 "type": "module" 配置。
  5. 新建 rollup.config.js 文件,并编写配置信息。
    // 引入 serve 插件
    import serve from 'rollup-plugin-serve'
    
    export default {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        // 使用 serve 插件
        serve({
          // 默认打开浏览器
          open: true,
          // 端口号
          port: 8080,
          // 服务哪一个文件夹,. 表示的就是以 rollup.config.js 为参照物所在的当前的文件夹,因为 index.html 就在根目录下
          contentBase: '.',
        })
      ]
    }
    
  6. 运行 npx rollup -c 命令进行打包,会发现,编译成功并自动开启了一个本地服务打开了浏览器,但此时,如果更改了代码,无法自动重新编译并刷新浏览器。
    请添加图片描述
    在这里插入图片描述
  7. 首先要想更改了代码自动重新编译,需要在命令行中增加一个参数 w 来实现监听:npx rollup -c -w
  8. 然后要想在重新编译之后自动刷新浏览器,需要安装 rollup-plugin-livereload 插件:npm install rollup-plugin-livereload -D

    rollup-plugin-livereload 插件实现的是实时刷新浏览器,并不是模块热替换。

  9. 更改 rollup.config.js 文件中的配置信息。
    import serve from 'rollup-plugin-serve'
    // 引入 livereload 插件
    import livereload from 'rollup-plugin-livereload'
    
    export default {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
      plugins: [
        serve({
          open: true,
          port: 8080,
          contentBase: '.',
        }),
        // 使用 livereload 插件
        livereload()
      ]
    }
    
  10. 运行 npx rollup -c -w 命令进行打包,会发现,编译成功并自动开启了一个本地服务打开了浏览器,如果更改了代码,也会自动重新编译并刷新浏览器。

Rollup 区分环境:

  1. 给命令行增加一个 enviromment 参数来区分环境:npx rollup -c --environment NODE_ENV:development
  2. rollup.config.js 配置文件中获取传入的环境参数。
    console.log(process.env.NODE_ENV)
    export default {
      input: './src/index.js',
      output:{
        file: 'dist/index.js'
      },
    }
    
  3. 运行 npx rollup -c --environment NODE_ENV:development 命令进行打包,会发现,获取到了 development。
    在这里插入图片描述