如何发布一个npm包

发布一个属于自己的 npm utils

在这里插入图片描述

前言

  • 在做项目的时候,我们可能需要将自己封装的公共方法在别的项目中使用,一种方式是复制粘贴,但是如果一个项目有添加一些新的方法,两一个项目也想用,那么也需要复制新的方法。

  • 问:那么,有木有什么方法可以让我们将多个项目之前的方法进行共用呢?

  • 答:我们可以使用 npm 的方式进行管理这些工具函数,达到一份维护,多个项目之间共用,如果有新的方法进行发布的时候,只需要更新npm包的版本。

技术选型

  • TypesScript

  • Rollup

依赖

## rollup
npm install rollup -D

## 生成.d.ts
npm install rollup-plugin-dts -D

## 编译ts插件
npm install rollup-plugin-typescript2 -D

## path模块
npm install path -D

## fs模块
npm install path -D

## ts
npm install typescript -G

设计目标

  • 实现命令式一键编译

文件查找工具

  • 因为我们的文件可能有多个,现在约定目录结构如下

    - src
        - index.ts
        - file1.ts
        - demo
            - index.ts
    
  • 文件遵循上述约定,可以进行文件之前的嵌套,在使用文件夹的时候,必须使用index.ts做为结尾

添加编译脚本

  # package.json

  // 生成文件后 进行编译 
  // 如果不使用 bundleConfigAsCjs 则会报错 
  "scripts": {
    "build": "node ./utils/getFile.js &&  rollup -c --bundleConfigAsCjs"
  },

在这里插入图片描述

按照步骤创建

  1. 创建如下的文件结构

    生成如下文件目录结构

    • 编辑内容

      # index.ts
      
      export * from './string.format.ts'
      
      # string.format.ts
      
      /**
      * @jsonParse 将json串解析为JSON对象
      * @param str string 需要解析的JSON串
      * @param initValue T 在解析失败时返回的初始值 默认为 {}
      * @returns
      */
      export const jsonParse = <D, T>(str: string, initValue?: T): T | D | undefined => {
        try {
            return JSON.parse(str);
        } catch {
            return initValue;
        }
      };
      
      
  2. 执行 npm init -y 生成 package.json

  3. 执行 tsconfig --init 生成 tsconfig.ts 文件

  4. 修改 tsconfig.json 内module要为 ESNext

  5. 修改 package.json 内的type要为 module

  6. package.json 添加script脚本

     "scripts": {
    	"build": "node ./utils/getFile.js &&  rollup -c --bundleConfigAsCjs"
     },
    
  7. 创建文件处理工具函数

    ## utils_npm/utils/getFile.js
    import fs from "fs";
    
    const findFile = async (filePath = "src") => {
        try {
            const data = await fs.readdirSync(`./${filePath}`);
            const result = [];
            for (let i = 0; i < data.length; i++) {
            const item = data[i];
            const targetFilePath = `${filePath}/${item}`;
            // 如果式src/index.ts 直接跳过
            if (targetFilePath === "src/index.ts") {
                continue;
            }
            // 如果式以.ts文件为结尾,则认为是文件
            if (item.endsWith(".ts")) {
                result.push(targetFilePath);
            } else {
                // 否则就是文件夹
                const r = await findFile(`${filePath}/${item}`);
                result.push(r);
            }
            }
            return result;
        } catch (err) {
            return [];
        }
    };
    
    const filePath = await findFile();
    let utilsFilePath = filePath.flat(Infinity);
    
    const writeFileData = `const utilsFilePath = ${JSON.stringify(utilsFilePath)};export default utilsFilePath `;
    
    // 写入文件
    fs.writeFile("./utils/file.js", writeFileData, () => {});
    
  8. rollup.config.js 配置

    import path from "path";
    import ts from "rollup-plugin-typescript2";
    import dts from "rollup-plugin-dts";
    import utilsFilePath from "./utils/file";
    
    /** 将文件名称转成大写 */
    const fileNameToLocaleUppercase = (fileName) => fileName.replace(/(\.\w{1})/g, ($1) => $1.slice(1).toLocaleUpperCase());
    
    const config = utilsFilePath
      .map((item) => {
        // 根据获取到的文件,编译成指定文件的文件结构
        const fileName = item.split("/").pop().replace(".ts", "");
        const filePath =
          item
            .split("/")
            .slice(1, item.split("/").length - 1)
            .join("/") + (fileName === "index" ? "" : `/${fileName}`);
        return [
          {
            input: item,
            output: [
              {
                file: path.join(__dirname, `dist/es/${filePath}/index.js`),
                format: "es",
              },
              {
                file: path.join(__dirname, `dist/cjs/${filePath}/index.js`),
                format: "cjs",
              },
              {
                file: path.resolve(__dirname, `./dist/umd/${filePath}/index.js`),
                format: "umd",
                name: fileNameToLocaleUppercase(fileName),
              },
            ],
            plugins: [ts()],
          },
          {
            // 打包声明文件 index.d.ts
            input: item,
            output: {
              file: path.resolve(__dirname, `./dist/es/${filePath}/index.d.ts`),
              format: "es",
            },
            plugins: [dts.default()],
          },
        ];
      })
      // 生成全局的cjs es umd 格式的文件结构
      .concat([
        {
          input: "src/index.ts",
          output: [
            {
              file: "./dist/es/index.es.js",
              format: "es",
            },
            {
              file: "./dist/cjs/index.cjs.js",
              format: "cjs",
            },
            {
              file: path.resolve(__dirname, "./dist/umd/index.umd.js"),
              format: "umd",
              name: "laodingtouUtils",
            },
          ],
          plugins: [ts()],
        },
        {
          //打包声明文件
          input: "./src/index.ts",
          output: {
            file: path.resolve(__dirname, "./dist/es/index.d.ts"),
            format: "es",
          },
          plugins: [dts.default()],
        },
      ])
      .flat();
    
    export default config;
    

发布到npm

  1. 执行 npm run build 打包文件

  2. 将编译后的文件 dist 目录可以单独放到一个文件夹,因为发布后的npm包不需要我们没有压缩的文件,

  3. 将我们开发目录下的 tsconfig.json package.json package.lock.json 也复制到新的文件夹,修改package.json 内的配置

  4. 添加如下配置

      "main": "dist/cjs/index.cjs.js",
      "module": "dist/es/index.es.js",
      "browser": "dist/umd/index.js",
      "types": "dist/es/index.d.ts",
    
  5. 删除package.json 内的type字段。

  6. 将npm包源设置为开源 ,添加如下配置文件

      "publishConfig": {
        "access": "public",
        "registry": "https://registry.npmjs.org/"
      },
    
  7. 添加git配置

      "repository": {
        "type": "git",
        "url": "git+https://github.com/z2244713679/laodingtou.utils/tree/master"
      },
      "homepage": "https://github.com/z2244713679/laodingtou.utils/tree/master",
    
  8. 执行 npm login 登录npm

  9. 在新建的包文件下执行 npm run publish 进行发布

源码

发布包的 package.json

{
  "name": "@laodingtou/utils",
  "version": "0.1.1",
  "description": "laodingtou Utils",
  "main": "dist/cjs/index.cjs.js",
  "module": "dist/es/index.es.js",
  "browser": "dist/umd/index.js",
  "types": "dist/es/index.d.ts",
  "scripts": {
    "build": "node ./utils/getFile.js &&  rollup -c --bundleConfigAsCjs"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/z2244713679/laodingtou.utils/tree/master"
  },
  "homepage": "https://github.com/z2244713679/laodingtou.utils/tree/master",
  "keywords": [],
  "author": "",
  "publishConfig": {
    "access": "public",
    "registry": "https://registry.npmjs.org/"
  },
  "license": "ISC",
  "devDependencies": {
    "fs": "0.0.1-security",
    "path": "^0.12.7",
    "rollup": "^3.28.0",
    "rollup-plugin-dts": "^6.0.0",
    "rollup-plugin-typescript2": "^0.35.0"
  }
}

开发文件的 package.json

{
  "name": "@laodingtou/utils",
  "version": "1.0.0",
  "description": "laodingtou Utils",
  "type": "module",
  "scripts": {
    "build": "node ./utils/getFile.js &&  rollup -c --bundleConfigAsCjs"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "fs": "0.0.1-security",
    "path": "^0.12.7",
    "rollup": "^3.28.0",
    "rollup-plugin-dts": "^6.0.0",
    "rollup-plugin-typescript2": "^0.35.0"
  }
}

rollup.config.js

import path from "path";
import ts from "rollup-plugin-typescript2";
import dts from "rollup-plugin-dts";
import utilsFilePath from "./utils/file";

/** 将文件名称转成大写 */
const fileNameToLocaleUppercase = (fileName) => fileName.replace(/(\.\w{1})/g, ($1) => $1.slice(1).toLocaleUpperCase());

const config = utilsFilePath
  .map((item) => {
    // 根据获取到的文件,编译成指定文件的文件结构
    const fileName = item.split("/").pop().replace(".ts", "");
    const filePath =
      item
        .split("/")
        .slice(1, item.split("/").length - 1)
        .join("/") + (fileName === "index" ? "" : `/${fileName}`);
    return [
      {
        input: item,
        output: [
          {
            file: path.join(__dirname, `dist/es/${filePath}/index.js`),
            format: "es",
          },
          {
            file: path.join(__dirname, `dist/cjs/${filePath}/index.js`),
            format: "cjs",
          },
          {
            file: path.resolve(__dirname, `./dist/umd/${filePath}/index.js`),
            format: "umd",
            name: fileNameToLocaleUppercase(fileName),
          },
        ],
        plugins: [ts()],
      },
      {
        // 打包声明文件 index.d.ts
        input: item,
        output: {
          file: path.resolve(__dirname, `./dist/es/${filePath}/index.d.ts`),
          format: "es",
        },
        plugins: [dts.default()],
      },
    ];
  })
  // 生成全局的cjs es umd 格式的文件结构
  .concat([
    {
      input: "src/index.ts",
      output: [
        {
          file: "./dist/es/index.es.js",
          format: "es",
        },
        {
          file: "./dist/cjs/index.cjs.js",
          format: "cjs",
        },
        {
          file: path.resolve(__dirname, "./dist/umd/index.umd.js"),
          format: "umd",
          name: "laodingtouUtils",
        },
      ],
      plugins: [ts()],
    },
    {
      //打包声明文件
      input: "./src/index.ts",
      output: {
        file: path.resolve(__dirname, "./dist/es/index.d.ts"),
        format: "es",
      },
      plugins: [dts.default()],
    },
  ])
  .flat();

export default config;

tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "ESNext",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值