文章介绍如何创建发布一个 npm 包,包括项目搭建、发布流程、注意事项等。演示代码 GitHub 地址
1. 初始化项目
首先在创建好的项目文件夹下面执行
npm init
根据对应提示完成 package.json 文件初始化。
package name 为你创建的 npm 包的名称,在发布后被安装使用即该名字,npm 规定包名首字母需要为小写。如 import App from ‘your-module’;
version 即为包版本,每次发布前都需要更新包版本,否则会失败,包版本应该遵守语义化规范。语义化版本号分为三位 0.0.0。主版本号:当进行了大都改动或者对 api 有很多不兼容修改时应该进行版本号升级。次版本号:增加了部分特性或者优化时升级该版本。修订号:当修改了项目 bug 或者小的改动时升级该版本。
entry point 项目的入口路径,当用户使用包的时候,会根据该入口也就是 package.json 的 main 中的路径来进行索引
git repository 关联的 git 仓库
keywords 会在 npm 中展示你的项目关键字
2. 项目构建
开发环境 webpack.config.js 配置
const path = require(‘path’);
const webpack = require(‘webpack’);
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
module.exports = {
mode: ‘development’,
entry: path.resolve(__dirname, ‘app.js’),
output: {
path: path.join(__dirname, ‘dist’),
filename: “main.js”,
},
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
exclude: /node_modules/,
loader: ‘babel-loader’
},
{test: /\.css$/, loader: ‘style-loader!css-loader’},
{
test: /\.(png|jpg|gif|svg)$/, // 对图片文件,使用 url-loader 里的加载器处理
loader: ‘url-loader’,
options: {
limit: 8192, // 限制图片文件字节,大于 8KB 则不生成 base64 用路径引用替代(相当于 file-loader)
name: ‘[name].[ext]?[hash]’ // 文件名
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
hash: true,
template: ‘./index.html’,
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件
],
devtool: ‘inline-source-map’, // map 文件追踪错误提示
devServer: {// 启动本地开发的 node 服务器环境(webpack-dev-server)
port: 8080, // 端口
contentBase: ‘./dist’, // 开发环境的服务目录
historyApiFallback: true,
host: ‘0.0.0.0’,
inline: true,
hot: true,
},
};
在开发环境中就是一些很常见的配置,保证我们可以进行本地的组件模块开发即可。
打包模块 webpack.prd.js 配置
const path = require(‘path’);
const webpack = require(‘webpack’);
const BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer’).BundleAnalyzerPlugin;
const NODE_ENV = process.env.NODE_ENV;
const prdWebpackConfig= {
mode: ‘production’,
entry: path.resolve(__dirname, ‘src/index.js’),
output: {
path: path.join(__dirname, ‘lib’),
filename: “chat-react.js”,
libraryTarget: ‘commonjs2’ // 模块输出方式
},
externals: {
react: ‘react’ // 打包时候排除 react
},
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
exclude: /node_modules/,
loader: ‘babel-loader’
},
{test: /\.css$/, loader: ‘style-loader!css-loader’},
{
test: /\.(png|jpg|gif|svg)$/,
loader: ‘url-loader’,
options: {
limit: 8192,
name: ‘[name].[ext]?[hash]’
}
}
]
},
plugins: []
};
if (NODE_ENV !== ‘publish’) {
prdWebpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = prdWebpackConfig;
打包模块与我们写应用逻辑代码有些不同,由于大部分用户使用模块都不会去再对模块进行 es5 转换,所有我们发布的模块也应该是已经被转换之后的代码,而且需要提供模块的引用入口以及排除模块自己以外的代码。
entry 在完成模块打包时,修改了项目的入口路径 entry。配置打包的 entry 路径为该发布模块的文件,而不是开发环境中的项目入口。
output path 为生成的目录位置以及目录名,filename 为打包后的模块文件。libraryTarget 为生成模块的引入方式,因为我们写的 react 组件基本为模块化打包开发方式,选择使用 commonjs2 配置,最后打包会生成符合 commonjs 规范的模块,具体配置规则可见 output.libraryTarget
externals 因为我们是基于 react 的组件,但是在完成打包的时候如果将 react 也打包进去,库的体积就会变大,而且 react 库通常会在使用组件的时候被外部引入,所以我们要排除 react。externals 配置
BundleAnalyzerPlugin 在非发布命令下打包时候,我们可以用该插件审查一下打包完成的包体积大小。所以只需判断下在 npm scripts 中设置的 NODE_ENV 环境变量,按需使用该插件即可。
mode 在 webpack4 中设置 mode 为 production,会自己启用生产环境的部分配置优化,此时 UglifyJsPlugin 压缩插件也会启用,帮助完成我们的 library 的代码压缩。
3. 发布前配置
1. 发布前需要正确配置 package.json 中的 main 内容,使用时会根据该内容自动索引模块内容
“main”: “lib/chat-react.js”
2. 在发布前我们需要完成打包,为了确保我们发布的版本为编译完成后的版本,可以利用 npm scripts 中的 prepublishOnly 钩子。这个钩子可以保证我们在执行 npm publish 的前进行打包操作。
“scripts”: {
“prepublishOnly”: “NODE_ENV=’publish’ npm run build”
}
prepublish 钩子也会在执行 npm publish 前触发该周期,我使用的是 npm v5.5 版本,在使用 npm install 的时候 prepublish 周期也会被触发,翻到了一篇阮老师的文章,其中提到 npm5 版本时候会改掉这一状态,prepublish 将只在 npm publish 命令之前运行,不过看起来跟预期不一致。在 15 年的 npm 官方讨论 issue 里说将来可能会废弃 prepublish 或者 prepublishOnly 某一个,不过翻看了官方 npm script 文档对两个钩子的用法都有说明,看起来是都保留了。
3. 配置.npmignore,.npmignore 的用法与.gitignore 一致。因为我们在执行 npm publish 发布命令时会将项目下掉所有文件都发布至 npm,.npmignore 可以忽略掉我们不需要发布都文件
node_modules
example
src
.babelrc
app.js
index.html
package-lock.json
webpack.config.js
webpack.prd.js
4. 编写使用文档 (readme)。为我们的模块组件编写使用文档是必不可少的,README.md 使用的是 markdown 语法,记不住语法的小伙伴也可以使用我的在线 markdown 编辑器。
4. 完成发布
发布流程
首先注册你的 npm 帐号
命令行执行 npm login 登录你的 npm 账号
进入你项目目录下 npm publish 即可完成发布
回撤版本
如果你意外的发布错了包,使用 npm unpublish + 包名即可删除该包。如:
npm unpublish chat-react
如果你想撤回指定版本,执行 npm unpublish + 包名 @版本号。如:
npm unpublish chat-react@1.0.0
Tips:npm 为了保证包不会影响到使用者,发布的版本只能在 24 小时内进行撤回。
文章代码演示 GitHub 地址