rollup 打包utils工具库 完整配置 jest单元测试(index动态加载,按需加载)

前言

网上关于使用 rollup 打包工具库的资料可谓是不少,但是似乎都没有贴出对应的package.json,导致虽然内容写的很详细,但是实际安装rollup.js版本的时候,错误百出(版本不一致,很多地方无法兼容)

先贴一版package.json,都是亲测可用的

{
  "name": "rollup-decentralization-template",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "serve": "rollup -i src/index.js -o dist/bundle.js -f es",
    "build": "rollup -c --bundleConfigAsCjs",
    "dev": "rollup -c rollup.dev.js --bundleConfigAsCjs",
    "build:dev": "rollup -c rollup.dev.js  -w --environment NODE_ENV:development --bundleConfigAsCjs",
    "build:prod": "rollup -c rollup.dev.js --environment NODE_ENV:production --bundleConfigAsCjs",
    "build:test": "jest"
  },
  "repository": {
    "type": "git",
    "url": "https://gitee.com/lining_21/rollup-decentralization-template.git"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2",
    "@rollup/plugin-eslint": "^9.0.1",
    "@rollup/plugin-node-resolve": "^15.0.1",
    "generate-source-map": "0.0.5",
    "jest": "^29.3.1",
    "postcss": "^8.4.20",
    "rollup": "^3.7.3",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-postcss": "^4.0.2",
    "rollup-plugin-require-context": "^1.0.1",
    "rollup-plugin-terser": "^7.0.2"
  }
}

插件

就目前来看需要的插件基本上就是这些

import babel from 'rollup-plugin-babel' // 转换es6语法。把自己写的方法,箭头函数啥的转为function
import commonjs from 'rollup-plugin-commonjs'// rollup默认是不支持CommonJS模块的,自己写的时候可以尽量避免使用CommonJS模块的语法,但有些外部库的是cjs或者umd(由webpack打包的),所以使用这些外部库就需要支持CommonJS模块
import eslint from '@rollup/plugin-eslint'  // eslint检查
import resolve from '@rollup/plugin-node-resolve'// 无后缀名引用时,需要识别 .vue 文件
import { terser } from 'rollup-plugin-terser'  // 压缩文件
import requireContext from 'rollup-plugin-require-context'// 支持 require.context 语法 需配合 ignore: ["conditional-runtime-dependency"] 实现

我汇总了一些大佬的rollup配置,主要包含如下几篇

# [踩坑] Rollup 打包 Vue 组件库项目 完整配置

# rollup从入门到打包一个按需加载的组件库

# 用rollup打包vue组件库

多仓库管理工具库成本实属太大,于是想做成npm包依赖减少维护成本,也利于多团队成员之间的维护,选用的是rollup工具打包。对于大团队的开发成本来说,如果不做统一工具库,一旦团队成员修改了,其不知道对其他工具使用方的影响,容易造成方法冗余或者错误

附上 rollup 官方文档

还是建议先多看看官方文档,毕竟教程这些东西不会是最新的。

以下从头开始讲解

rollup安装与使用

npm i rollup -g # 全局安装 
npm i rollup -D # 项目本地安装

然后一步一步安装插件

npm install rollup-plugin-babel -D
npm install rollup-plugin-commonjs -D
npm install @rollup/plugin-eslint -D
npm install @rollup/plugin-node-resolve -D
npm install rollup-plugin-require-context -D

插件安装完后,再使用过程中可能会提示某些插件没安装。例如rollup-plugin-require-context使用时,会提示generate-source-map未安装,只需按照 npm install XXX -D 的形式 ,依次安装即可。

或者 粗暴一点

直接将package.json中的devDependencies复制到自己的 package.josn中 直接 npm install

  "devDependencies": {
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2",
    "@rollup/plugin-eslint": "^9.0.1",
    "@rollup/plugin-node-resolve": "^15.0.1",
    "generate-source-map": "0.0.5",
    "jest": "^29.3.1",
    "postcss": "^8.4.20",
    "rollup": "^3.7.3",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-postcss": "^4.0.2",
    "rollup-plugin-require-context": "^1.0.1",
    "rollup-plugin-terser": "^7.0.2"
  }

上述配置是经过实践证明可用的

rollup.dev.js 配置

import babel from 'rollup-plugin-babel'
import commonjs from 'rollup-plugin-commonjs'
import postcss from 'rollup-plugin-postcss'
import eslint from '@rollup/plugin-eslint'
import resolve from '@rollup/plugin-node-resolve'
import { terser } from 'rollup-plugin-terser'
import requireContext from 'rollup-plugin-require-context'

const isProd = process.env.NODE_ENV === 'production'

// rollup默认只支持 export import 以及其他 es5 语法(function),因此,需要引入至少commonjs babel,来协助解决我们打包过程中的语法错误
// commonjs,解析编码中 自己写的 或者 第三方引入的 module.exports等语法
// babel 解析编码中,诸如:()=>{} 箭头函数,map等 es6语法。
const basePlugins = [
  // commonjs 转 es6模块
  // rollup默认是不支持CommonJS模块的,自己写的时候可以尽量避免使用CommonJS模块的语法,但有些外部库的是cjs或者umd(由webpack打包的),所以使用这些外部库就需要支持CommonJS模块
  commonjs({
      ignore: ["conditional-runtime-dependency"]
  }),
  // 转换es6语法。把自己写的方法,箭头函数啥的转为function
  babel({
      exclude: 'node_modules/**'
  }),
  // eslint检查
  eslint({
    throwOnError: true,
    throwOnWarning: true,
    include: ['src/utils/**'],
    exclude: ['node_modules/**']
  }),
  // 支持 require.context 语法 需配合 ignore: ["conditional-runtime-dependency"] 实现
  requireContext(),
  resolve({
    extensions: ['.vue'], // 无后缀名引用时,需要识别 .vue 文件
    exclude: '**/node_modules/**'  // 排除node_modules
  }),
  postcss()
]

const devPlugins = []
const prodPlugins = [
  // 压缩文件
  terser()
]

let plugins = [...basePlugins].concat(isProd ? prodPlugins : devPlugins)

export default {
  input: "./src/index.js",
  output: [
    {
      file: './dist/my-lib-umd.js',
      format: 'umd',
      name: 'myLib'   
      //当入口文件有export时,'umd'格式必须指定name
      //这样,在通过<script>标签引入时,才能通过name访问到export的内容。
    },
    {
      file: './dist/my-lib-es.js',
      format: 'es'
    },
    {
      file: './dist/my-lib-cjs.js',
      format: 'cjs'
    }
  ],
  plugins
}

注意:eslint和babel 都要创建对应.eslintrc和.babelrc的文件才能生效

.eslintrc

{
  "env": {
      "browser": true,
      "commonjs": true,
      "es6": true,
      "node": true,
      "mocha": true
  },
  "parserOptions": {
      "ecmaFeatures": {
          "jsx": true
      },
      "sourceType": "module"
  },
  "rules": {
      "no-var": "error",
      "indent": ["error", 2],
      "semi": ["error", "never"],
      "quotes": ["error", "single"]
  }
}

.babelrc

{
  "presets": [
      [
        "@babel/preset-env"
      ]
    ]
}

依次创建utils、test、dist等文件夹

目录结构如下

image.png

其中utils的 文件如下写法
debounce.js

/**
 * 防抖
 * @param {Function} 执行函数
 * @param {Number} delay 延时ms
 */
let _debounceTimeout = null
export default (fn, delay = 500) => {
  clearTimeout(_debounceTimeout)
  _debounceTimeout = setTimeout(() => {
    fn()
  }, delay)
}

sum.js

export default (a, b) => {
  return a + b
}

index.js

const requireCxt = require.context("./utils", true, /.js/)
// requireCxt('./debounce.js') 能获取到 debounce 函数
const components = {}

requireCxt.keys().map((item, index) => {
  const component = requireCxt(item)
  const reg = /(?<=\.\/)(.+?)(?=.js)/g;   // 去掉 ./ 和 js
  const name = item.match(reg)
  return (components[name] = component)
})

export default components

test文件如下
debounce.test.js

jest.useFakeTimers();

const { debounce } = require("../dist/my-lib-cjs");

test('fails to mock debounce', function() {
  var test = jest.fn();
  var debounced =()=> { debounce(test, 1000); }

  debounced();
  debounced();

  jest.runAllTimers();

  expect(test).toHaveBeenCalledTimes(1);
});

sum.test.js

test("adds 1 + 2 to equal 3", () => {
  const { sum } = require("../dist/my-lib-cjs");
  expect(sum(1, 2)).toBe(3);
});

一切准备妥当可以运行了。

npm run build:dev

打包工具库命令(代码不压缩,可正常看代码),可热重载

npm run build:prod

打包工具库命令(代码压缩),可热重载

npm run build:test

jest框架,对工具库方法进行单元测试,可在test文件夹中自行维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值