使用rollup打包前端工具库并配置github自动构建和发布npm

871 阅读4分钟

1 准备工作

  • 在github上创建仓库并clone到本地
  • npm init 初始化配置
zhongweisheng@zws code % git clone https://github.com/Weison-Zhong/weison-utils.git
zhongweisheng@zws code % cd weison-utils 
zhongweisheng@zws weison-utils % npm init
package name: (weison-utils) weison-utils
version: (1.0.0) 0.0.1
description: 前端常用工具库
entry point: (index.js) 
test command: 
git repository: (https://github.com/Weison-Zhong/weison-utils.git) 
keywords: 前端 前端工具库 utils 钟伟胜
author: weison
license: (ISC) MIT
Is this OK? (yes)
  • 创建src和dist目录 image.png
  • 在src目录下新建index.js并写上工具函数
export function myTypeof(val) {
  var type = typeof val;
  var resObj = {
    "[object Array]": "array",
    "[object Map]": "map",
    "[object Set]": "set",
    "[object Object]": "object",
    "[object Number]": "object number",
    "[object String]": "object string",
    "[object Boolean]": "object boolean",
  };
  if (val === null) {
    return "null";
  } else if (type === "object") {
    var typeStr = Object.prototype.toString.call(val);
    return resObj[typeStr];
  } else {
    return type;
  }
}

//节流,连续触发只会在每time时间段内执行回调
//例如滚动屏幕scroll,不停的滚动只会在[0,time],[time+1,time*2],...每个time时间段内分别执行一次回调
export function throttle(
  cb,
  interval,
  isImmediately = true,
  isLastExec = false
) {
  //isImmediately是否首次触发事件马上执行回调,否的话则等到下个time时间段再执行
  //isLastExec是否执行最后一次
  let last = isImmediately ? 0 : Date.now();
  let t = null;
  return function () {
    const args = arguments;
    const now = Date.now(); //当前时间戳
    if (now - last > interval) {
      //上次执行的时间戳减去当前触发事件的时间戳大于设定的间隔
      cb.apply(this, args);
      last = now; //回调后更新最新一次执行的时间戳
    } else if (isLastExec) {
      t && clearTimeout(t);
      t = setTimeout(() => {
        cb.apply(this, args);
        last = Date.now(); //需要重新获取now并刷新last防止最后一次执行后新触发事件时立马执行
      }, interval);
    }
  };
}

//防抖,连续触发只会在最后一次触发事件延迟time内不再触发事件后执行回调一次
//例如滚动屏幕scroll,不停的滚动只会在(1,需要停止滚动 2,且停止滚动后等待time内不再滚动)后执行一次回调
export function debounce(cb, time = 3000, isImmediately = false) {
  //isImmediately是否立即执行
  let t = null;
  let exec = true;
  return function () {
    const args = arguments;
    t && clearTimeout(t); //清除上次触发事件的定时器
    if (isImmediately && exec) {
      cb.apply(this, args); //首次需立即执行
      exec = false;
    } else {
      t = setTimeout(() => {
        //重新设定最新一次触发事件的定时器
        cb.apply(this, args); //time内不再触发,即t不被clear,那么time后执行一次回调cb
      }, time);
    }
  };
}

//深拷贝
export function deepClone(origin, target) {
  var tar = target || {},
    toStr = Object.prototype.toString,
    arrType = "[object Array]";

  for (var key in origin) {
    if (origin.hasOwnProperty(key)) {
      if (typeof origin[key] === "object" && origin[key] !== null) {
        toStr.call(origin[key]) === arrType ? (tar[key] = []) : (tar[key] = {});
        deepClone(origin[key], tar[key]);
      } else {
        tar[key] = origin[key];
      }
    }
  }
  return tar;
}

2 配置rollup并打包

  • npm install -D rollup
  • 根目录下新建rollup.config.js配置文件
export default {
  input: "./src/index.js", // 入口
  output: [
    {
      format: "umd", // 打包为umd通用格式,兼容了amd和CommonJS,可在浏览器或node环境运行
      file: "dist/index.js", //输出目录及文件名
      name: "index.js",
    },
  ],
};
  • 修改package.json配置文件
{
  "name": "weison-utils",
  "version": "0.0.1",
  "description": "前端常用工具库",
+  "main": "dist/index.js",
   "scripts": {
+    "build": "rollup -c"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Weison-Zhong/weison-utils.git"
  },
  "keywords": [
    "前端",
    "前端工具库",
    "utils",
    "钟伟胜"
  ],
  "author": "weison",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/Weison-Zhong/weison-utils/issues"
  },
  "homepage": "https://github.com/Weison-Zhong/weison-utils#readme",
  "devDependencies": {
    "rollup": "^2.76.0"
  }
}
  • 运行 npm run build 打包 image.png

3 发布到npm

  • 注册npm账号注册入口
  • 如果设置了其他npm镜像源的务必要换回官方源
    • npm config set registry https://registry.npmjs.org
  • 登录 npm login 按提示操作 image.png
  • 发布 npm publish

image.png

image.png

4 发布成功后尝试在项目中使用,以我博客的置顶按钮显隐切换为例

  • yarn add weison-utils

image.png

import React, { useEffect, useState, useCallback, memo } from "react";
import { getScrolledSize, getViewportSize } from "../../utils/tools";
import { debounce } from "weison-utils";
const handleScrollToTop = () =>
  (document.body.scrollTop = document.documentElement.scrollTop = 0);

export default memo(() => {
  const [isShow, setIsShow] = useState(false);
  const scrollCb = useCallback(() => {
    const scrolledHeight = getScrolledSize().top;
    const clientHeight = getViewportSize().height;
    if (scrolledHeight > clientHeight / 2) {
      //滚动距离超过窗口高度一半时显示置顶按钮
      setIsShow(true);
    } else {
      setIsShow(false);
    }
  }, []);
  useEffect(() => {
    const debouncedScrollCb = debounce(scrollCb, 800);
    document.addEventListener("scroll", debouncedScrollCb);
    return () => document.removeEventListener("scroll", debouncedScrollCb);
  }, []);
  return (
    <>
      {isShow && (
        <button
          className="bg-primary fixed z-50 bottom-3 right-3 w-10 h-10 border-2 rotate-180 rounded-full overflow-hidden border-secondary hover:border-primary focus:border-primary focus:outline-none"
          onClick={handleScrollToTop}
        >
          <i className="icon-long-arrow-down iconfont text-xl text-secondary" />
        </button>
      )}
    </>
  );
});

5 设置github action自动发布npm

  • 到npm官网登录账号生成一个token,点击右上角个人中心Access Tokens image.png
  • 新建一个名为npm的token

image.png

image.png

  • 复制token值

image.png

  • 把刚刚复制的token值粘贴到github上

image.png

  • 这里的Name命名可按照个人喜好

image.png

  • 在Actions选项下输入 Publish Node.js Package 按回车键搜索

image.png

  • 修改npm-publish.yml文件如下
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages

name: Node.js Package

on:
  push:
    branches:
      - main  //推送到main分支触发构建

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm i

  publish-npm:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          registry-url: https://registry.npmjs.org/
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.npm}} //刚刚添加的npm的token值(注意这里的secrets.xxx里面的xxx要和上面自定义token名的Name对应上)
  • 点击右上角Start commit 保存 image.png

  • 回到工具库代码,我们删掉package-lock.json这个文件,不然待会GitHub会build失败;

image.png

  • 记得每次更新要修改下版本号,如果版本号有冲突那么npm发布是会失败的

image.png

  • 尝试push代码触发自动构建发布

image.png

最后

  • github链接 整个工具库比较基础,没有用到typescript,单元测试和组件库文档,后续学习了这块知识再来更新啦~~~
  • 我还有篇文章介绍入门写react组件库,感兴趣的可以瞄瞄一步步写一个react组件库并打包发布到npm
  • 最后分享下我的博客网站,学习react后写的,开源了管理系统及后台WebApi,欢迎查看交流 👉 www.weison-zhong.cn