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

发布一下 0 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 的项目名字段)  网络原因     镜像源问题   新注册的用户邮箱未激活。  登陆你的邮箱去激活(如下)     复制代码
https://blog.sina.com.cn/s/blog_95b83d1401030ldz.html

image.png

2、 如果出现

https://blog.sina.com.cn/s/blog_95b83d1401030ldz.html

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



版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/82516.html