Write your own NPM package and publish it to NPM
When it comes to NPM packages, they will give people a particularly lofty feeling, and after writing a package, if someone uses it, they will have a great sense of achievement. The joy of programmers is so simple.
Anyone who came up with the idea of writing an NPM package is probably familiar with modularity and is familiar with either React or Vue.
Webpack5 + React + ESLint +tslint we use webpack scaffolding to write our own NPM package with React. The following content is also based on this.
Scaffolding is also available
1. Differences
The directory structure of the NPM package is different from the normal scaffolding structure
-
The startup directory is different: we used to write the entry file in SRC, but the NPM package entry file cannot be in SRC because NPM packages our source code and cannot include HTML.
So extract the index.jsx and index.html files into the example file. The example file should be the same as SRC.
The structure and contents are as follows
index.jsx
import React from 'react'; import { render } from 'react-dom'; import ReactDemo from '.. /src'; const App = () => <ReactDemo />; render(<App />, document.getElementById('root'));Copy the code
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 >Copy the code
Then export it in the SRC /index.jsx file
import App1 from './App'; export default App1; Copy the code
Configure the NPM package run file
Create a new webpack.npm.js file in the config folder
The configuration files are similar. For details, go to webPack5 + React + ESlint +tslint
Externals: This will tell NPM not to pack the following items.
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,,}},}, the 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'], // Cache: The previous cache will be read for the second build 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]', }, }, }, ], }, };Copy the code
Let’s focus on what’s in package.json
-
Name: the package name, which is used for subsequent searches in NPM
-
Version: Version number. Each release of the NPM package requires an additional version. Each version cannot be repeated.
-
Description: describe
-
Main: The file exposed in this package, it is important to make sure that the file name is exactly the same as the file you packaged. Mine is called “dist/index.js”.
-
Private: true/false Indicates whether it is private. Generally false otherwise only you can use it
-
Flies: exposed folders, what folders are submitted to NPM in the format [“dist”]
-
Keywords: keyword for NPM search
-
Author: the author
-
license: ISC
-
PeerDependencies: indicates that the current NPM package depends on the following environments.
Complete configuration
{" 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": "[email protected]", "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 - the 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 -", "reality", "^ 19.0.4", "eslint - plugin - import" : "^ 2.25.4", "eslint - plugin - JSX - a11y" : "^ 6.5.1 eslint", "- the 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.4.1," "less - loader" : "^ 10.0.1", "lodash" : "^ 4.17.21", "mini - CSS - extract - the 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 -", "plugins" : "^ 5.1.4 ensuring", "thread - loader" : "^ 3.0.4", "ts - loader" : "^ 9.2.5", "tslint" : "^ also 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", "the react - dom" : "17.0.2", "the react - the 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", "the react - dom" : "17.0.2", "the react - the 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"]}}Copy the code
Three, publish,
If the package is released for the first time, run the following command and enter the NPM account, password, and email address that you have registered
npm adduser Copy the code
If the package is not released for the first time, run the following command to log in, also enter the NPM account, password, and email address
npm login Copy the code
Note: when NPM adduser succeeds, you are already logged in by default, so there is no need for NPM login
Then go to the project folder first and enter the following command to publish
npm publish Copy the code
When the terminal displays the following message, the package version 1.0.0(in your package.json) has been published successfully. Go to the NPM website to find your bag
+ Your filename @0.1.0Copy the code
Four, an error
1, if appear
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. Copy the code
There are several reasons for this
Incorrect account password (please check the account password on the official website of NPM) package name (please check whether there is a project with the same name on the official website of NPM, the name depends on the project name field of package.js) Network cause Mirror source problem The mailbox of the newly registered user is not activated. Login your email to activate (below)Copy the code
2, if appear
Change private to false or remove it from your package.json
Update published packages
Updating a package is the same as publishing a package
npm publish
Copy the code
However, the version number must be changed every time it is updated. For example, 1.0.0 must be changed to 1.0.1 before it is released.
The package versioning rules are the same here, using semver (semantic versioning), which means version number: big change. Medium change. Minor change
## Uninstall your distributed packages from NPM
Enter the directory of your project to execute. NPM unpublish –force
NPM WARN using --force Recommended Protections Disabled. - Package name @0.1.0Copy the code
The uninstallation is successful, then the search can not be found on NPM