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

本文将介绍通过 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 初始如下:

{
  "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/es'),
      format: 'es'
    }
  ]
}

2.1编写脚本如下:

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

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

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

也就是我们的npm包可以支持哪种方式进行使用?常见的是输出以下三种格式:
es – 支持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.构建编译成 es 格式
2.1在根目录,创建 rollup.es.config.js

import babel from '@rollup/plugin-babel'
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/es'),
      format: 'es'
    }
  ],
  plugins: [
    esbuild({
      target: 'es2018'
    }),
    nodeResolve(),
    json(),
    babel({
      extensions: [".js", ".ts"], // 需要处理的文件后缀
      presets: ['@babel/preset-env'],
      exclude: 'node_modules/**',
      babelHelpers: 'bundled'
    }),
  ],

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

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

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

{
  "compilerOptions": {
  	"target": "es5",
    "module": "es6", // 指定生成代码的模板标准
    "declaration": true,
    "outDir": "dist",
    "lib": ["es2015", "dom"],
    "removeComments": true, // 删除注释
    "preserveConstEnums": true, // 保留 const 和 enum 声明
    "sourceMap": true // 生成目标文件的sourceMap文件
    
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

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

npm run build:es

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

import path from 'path'
const resolve = () => path.resolve(__dirname, dir)
import typescript from 'rollup-plugin-typescript2';
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: [
    typescript(),
    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({
      extensions: [".js", ".ts"],
      presets: ['@babel/preset-env'],
      exclude: 'node_modules/**',
      babelHelpers: 'bundled'
    }),
    nodeResolve(),
    json(),
    commonjs(),
    ...envPlugins
  ]
}

新增变化内容如下图红色框处:
从零到1构建可发布的npm包_第1张图片

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:es": "cross-env NODE_ENV=production rollup -c rollup.es.config.js",
  },

4.1.3 在根目录创建 examples/base/index.html
从零到1构建可发布的npm包_第2张图片

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:es": "run-p watch:es serve:vue",
    "watch:esm": "cross-env NODE_ENV=development rollup -w -c rollup.es.config.js",
    "serve:vue": "cd ./examples/vuetest && yarn && yarn serve",
  },

4.2.4 在vue项目中调试,在引入时,其路径无需指定到具体文件,会自动找pkg.main、pkg.module进行匹配
从零到1构建可发布的npm包_第3张图片

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

module.exports = {
    lintOnSave: false
}

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

从零到1构建可发布的npm包_第4张图片

五、发布到NPM上

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

npm login

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

npm version patch

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

npm publish

如果现在的版本号跟已经发布的重复,则会报错,需要重新执行 【5.2】和【5.3】的步骤,见下图:
从零到1构建可发布的npm包_第5张图片

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

{
  "name": "wujs",
  "version": "1.1.4",
  "description": "",
  "main": "dist/umd/index.js",
  "module": "dist/es/index.js",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "run-p \"build:*\"",
    "dev:es": "run-p watch:es serve:vue",
    "watch:es": "cross-env NODE_ENV=development rollup -w -c rollup.es.config.js",
    "serve:vue": "cd ./examples/app08 && yarn && yarn serve",
    "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:es": "cross-env NODE_ENV=production rollup -c rollup.es.config.js",
    "postbuild:es": "tsc --emitDeclarationOnly --declaration --project tsconfig.json --outDir dist/es"
  },
  "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-run-all": "^4.1.5",
    "rollup": "^2.78.0",
    "rollup-plugin-esbuild": "^4.9.3",
    "rollup-plugin-livereload": "^2.0.5",
    "rollup-plugin-serve": "^2.0.1",
    "rollup-plugin-typescript2": "^0.34.1",
    "typescript": "^4.7.4"
  }
}

你可能感兴趣的:(js库,npm,npm,javascript,前端)