代码魔法:探秘背后的奇幻-NPM库世界

前言打造属于自己的npm库 - 走进编程世界的新奇冒险

编程世界是一个充满无限可能的地方,它让我们能够创造出令人惊叹的应用和工具,改变着我们的生活方式和社会。不论你是一个刚踏入这个神奇领域的新手,还是一个经验丰富的老手,你已经取得了很大的进步,学会了使用现有的npm库来加速你的开发过程。现在,是时候向前迈出更大的一步,创造属于自己的npm库,让你的想象力得到充分的发挥!

为什么要写npm库?

你可能会疑问,为什么要自己动手写一个npm库呢?因为编写自己的npm库不仅可以提高你的技术水平,还能让你的代码为他人所用,让更多人受益。你的库可能解决了某个特定问题,或者提供了一种新颖的方法来处理常见任务。这是你展示才华、学习和成长的机会。

本教程的目标

在这个教程中,我将带你逐步了解如何创建自己的npm库。无需担心,我们将从最基础的开始,确保即使是没有太多经验的新手也能跟上。随后,我们将深入探讨npm库的结构、创建和发布过程,以及如何使用Node.js技术来实现功能强大、高质量的npm库。

将学到的技能

通过本教程,你将学到以下关键技能:

  1. 使用npm初始化一个新的npm库项目
  2. 编写库的代码和文档
  3. 进行本地测试和调试
  4. 发布你的npm库到全球npm注册表
  5. 处理版本控制和库维护

走向新奇冒险

写npm库是一段充满新奇冒险的旅程。它不仅让你深入了解软件开发的方方面面,还为你提供了与其他开发者分享和学习的机会。最重要的是,它展示了你的独创性和创造力。

我相信你已经准备好踏上这个令人兴奋的旅程。让我们一起开始吧!探索编程的乐趣,创造属于自己的世界,让你的代码闪耀着光芒,影响着未来。

祝你编程之旅愉快!

1. 搭建一个简单的npm库项目

一个优秀的项目必须建立在稳固的基础架构之上,因此我们首先需要确立项目规范并搭建良好的基础架构

所以接下来就开始搭建起始项目啦!

由于本篇文章只讲述搭建项目的核心芝士,所以prettier、eslint、commitlint、husky等这些基础规范配置就跳过了

当然!有兴趣的话或者不想自己搭建可以跳过,直接使用我搭建的更全面的 起始框架 starter-ts (求个star~)

初始化项目文件

  • 创建项目文件夹 mkdir start-npm
  • 进入项目文件夹 cd start-npm
  • 初始化package pnpm init
    • 我这边使用的是pnpm,要使用其他的都没问题
  • 由于是ts开发,所以安装 pnpm i typescript@4.8.4 -D
  • 使用vscode打开当前的目录 code .
    • 如果是mac的话 需要cmd + shift + p开启code命令

初始化vitepress

安装vitepress

zsh 复制代码
pnpm add -D vitepress@latest

初始化vitepress

zsh 复制代码
pnpm dlx vitepress init

我的选择是这些,建议与我的相同

然后需要在vitepress的config中加上base

因为后续的github pages的初始路径就是项目的名字,不设置的话部署完成之后是会路径错误的

此时执行 pnpm run docs:dev 就可以运行vitepress项目啦!

里面的各种可以在 config.ts 文件中配置 具体的可以查看官方文档,这里就不一一赘述了

安装vite打包工具

  • 首先,项目中还需要安装vue与vue-tsc

    • vue在vitepress中写组件会用到
    • vue-tsc在打包的时候会用到
    zsh 复制代码
    pnpm i vue vue-tsc -D
  • 然后安装打包工具: pnpm i vite vite-plugin-build rimraf -D

    • vite-plugin-build 是一款vite社区的plugin
      • 原生的vite库模式只能打包文件
      • 而这款插件支持整个文件夹的转换和声明文件生成
      • 详细的可以查看官方文档
    • rimraf是一款删除文件的工具
  • 接着需要在package.json中增加以下script

    json 复制代码
    {
      "scripts": {
        "build": "npm run clean && vue-tsc --noEmit && vite build",
        "clean": "rimraf dist lib es types",
      }
    }

配置vite打包

  • 创建 vite.config.ts
  • 以下主要是通过vite-plugin-build打包的
  • 详细的配置说明可以查看vite-plugin-build
  • 其中也用到了rollup配置,详细的可以查看官方文档
ts 复制代码
import path from 'path'
import { defineConfig } from 'vite'
import { buildPlugin } from 'vite-plugin-build'

export default defineConfig({
  plugins: [
    buildPlugin({
      fileBuild: {
        emitDeclaration: true, // 生成声明
        inputFolder: 'packages', // 输入根目录
        ignoreInputs: ['**/*.spec.*', '**/*.test.*', '**/*.d.ts', '**/*.vue', '**/*.md'] // 排除转换的文件
      },
      libBuild: {
        buildOptions: [
          {
            rollupOptions: {
              external: ['vue'], // 排除打包的依赖
              output: { globals: { vue: 'vue' } } // 指定外部依赖
            },
            lib: {
              formats: ['es', 'cjs'], // 打包转换的模式
              entry: path.resolve(__dirname, 'packages/index.ts'), // 入口文件
              name: 'starter-ts',
              fileName: (format) => `index.${format}.js`
            }
          }
        ]
      }
    })
  ]
})

配置 tsconfig.json

ts 复制代码
{
  "compilerOptions": {
    "target": "ESNext",
    "removeComments": true, // 删除注释
    "alwaysStrict": true, // 在代码中注入'use strict'
    "noImplicitAny": true, // 不允许隐式的any类型
    "noImplicitThis": true, // 不允许this有隐式的any类型
    "sourceMap": false, // 生成目标文件的sourceMap文件
    "noUnusedLocals": false, // 检查只声明、未使用的局部变量(只提示不报错)
    "strictNullChecks": true, // 不允许把null、undefined赋值给其他类型的变量
    "strictFunctionTypes": true, // 不允许函数参数双向协变
    "module": "CommonJS",
    "esModuleInterop": true, // 允许export=导出,由import from 导入
    "moduleResolution": "node", // 模块解q析策略,ts默认用node的解析策略,即相对的方式导入
    "lib": ["ESNext"],
    "resolveJsonModule": true,
    "strict": true,
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "types": ["vitest/globals"]
  },
  "include": ["packages/**/*"],
  "ts-node": {
    "files": true
  }
}

安装vitest单测工具

zsh 复制代码
npm i vitest -D

接下来,为了执行测试,请将以下部分添加到你的 package.json 文件中:

json 复制代码
{
  "scripts": {
    "test": "vitest"
  }
}

另外建议安装vscode的vitest扩展,可以方便测试

vitest详细的配置可以查看 vitest官方文档

2. 编写库代码

创建一个hook - useSum

  • 首先在packages下创建一个这样的文件结构

    js 复制代码
    useSum
    ├─index.md // hook对应的文档
    ├─index.test.ts // hook的测试程序
    └index.ts // hook的入口文件
  • index.ts useSum源码

    ts 复制代码
    export const useSum = (a: number, b: number) => a + b
  • index.test.ts useSum测试

    ts 复制代码
    import { describe, expect, it } from 'vitest'
    
    import { useSum } from './index'
    
    describe('useSum', () => {
      it('should return the sum of two numbers', () => {
        const result = useSum(3, 5)
        expect(result).toBe(8)
      })
    
      it('should handle negative numbers', () => {
        const result = useSum(-2, -4)
        expect(result).toBe(-6)
      })
    
      it('should handle zero values', () => {
        const result = useSum(0, 0)
        expect(result).toBe(0)
      })
    })
  • index.md useSum文档

    md 复制代码
    # useSum
    
    计算两数之和
    
    ## 示例
    
    ```vue
    <template>
      <div>
        <input type="number" v-model="val1" />
        <input type="number" v-model="val2" />
        <br /><br />
        result: {{ sum }}
      </div>
    </template>
    
    <script setup lang="ts">
    import { useSum } from '.'
    import { ref, computed } from 'vue'
    
    const val1 = ref(1)
    const val2 = ref(1)
    
    const sum = computed(() => useSum(val1.value, val2.value))
    </script>
    ```
  • 然后在vitepress的sidebar中添加上useSum的文档连接

    js 复制代码
    {
        sidebar: [
          {
            text: 'hooks',
            items: [
              { text: 'useSum', link: '/useSum/' }]
          },
          {
            text: 'Examples',
            items: [
              { text: 'Markdown Examples', link: '/markdown-examples' },
              { text: 'Runtime API Examples', link: '/api-examples' }
            ]
          }
        ]
    }
  • 最后一步:创建库入口文件

    • 在packages下创建一个index.ts文件
    ts 复制代码
    export * from './useSum'

到现在就已经开发完一个hook了,然后可以执行test文件进行测试,通过之后就可以打包发包啦

3. 打包项目

以上流程都做好之后就可以打包项目了

zsh 复制代码
pnpm run build

打包结果会创建以下3个文件夹

json 复制代码
├─dist // 通过主入口文件打包出的文件夹
├─es   // vite-plugin-build 打包出的es模式
├─lib  // vite-plugin-build 打包出的commonJs模式

4. 发包前的准备

配置 package.json

json 复制代码
{
  "name": "start-npm",
  "version": "1.0.0",
  "description": "description", // 项目描述
  "author": "coderhyh <coderhyh@gmail.com>", // 作者
  "license": "MIT", // 开源许可证
  "homepage": "https://coderhyh.github.io/start-npm",
  "repository": { // 仓库来源
    "type": "git",
    "url": "git+https://github.com/coderhyh/start-npm"
  },
  "bugs": "https://github.com/coderhyh/start-npm/issues", 
  "main": "./lib/index.js", // commonJs模式入口文件
  "types": "./es/index.d.ts", // ts类型入口文件
  "module": "./es/index.js", // es模式入口文件
  "files": [ // 发包包含的文件
    "dist",
    "lib",
    "es"
  ],
  "sideEffects": [ // tree shaking 优化
    "dist/*"
  ],
  "keywords": [ // 库的关键词 利于搜索
    "start-npm"
  ],
  "exports": { // 声明模块的导出方式 使你的库在不同的环境中能够被正确地引用和加载
    ".": {
      "types": "./es/index.d.ts",
      "import": "./es/index.js",
      "require": "./lib/index.js"
    },
    "./es": {
      "types": "./es/index.d.ts",
      "import": "./es/index.js"
    },
    "./lib": {
      "types": "./lib/index.d.ts",
      "require": "./lib/index.js"
    },
    "./*": "./*"
  },
  "scripts": {
    "build": "npm run clean && vue-tsc --noEmit && vite build",
    "clean": "rimraf dist lib es types",
    "test": "vitest",
    "docs:dev": "vitepress dev packages",
    "docs:build": "vitepress build packages",
    "docs:preview": "vitepress preview packages"
  },
  "devDependencies": {
    "rimraf": "^5.0.1",
    "typescript": "^4.8.4",
    "vite": "^4.4.9",
    "vite-plugin-build": "^0.10.0",
    "vitepress": "1.0.0-beta.7",
    "vitest": "^0.34.1",
    "vue": "^3.3.4",
    "vue-tsc": "^1.8.8"
  },
  "dependencies": {}
}

这里重点解释一下 dependencies 字段:

dependencies中存放的是当前库的依赖, 比如我的库依赖js-cookie, 那么在我的库被下载时, npm便会读取package.json文件,下载库所需的依赖到node_modules

package版本控制

安装bumpp

zsh 复制代码
pnpm i bumpp -D

bumpp是一个版本控制工具,用于协助在更新 npm 包版本时生成更友好和可定制的版本变更提示信息。在开发和维护 npm 包时,更新版本是一个常见的操作,而 bumpp 可以帮助你生成有意义的版本变更说明,以便用户和开发者了解每个版本的改动。

并在package.json的scripts中增加以下

json 复制代码
{
  "scripts": {
    "release": "bumpp",
  }
}

之后切换版本就会更加友好啦,并且还会自动commit、tag、push

配置 .gitignore

lua 复制代码
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
bin
es
lib
cli
dist-ssr
packages/.vitepress/cache
*.local

# Editor directories and files
# .vscode/*
# !.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

创建github actions

GitHub Actions 是 GitHub 提供的一项持续集成(CI)和持续部署(CD)服务。它允许开发者自动化构建、测试和部署他们的代码,以提高开发工作流程的效率和可靠性。GitHub Actions 可以与 GitHub 仓库紧密集成,使开发者能够通过配置文件定义自定义的工作流程。

也就是说可以使用github actions实现自动化部署文档、自动发包。现在就开始吧!

  • 首先在根目录创建对应文件

    js 复制代码
    ├─.github
    | ├─workflows 
    | | ├─docs.yml   // 自动部署文档
    | | └publish.yml // 自动发包
  • docs.yml

    • 这个配置文件定义了一个完整的工作流程,涵盖了从代码检出到文档构建和部署的各个步骤,以自动化地将文档更新发布到 GitHub Pages 上
    yml 复制代码
    name: Deploy Docs # 工作流程的名称,显示在 GitHub Actions 页面上
    
    on: # 定义触发事件
      workflow_dispatch: # 运行手动执行
      push: # 当push的是master的分支,且修改的文件是paths中的,就会执行这个action
        branches:
          - master
        paths:
          - 'packages/**/*.md'
          - 'packages/.vitepress/**'
          - 'packages/public/**'
    
    jobs: # 定义一个或多个作业(jobs)
      docs: 
        runs-on: ubuntu-latest # 指定作业运行在 `ubuntu-latest` 操作系统上
    
        steps: # 定义作业中的一系列步骤
          # 使用 `actions/checkout` 动作来检出代码库的内容
          - name: Checkout 🛎️
            uses: actions/checkout@v3.5.3 
          # 安装指定版本的 pnpm 包管理器
          - name: Install pnpm 
            uses: pnpm/action-setup@v2 
            with:
              version: '8.x'
          # 设置 Node.js 环境,然后进行依赖安装和文档构建
          - name: Install and Build 🔧
            uses: actions/setup-node@v3.7.0 
            with:
              node-version: '16.x'
              cache: pnpm
          - run: pnpm i
          - run: pnpm run docs:build
          # 将构建好的文档部署到 GitHub Pages
          - name: Deploy to GitHub Pages 🚀
            uses: JamesIves/github-pages-deploy-action@v4.4.3
            with:
              branch: pages # 指定部署到的分支名称
              folder: packages/.vitepress/dist # 指定需要部署的文件夹路径
  • publish.yml

    • 通过这个配置文件,GitHub Actions 会在推送一个标签,并且标签名符合 v* 格式的时候,自动执行一系列步骤,包括安装依赖、构建项目以及将代码包发布到 NPM 包管理器。这使得发布新版本的 npm 包变得更加自动化和便捷
    yml 复制代码
    name: Publish Package To Npmjs
    # 定义触发工作流程的事件。在这里,工作流程会在标签推送到代码库,并且标签名符合 `v*` 格式时触发
    on:
      workflow_dispatch: # 运行手动执行
      push:
        tags:
          - 'v*'
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout 🛎️
            uses: actions/checkout@v3.5.3
          # 设置 Git 配置,以便在发布时使用指定的用户名和邮箱
          - name: Configure Git
            run: |
              git config user.email "772567615@qq.com"
              git config user.name "coderhyh"
    
          - name: Install pnpm
            uses: pnpm/action-setup@v2
            with:
              version: '8.x'
    
          - uses: actions/setup-node@v3.7.0
            with:
              node-version: '16.x'
              registry-url: 'https://registry.npmjs.org/'
              cache: pnpm
    
          - name: ⏳ Install dependencies
            run: pnpm i
    
          - name: 👷  Build lib
            run: pnpm run build
          # 使用 `npm` 命令来发布包到 NPM 注册表
          - name: 📦 Publish
            run: npm publish
            env:
              NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # 使用 GitHub Actions 的 secrets 存储的 NPM token
              NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # 另一种存储 NPM token 的环境变量

配置github中的settings

1. 要设置一下仓库的actions权限,不然的话执行工作流一些操作是没有权限的

然后往下滑 选择这个选项保存

2. 配置github pages

这里选择的分支是pages是因为上面的action工作流把打包的文档放在了pages分支下

如此就可以通过github站点访问部署的文档了

3. 配置npm发包的token

这个是需要创建npm账号的,可以自行创建

创建npm token

然后拿到token放在仓库即可

5. 发布仓库

如此一来,所有操作都已完成,现在就可以初始化仓库并发布到仓库

记住!包名不要重复!!不然发布npm不可以的!!!

如果首次发布没有给tag, 是不会执行publish的action, 所以可以去仓库actions中手动执行一下

仓库的action执行都可以在这里看到了,并且可以点击进入查看更详细的信息

手动发布npm包

这里说一下本地手动发布npm包的流程

  • 创建一个npm账号
  • npm的镜像源一定要设置会npm的
    • 因为要发布到npm官网, 所以这个是不能错的
  • 然后cd到项目中
  • npm login 登录账号
  • npm publish 发布

6. 大功告成

现在,就可以在npm查看自己发布的包了

以下是我发布的一个库,有兴趣的童鞋可以拿去参考一下 hyh-toolkit 求个star~

结语

在这个教程中,我们一起探索了创建自己的npm库的精彩世界。从最初的规划到最后的实现,你已经迈出了许多令人激动的步伐,成为了自己的npm库创造者。

通过编写npm库,我们不仅提高了技术水平,还为开发社区贡献了独特的知识和创意。自己的库可能会成为其他开发者的强大工具,解决问题,推动项目向前发展。

感谢你我一起完成这个npm库的创造之旅。我相信,你将继续在编程的世界里谱写属于自己的精彩篇章。愿你的代码充满创造力,影响着更多的人,并为这个美妙的技术世界添彩。

祝你编程之路越走越远,不断迸发新的创意和成就!

相关推荐
想睡好几秒前
css文本属性
前端·css
qianmoQ2 分钟前
第三章:组件开发实战 - 第五节 - Tailwind CSS 响应式导航栏实现
前端·css
zhoupenghui16815 分钟前
golang时间相关函数总结
服务器·前端·golang·time
White graces29 分钟前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea
庸俗今天不摸鱼30 分钟前
Canvas进阶-4、边界检测(流光,鼠标拖尾)
开发语言·前端·javascript·计算机外设
bubusa~>_<1 小时前
解决npm install 出现error,比如:ERR_SSL_CIPHER_OPERATION_FAILED
前端·npm·node.js
流烟默2 小时前
vue和微信小程序处理markdown格式数据
前端·vue.js·微信小程序
梨落秋溪、2 小时前
输入框元素覆盖冲突
java·服务器·前端
菲力蒲LY2 小时前
vue 手写分页
前端·javascript·vue.js
天下皆白_唯我独黑3 小时前
npm 安装扩展遇到证书失效解决方案
前端·npm·node.js