从零到1构建可发布的npm包

news2024/9/28 17:22:19

本文将介绍通过 rollup, 从零开始构建一个简易的可发布的npm包。本文可实现的目标如下:

  1. 通过 rollup进行构建
  2. 支持 Typescript
  3. 支持 npm 方式安装
  4. 支持 cdn 方式,在页面中引入
  5. 支持本地调试
  6. 可发布到npm

一、从 package 开始项目分析

首先,在终端中 创建我们的包名【wujs】,可执行以下命令行:

mkdir wujs

其次,将 项目【wujs】在vscode中打开,打开项目终端,并执行以下命令, 创建 package.json

npm init

最后 package.json 初始如下:
最后 package.json 初始如下:

{
  "name": "wujs", // 包名
  "version": "1.0.0", // 版本号
  "description": "", // 描述
  "main": "src/index.js", // 入口文件
  "files": ['dist'] // 包发布后,需要打包上传的文件列表
}

二、rollup相关插件下载和初始配置

1.下载rollup插件

npm i rollup -D

2.在根目录,创建 rollup.config.js, 初始内容如下

import path from 'path'
const resolve = (dir) => path.resolve(__dirname, dir)
export default {
  input: resolve('./src/index.js'),
  output: [
    {
      dir: resolve('dist/esm'),
      format: 'esm'
    }
  ]
}

2.1编写脚本如下:

"scripts": {
    "build": "rollup -c"
},

2.2 执行npm run build 即可实现简易编译。

三、对构建输出内容的思考

也就是我们的npm包可以支持哪种方式进行使用?常见的是输出以下三种格式:
esm – 支持npm安装,在构建工具中使用。其特点是:只编译,不打包。实现按需引入
umd – 支持cdn的方式,直接在页面中引入
cjs – 在 node 环境中使用,本文暂时忽略
此外,我们的包需要支持 Typescript, 这就需要对 TS 进行编译,常见的有: Typescript、babel、esbuild。根据有关文章分析,esbuild 的编译速度比babel更快,因此我们使用 esbuild 来将 ts 编译为 js, 使用 typescript 的 tsc 来生成 .d.ts 文件
1.主要插件下载
npm i -D rollup-plugin-esbuild typescript @babel/core @babel/preset-env @rollup/plugin-babel
1.1 其他常规rollup插件
@rollup/plugin-commonjs — 识别 commonjs 模块,并转为 es 模块供rollup 处理
@rollup/plugin-json — 将 json 格式转为es 模块
@rollup/plugin-node-resolve — 简化引入路径。不配置时,引入路径必须是完整的。
npm i -D @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve

2.构建编译成 esm 格式
2.1在根目录,创建 rollup.esm.config.js

import json from '@rollup/plugin-json'
import nodeResolve from '@rollup/plugin-node-resolve'
import path from 'path'
const resolve = (dir) => path.resolve(__dirname, dir)
import esbuild from 'rollup-plugin-esbuild'
export default {
  input: resolve('./src/index.ts'),
  output: [
    {
      dir: resolve('dist/esm'),
      format: 'esm'
    }
  ],
  plugins: [
    esbuild({
      target: 'es2018'
    }),
    nodeResolve(),
    json()
  ],

preserveModules: true, // 只有设置为true, 才可以实现只编译,不打包
external: [‘’] // 非常重要,dependencies 中的属性名都必须列入这里,让rollup不要对其进行打包,而是作为外部依赖
}
2.2编写脚本如下,【postbuild】是【build:esm】的后置脚本,当【build:esm】执行完后会自动执行。
配置【module】,1:用户在使用该包时,可以按需引入,享受TreeShaking带来的好处;2.在配置babel插件时,可以放心屏蔽node_modules

 "module": "dist/esm/index.js",
 "scripts": {
    "build:esm": "rollup -c rollup.esm.config.js",
    "postbuild": "tsc --emitDeclarationOnly --declaration --project ts.config.json --outDir dist/esm"
  },

2.3 常规 ts.config.json配置,
(详情可参考–了不起的 tsconfig.json 指南:https://blog.csdn.net/6346289/article/details/120426715)

{
  "compilerOptions": {
    "module": "commonjs", // 指定生成代码的模板标准
    "noImplicitAny": true, // 不允许隐式的 any 类型
    "removeComments": true, // 删除注释
    "preserveConstEnums": true, // 保留 const 和 enum 声明
    "sourceMap": true // 生成目标文件的sourceMap文件
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

2.4 执行以下脚步,即可实现esm格式的编译

npm run build:esm 

3.构建编译成 umd 格式
3.1 在根目录,创建 rollup.umd.config.js

import path from 'path'
const resolve = () => path.resolve(__dirname, dir)
import esbuild from 'rollup-plugin-esbuild'
import babel from '@rollup/plugin-babel'
import json from '@rollup/plugin-json'
import nodeResolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
export default {
  input: resolve('./src/index.ts'),
  output: [
    {
      file: resolve('dist/umd/index.js'),
      format: 'umd',
      name: 'wujs', // 重要,这是通过 cdn 引入后,挂载到window上的属性名
    },
  ],
  plugins: [
    esbuild({
      target: 'es2015' // 兼容性
    }),
    nodeResolve(),
    json(),
    commonjs(),
    babel({
      extensions: [".js", ".ts"],
      presets: ['@babel/preset-env'],
      exclude: 'node_modules/**',
      babelHelpers: 'bundled'
    })
  ]
}

3.2 编写脚本, 执行以下命令, 完成umd格式的编译

 npm run build:umd 
"scripts": {
    "build:umd": "rollup -c rollup.umd.config.js"
 },

四、对构建物进行调试

4.1 对 umd 构建物的调试
需要下载以下三个插件
cross-env — 区分开发与生产环境
rollup-plugin-serve — 启动一个http 静态服务器
rollup-plugin-livereload —监听某个文件夹,当其中的文件发生变化时,刷新页面
npm i -D cross-env rollup-plugin-serve rollup-plugin-livereload
4.1.1 修改 rollup.umd.config.js

import path from 'path'
const resolve = (dir) => path.resolve(__dirname, dir)
import esbuild from 'rollup-plugin-esbuild'
import babel from '@rollup/plugin-babel'
import json from '@rollup/plugin-json'
import nodeResolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'

import serve from 'rollup-plugin-serve'
import livereload from 'rollup-plugin-livereload'
const isPro = process.env.NODE_ENV === 'production'
const envPlugins = isPro ? [] : [serve({
  port: 1001,
  open: true,
  openPage: '/base/',
  contentBase: ['dist', 'examples']
}), livereload('dist/umd')]

export default {
  input: resolve('./src/index.ts'),
  output: [
    {
      file: resolve('dist/umd/index.js'),
      format: 'umd',
      name: 'wujs', // 重要,这是通过 cdn 引入后,挂载到window上的属性名
    },
  ],
  plugins: [
    esbuild({
      target: 'es2015'
    }),
    babel({
      presets: ['@babel/preset-env'],
      exclude: 'node_modules/**',
      babelHelpers: 'bundled'
    }),
    nodeResolve(),
    json(),
    commonjs(),
    ...envPlugins
  ]
}

新增变化内容如下图红色框处:
在这里插入图片描述

4.1.2 修改脚本,区分环境。
配置 -w 或 watch ,可监听文件更新,实时刷新页面

"scripts": {
    "dev:umd": "cross-env NODE_ENV=development rollup -w -c rollup.umd.config.js",
    "build:umd": "cross-env NODE_ENV=production rollup -c rollup.umd.config.js",
    "build:esm": "cross-env NODE_ENV=production rollup -c rollup.esm.config.js",
  },

4.1.3 在根目录创建 examples/base/index.html
在这里插入图片描述

4.1.4 执行以下命令, 即可进行调试

 npm run dev:umd

4.2 对 esm 构建物的调试
这里使用vue进行调试,如果还没有安装过,请先安装

yarn global add @vue/cli

或者:

npm install -g @vue/cli

4.2.1 创建本地调试项目

vue create example

4.2.2 安装 npm-run-all ,以便异步执行多个脚本

npm i -D npm-run-all

4.2.3 编写脚本如下,只需执行 npm run dev:esm 即可

 "scripts": {
    "build": "run-p \"build:*\"",
    "dev:esm": "run-p watch:esm serve:vue",
    "watch:esm": "cross-env NODE_ENV=development rollup -w -c rollup.esm.config.js",
    "serve:vue": "cd ./examples/vuetest && yarn && yarn serve",
  },

4.2.4 在vue项目中调试,在引入时,其路径无需指定到具体文件,会自动找pkg.main、pkg.module进行匹配
在这里插入图片描述

4.2.5 如果报eslint配置错误,可以在vue3项目中添加vue.config.js ,并设置

module.exports = {
    lintOnSave: false
}

4.2.6 如果报引入路径错误问题。
首先,请先检查,是否将pkg.mian 和 pkg.module指向相关输出文件,如下图(这个的前提是相关配置文件正确)。其次是,引入路径是否可以找到的输出目录,如dist
在这里插入图片描述

五、发布到NPM上

首先要有npm的账号,没有的话,先注册一个。
5.1 执行,会进行登录

npm login

[图片]
5.2 执行以下命令 ,实现包版本号加1

npm version patch

5.3 执行执行以下命令 ,发布到npm

npm publish

如果现在的版本号跟已经发布的重复,则会报错,需要重新执行 【5.2】和【5.3】的步骤,见下图:
在这里插入图片描述

至此,完成项目的构建与发布!
附上终极版 package.json 文件如下:

{
  "name": "wujs",
  "version": "1.1.0",
  "description": "",
  "main": "dist/umd/index.js",
  "module": "dist/esm/index.js",
  "files": [
    "dist"
  ],
  "scripts": {
    "说明1": "--------------------调试umd格式:执行下面这条脚本↓---------------------",
    "dev:umd": "cross-env NODE_ENV=development rollup -w -c rollup.umd.config.js",
    "说明2": "-----------------在vue3中调试esm格式:执行下面这条脚本↓-----------------",
    "dev:esm": "run-p watch:esm serve:vue3",
    "watch:esm": "cross-env NODE_ENV=development rollup -w -c rollup.esm.config.js",
    "serve:vue3": "cd ./examples/vuetest && yarn && yarn serve",
    "说明3": "--------------------打包构建:执行下面这条脚本↓---------------------",
    "build": "run-p \"build:*\"",
    "build:umd": "cross-env NODE_ENV=production rollup -c rollup.umd.config.js",
    "build:esm": "cross-env NODE_ENV=production rollup -c rollup.esm.config.js",
    "postbuild:esm": "tsc --emitDeclarationOnly --declaration --project tsconfig.json --outDir dist/esm"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "@rollup/plugin-babel": "^5.3.1",
    "@rollup/plugin-commonjs": "^22.0.2",
    "@rollup/plugin-json": "^4.1.0",
    "@rollup/plugin-node-resolve": "^13.3.0",
    "cross-env": "^7.0.3",
    "npm": "^8.17.0",
    "npm-run-all": "^4.1.5",
    "rollup": "^2.78.0",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-esbuild": "^4.9.3",
    "rollup-plugin-livereload": "^2.0.5",
    "rollup-plugin-serve": "^2.0.1",
    "typescript": "^4.7.4"
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

港科夜闻|香港科大与香港科大(广州)两校交流开启新篇章

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、香港科大与香港科大(广州)两校交流开启新篇章。2月10日,香港科技大学校董会主席廖长城先生、校董会副主席杨佳锠先生、校长叶玉如院士一行到访香港科大(广州),共商“香港科大一体、双校互补”框架下的…

go gin学习记录3

环境 环境:mac m1,go version 1.17.2, goland, mysql 安装gorm 第二节学习了在gin中使用go的原生SQL进行操作,这节学习一下使用orm。 go的orm包有很多,gorm是使用较多较广的,所以我们就用gor…

车辆逆行识别检测预警算法 yolov5

车辆逆行识别检测预警算法通过Pythonyolov5网络模型计算机算法技术,车辆逆行识别检测预警算法对道路来往行驶车辆出现逆行行为及时预警存档。Python是一种由Guido van Rossum开发的通用编程语言,它很快就变得非常流行,主要是因为它的简单性和…

大数据之-Nifi-监控nifi数据流信息_监控数据来源_bub轻松复现---大数据之Nifi工作笔记0011

通过数据流功能可以轻松复现,数据的流向在某个时间点数据是怎么流动的,出现了什么问题,太强大了.. 真的是,可以看到通过右键,处理器,打开view data province就可以看到, 上面是处理器处理数据的详细信息 点击左侧的详情图标可以查看详情信息,details是这个事件处理的内容详情,…

【计算机网络】运输层

文章目录运输层概述运输层端口号、复用与分用的概念UDP和TCP的对比TCP的流量控制TCP的拥塞控制TCP超时重传时间的选择TCP可靠传输的实现TCP的运输连接管理TCP的连接建立(3次握手)TCP的连接释放(4次挥手)TCP报文段的首部格式运输层概述 这里我们对运输层进行概述,之…

【双指针问题】LeetCode 925. 长按键入

Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…

【C++】类型转化

🌈欢迎来到C专栏~~类型转化 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&…

Python-第九天 Python异常、模块与包

Python-第九天 Python异常、模块与包一、了解异常1. 什么是异常:2. bug是什么意思:二、异常的捕获方法1. 为什么要捕获异常?2. 捕获异常的语法3. 如何捕获所有异常?三、异常的传递性1.异常是具有传递性的四、Python模块1. 什么是模…

21. 合并两个有序链表

题目链接:解题思路:遍历,双指针:因为两个链表有序,所以只需要依次比较两个元素的大小,然后添加到新的链表中即可first指针指向第一个链表l1,second指针指向第二个链表l2,answer保存合…

Python3 JSON 数据解析

Python3 JSON 数据解析 JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。 Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数: json.dumps(): 对数据进行编码。json.loads(): 对数据进行解码。 在 json 的编解码…

CleanMyMac4.12.5最新版安装下载教程

告别硬盘空间不足,让您的Mac极速如新CleanMyMac是一款强大的 Mac 清理、加速工具和健康卫士,让您的 Mac 加快启动速度。CleanMyMac是一款专业的Mac清理软件,可智能清理mac磁盘垃圾和多余语言安装包,快速释放电脑内存,轻…

01:入门篇 - 初识 CTK

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 CTK 是什么 CTK:支持生物医学图像计算的公共开发包 CTK 全称:Common ToolkitCTK 主页:http://www.commontk.org/Github 地址:https://github.com/commontkCTK 标志 Logo 是一个品牌的形象,对外它传递的…

关于 Docke r安装 Redis 的评论区问题总结及解答

前言: 文章链接:史上最详细Docker安装Redis (含每一步的图解)实战 原文标题只是想让我这篇文章,能够多得到大家的一些关注,事实证明它做到了,当然看到收藏量的那一刻,我也明白&…

数据结构课程设计—简单行编辑程序

简单行编辑程序 一、引言 1.1 问题的提出 文本编辑程序是利用计算机进行文字加工的基本软件工具,实现对文本文件的插入、删除等修改操作。限制这些操作以行为单位进行的编辑程序称为行编辑程序。 被编辑的文本文件可能很大,全部读入编辑程序的数据空间(内存)的作法既不经济,…

强化学习基础知识

强化学习是一种机器学习方法,通过agent与environment的互动,学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识,与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…

Python:跳蚱蜢(BFS判重)

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 如下图所示: 有 9 只盘子,排成 1 个圆圈。 其中 8 只盘子内装着 8 只蚱蜢,有一个是空盘。 我们把这些蚱蜢顺时针编号为 1 ~ 8。 …

Java【数据结构】—— 冒泡排序、选择排序、直接插入排序

Java实现冒泡排序、选择排序、直接插入排序一、排序的概念及稳定性二、冒泡排序1.基本思想2.代码实现三、选择排序1.基本思想2.代码实现四、直接插入排序1.基本思想2.代码实现五、复杂度及稳定性分析1.冒泡排序2.选择排序3.直接插入排序一、排序的概念及稳定性 - 概念&#xf…

文件断点续传

1、前端上传文件前请求媒资接口层检查文件是否存在,如果已经存在则不再上传。 2、如果文件在系统不存在前端开始上传,首先对视频文件进行分块 3、前端分块进行上传,上传前首先检查分块是否上传,如已上传则不再上传,如…

奇舞周刊第482期:每天都在用,也没整明白的 React Hook

记得点击文章末尾的“ 阅读原文 ”查看哟~下面先一起看下本期周刊 摘要 吧~奇舞推荐■ ■ ■每天都在用,也没整明白的 React Hook推荐理由:针对我们经常使用的 React Hook,本文详细介绍了 useState、useEffect、useContext、useCallback、use…

IP协议格式、IP地址管理、路由选择

目录 一、IP协议格式 16位总长度 ip协议针对传输层的UCP协议或者TCP协议,进行传输的时候,需不需要进行分片传输(拆包传输) 如何进行分片 和 组合分片 8位生存时间: 8位协议、16位校验和、32位源端口、32位目的端…