百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

教你写第一个NPM包惊艳其他人

ztj100 2024-11-17 18:14 18 浏览 0 评论

自己书写一个npm包并发布到npm上面

说到npm包都会给人一种特别高大上的感觉,并且自己写了一个包之后如果有人用那么就会产生莫大的成就感,程序员的快乐就是这么简单。

想必有产生写npm包想法的人都对模块化比较熟悉,并且对于react、vue两者之一都比较熟练了。

下面呢我们就是使用react来写一个自己的npm包,我们呢会使用自己封装的webpack脚手架来写,如果有兴趣同学可以来看一下我的自我沉淀webpack5+react+eslint+tslint[1]文章。接下来的内容呢也是基于此来说明的。

这里也有现成的脚手架[2]

一、不同点

npm包的目录结构和普通的脚手架结构有所不同

  1. 启动目录不同:以往我们习惯将entry文件写在src中,但是npm包的入口文件不能写在src中,因为npm是将我们的源代码打包,不可以包括html。所以将index.jsx和index.html文件提取到example文件中。【注意】example文件要和src同级。结构和内容如下index.jsx
 import React from 'react';
 import { render } from 'react-dom';
 import ReactDemo from '../src';

 const App = () => <ReactDemo />;
 render(<App />, document.getElementById('root'));
 
    复制代码
index.html
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Document</title>
   </head>
   <body>
     <div id="root"></div>
   </body>
 </html>
    复制代码
然后在src/index.jsx文件中 导出
 import App1 from './App';
 export default App1;
    复制代码
## 二 配置npm包的打包运行文件

在 config文件夹中新建webpack.npm.js文件

配置文件内容差不多。如下:详细配置请移步 [自我沉淀webpack5+react+eslint+tslint](https://juejin.cn/post/7002157698108096543 "https://juejin.cn/post/7002157698108096543")

externals划重点:这个可以告诉npm打包的时候不许将下面几种东西打包进去哦。
 const { resolve } = require('path');
 const cssLoaders = [
   'style-loader',
   {
     loader: 'css-loader',
     options: {
       importLoaders: 1,
       modules: {
         auto: (resourcePath) => resourcePath.endsWith('.less'),
         localIdentName: '[local]_[hash:base64:10]',
       },
     },
   },
   {
     loader: 'postcss-loader',
     options: {
       postcssOptions: {
         plugins: [['autoprefixer'], require('postcss-preset-env')()],
       },
     },
   },
 ];
 module.exports = {
   entry: './src/index.tsx',
   mode: process.env.NODE_ENV,
   externals: {
     antd: 'antd',
     react: 'React',
   },
   output: {
     libraryTarget: 'umd',
     filename: 'index.js',
     path: resolve(resolve(__dirname, '..'), 'dist'),
     clean: true,
   },
   resolve: {
     alias: {
       '@': resolve(resolve(__dirname, '..'), 'src/'),
     },
     extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
     mainFiles: ['index'],
   },

   devServer: {
     hot: true,
     port: 3002,
     host: '127.0.0.1',
     compress: true,
     open: true,
     proxy: {
       '/api': {
         target: 'http://127.0.0.1:3002',
         pathRewrite: { '^/api': '' },
         secure: false,
       },
     },
   },

   module: {
     rules: [
       {
         test: /\.(js|jsx)$/,
         include: resolve(resolve(__dirname, '..'), ''),
         exclude: /node_modules/,
         enforce: 'pre',
         use: [
           {
             loader: 'babel-loader',
             options: {
               presets: ['@babel/preset-env', '@babel/preset-react'],
               // 缓存:第二次构建时,会读取之前的缓存
               cacheDirectory: true,
             },
           },
         ],
       },
       {
         test: /\.tsx$/,
         loader: 'ts-loader',
         exclude: /node_modules/,
       },
       {
         test: /\.css$/,
         use: [...cssLoaders],
       },
       {
         test: /\.less$/,
         use: [...cssLoaders, 'less-loader'],
       },
       {
         test: /\.s[ac]ss$/,
         use: [...cssLoaders, 'sass-loader'],
       },
       {
         exclude: /.(html|less|css|sass|js|jsx|ts|tsx)$/,
         test: /\.(jpg|jpe|png|gif)$/,
         loader: 'file-loader',
         options: {
           name: 'imgs/[name].[ext]',
           outputPath: 'other',
         },
       },
       {
         test: /\.(ect|ttf|svg|woff)$/,
         use: {
           loader: 'file-loader',
           options: {
             name: 'icon/[name].[ext]',
           },
         },
       },
     ],
   },
 };
 
 
 
    复制代码

下面着重说一下package.json中的内容

  • name: 包名,后续在npm中搜索全靠它
  • version:版本号,每发布一次npm包就要增加一个版本,每个版本不能重复。
  • description:描述
  • main: 本包向外暴露的文件,很重要,一定要和你打包出来的文件名一模一样,我的叫做"dist/index.js"
  • private: true/false 是否为私有。一般为false否则只有自己能使用
  • flies: 暴露的文件夹, 有哪些文件夹提交到npm上面 格式为[ "dist" ]
  • keywords: npm检索的关键字
  • author: 作者
  • license: ISC
  • peerDependencies: 代表着当前npm包依赖下面这几种环境。
  • 完整配置
   {
    "name": "new_webpack_action2",
    "version": "1.0.24",
    "m": "",
    "main": "dist/index.js",
    "private": false,
    "flies": [
      "dist"
    ],
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "dev": "export NODE_ENV=development && npx webpack serve --config config/webpack.dev.js",
      "build": "export NODE_ENV=production && npx webpack   --config config/webpack.prod.js",
      "npm": "export NODE_ENV=production && npx webpack   --config config/webpack.npm.js"
    },
    "keywords": [
      "react",
      "javascript",
      "npm"
    ],
    "author": "919022572@qq.com",
    "license": "ISC",
    "devDependencies": {
      "@ant-design/icons": "4.7.0",
      "@babel/core": "^7.15.0",
      "@babel/preset-env": "^7.15.0",
      "@babel/preset-react": "^7.14.5",
      "@types/lodash": "^4.14.178",
      "@types/react": "^17.0.19",
      "@types/react-dom": "^17.0.11",
      "@types/react-router-dom": "^5.3.3",
      "@typescript-eslint/eslint-plugin": "^5.11.0",
      "@typescript-eslint/parser": "^5.11.0",
      "autoprefixer": "^10.3.2",
      "babel-loader": "^8.2.2",
      "babel-plugin-import": "^1.13.3",
      "css-loader": "^6.2.0",
      "css-minimizer-webpack-plugin": "^3.0.2",
      "eslint": "^8.8.0",
      "eslint-config-airbnb": "^19.0.4",
      "eslint-plugin-import": "^2.25.4",
      "eslint-plugin-jsx-a11y": "^6.5.1",
      "eslint-plugin-react": "^7.28.0",
      "eslint-plugin-react-hooks": "^4.3.0",
      "eslint-webpack-plugin": "^3.1.1",
      "file-loader": "^6.2.0",
      "html-webpack-externals-plugin": "^3.8.0",
      "html-webpack-plugin": "^5.5.0",
      "less": "^4.1.1",
      "less-loader": "^10.0.1",
      "lodash": "^4.17.21",
      "mini-css-extract-plugin": "^2.2.0",
      "postcss-loader": "^6.1.1",
      "postcss-preset-env": "^7.4.2",
      "sass": "^1.38.0",
      "sass-loader": "^12.1.0",
      "speed-measure-webpack-plugin": "^1.5.0",
      "style-loader": "^3.2.1",
      "stylelint": "^13.13.1",
      "stylelint-config-standard": "^22.0.0",
      "terser-webpack-plugin": "^5.1.4",
      "thread-loader": "^3.0.4",
      "ts-loader": "^9.2.5",
      "tslint": "^6.1.3",
      "typescript": "^4.5.5",
      "webpack": "^5.68.0",
      "webpack-cli": "^4.8.0",
      "webpack-dev-server": "^4.0.0",
      "webpack-merge": "^5.8.0",
      "workbox-webpack-plugin": "^6.4.2"
    },
    "dependencies": {
      "antd": "4.18.8",
      "axios": "^0.26.0",
      "react": "17.0.2",
      "react-dom": "17.0.2",
      "react-router-dom": "5.2.0"
    },
    "peerDependencies": {
      "@ant-design/icons": "4.7.0",
      "antd": "4.18.8",
      "bizcharts": "4.1.15",
      "rc-footer": "0.6.6",
      "react": "17.0.2",
      "react-dom": "17.0.2",
      "react-router-dom": "5.2.0"
    },
    "browserslist": {
      "development": [
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
      ],
      "production": [
        ">0.2%",
        "not dead",
        "not op_mini all"
      ]
    }
  }
  
  
  复制代码

三、发布

如果是第一次发布包,执行以下命令,然后输入前面注册好的NPM账号,密码和邮箱,将提示创建成功

  npm adduser
  
  复制代码

如果不是第一次发布包,执行以下命令进行登录,同样输入NPM账号,密码和邮箱

  npm login
  
  复制代码

注意:npm adduser成功的时候默认你已经登陆了,所以不需要再进行npm login了

接着先进入项目文件夹下,然后输入以下命令进行发布

  npm publish
  
  复制代码

当终端显示如下面的信息时,就代表版本号为1.0.0(你的package.json中的版本号)的包发布成功啦!前往NPM官网就可以查到你的包

 + 你的文件名@0.1.0
 
  复制代码

四、报错

1、如果出现

  npm ERR! code E403
  npm ERR! 403 403 Forbidden - PUT https://registry.npmjs.org/ghost-watermarkdemo - Forbidden
  npm ERR! 403 In most cases, you or one of your dependencies are requesting
  npm ERR! 403 a package version that is forbidden by your security policy, or
  npm ERR! 403 on a server you do not have access to.
  复制代码

以下几种原因会导致

  账号密码错误   (请检查npm官网的账号密码)
  包重名     (请检查npm官网上是否有同名项目,名字取决于 package.js 的项目名字段)
  网络原因   
  镜像源问题 
  新注册的用户邮箱未激活。  登陆你的邮箱去激活(如下)

   
  复制代码

image.png

2、 如果出现

image.png

需要在你的package.json中 private改为false或者删除

更新已经发布的包

更新包的操作和发布包的操作是一样的

   npm publish
   
复制代码

但是每次更新时,必须修改版本号后才能更新,比如将1.0.0修改为1.0.1后才能更新发布。

这里的包版本管理规则都是一样的,采用的是semver(语义化版本),意思就是版本号:大改.中改.小改

五、## 从npm上面卸载自己发布的包

进入自己项目的目录执行。npm unpublish --force 出现:

   npm WARN using --force Recommended protections disabled.
-包名@0.1.0
复制代码

则卸载成功,这时在npm上面就搜索不到了

关于本文

来自:夏末海棠

https://juejin.cn/post/7072652104837365774



相关推荐

从IDEA开始,迈进GO语言之门(idea got)

前言笔者在学习GO语言编程的时候,GO语言在国内还没有像JAVA/Php/Python那样普及,绕了不少的弯路,要开始入门学习一门编程语言,最好就先从选择一个好的编程语言的开发环境开始,有了这个开发环...

基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于SpringBoot...

基于springboot的个人服装管理系统java网上商城jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...

基于springboot的美食网站Java食品销售jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...

贸易管理进销存springboot云管货管账分析java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目描述贸易管理进销存spring...

SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍SpringBoot+V...

目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗

帮粉丝找了一个基于SpringBoot的天猫商城项目,快速部署运行,所用技术:MySQL,Druid,Log4j2,Maven,Echarts,Bootstrap...免费给大家分享出来前台演示...

SpringBoot+Mysql实现的手机商城附带源码演示导入视频

今天为大家带来的是基于SpringBoot+JPA+Thymeleaf框架的手机商城管理系统,商城系统分为前台和后台、前台用的是Bootstrap框架后台用的是SpringBoot+JPA都是现在主...

全网首发!马士兵内部共享—1658页《Java面试突击核心讲》

又是一年一度的“金九银十”秋招大热门,为助力广大程序员朋友“面试造火箭”,小编今天给大家分享的便是这份马士兵内部的面试神技——1658页《Java面试突击核心讲》!...

SpringBoot数据库操作的应用(springboot与数据库交互)

1.JDBC+HikariDataSource...

SpringBoot 整合 Flink 实时同步 MySQL

1、需求在Flink发布SpringBoot打包的jar包能够实时同步MySQL表,做到原表进行新增、修改、删除的时候目标表都能对应同步。...

SpringBoot + Mybatis + Shiro + mysql + redis智能平台源码分享

后端技术栈基于SpringBoot+Mybatis+Shiro+mysql+redis构建的智慧云智能教育平台基于数据驱动视图的理念封装element-ui,即使没有vue的使...

Springboot+Mysql舞蹈课程在线预约系统源码附带视频运行教程

今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的Springboot+Mysql舞蹈课程在线预约系统,系统项目源代码在【猿来入此】获取!https://www.yuan...

SpringBoot+Mysql在线众筹系统源码+讲解视频+开发文档(参考论文

今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的在线众筹管理系统,主要实现了普通用户在线参与众筹基本操作流程的全部功能,系统分普通用户、超级管理员等角色,除基础脚手架外...

Docker一键部署 SpringBoot 应用的方法,贼快贼好用

这两天发现个Gradle插件,支持一键打包、推送Docker镜像。今天我们来讲讲这个插件,希望对大家有所帮助!GradleDockerPlugin简介...

取消回复欢迎 发表评论: