背景
前段时间写过一篇 一文拿下Web端基于AudioWorkletNode录制音频 , 然后现在毕设什么的都搞定了比较闲, 就来琢磨怎么将其发包(主要是想重操一下发包流程),此篇整理详细记录实现过程, 以防自己以后多走弯路
搞定npm
要发布一个npm包首先你要有对应的npm账号, 这里就不赘述了
在操作之前, 先通过npm get registry
确认是否为官方源
- 若显示为:
https://registry.npmjs.org/
则为官方源 - 若显示为:
https://registry.npmmirror.com
或者https://registry.npm.taobao.org
(过期了的)则为淘宝源, 此时如果你登录的话其实是登录cnpm, 故需要可通过npm config set registry https://registry.npmjs.org
进行切换
接着呢, 在命令行输入npm login
或者npm adduser
进行登录,显示如下或者让你输入账密登录,跟着流程走就好 想确认是否登录成功可以通过
npm whoami
, 如已经登录了的话则会显示你的账号名称
关键步骤
建包
新建一个文件夹并使用npm init
,会让你输入一些关键属性接着生成package.json
,以下为发包可能涉及到的一些属性
name
: 该包的名称description
: 该包的简述main
: 该包的入口文件scripts
: 定义一组可以运行的node
脚本author
:作者名contributors
: 贡献者keywords
: 一组关键词, 影响搜索repository
: 指定仓库链接private
: 如果设置为true
,则可以防止应用程序/软件包被意外地发布到npm
。 故这里要么不指定要么设置为false
files
: 可以通过files
指定需要跟随一起发布的内容来控制npm
包的大小,避免安装时间太长
当然这里如果想更详细地了解package.json的属性, 指路: package.json 配置完全解读 - 掘金 (juejin.cn)
发布
当业务内容都搞完了就可以发布了, 在发布之前需要先检查一下包名称是否有问题, npm
是不允许有同名的包, 当你发包时,若已有同名的包那么就会失败
可以先通过npm search
搜索是否已有同名包, 若有符合的包名称则会显示相关信息, 匹配上的包名称还会标红。 如果此时发现有同名的包, 那么就修改package.json
中的name
以修改包名称。注意包名称不能出现下划线、大写字母、空格等字符,可以有连字符和中划线。

发布的话则使用npm publish
就OK了。 在发包的时候会显示该包内包含了什么文件,以及相关的包的信息。 一般来说除了package.json
中通过files
指定的目录之外, 还会带上整体的README
文件和package.json
文件
当然发包偶尔就会失败(超时).... 多试几次就好了

更新
当包内容有更新时, 直接使用npm publish
是会失败的,因为此时的版本号与现有的版本号重复了。
故需要先更新版本号, 有两个方法可以修改版本号:
- 直接修改
package.json
的version
属性 - 通过命令行
npm version [option]
更新版本号, 主要option
如下major
: 主版本号 -- 大更新 1.0.0 -> 2.0.0minor
: 次版本号 -- 小更新 1.0.0 -> 1.1.0patch
: 补丁版本号 -- 打补丁 1.0.0 -> 1.0.1premajor
: 预备主版本preminor
: 预备次版本prepatch
: 预备补丁版本
当然还有包的撤销和弃用, 这按需搜索就好了
结合内容
这个包的内容很简单, 基本源代码就是之前文章内写的。记录也不是为了记录源码内容, 而是其他步骤。
src
目录下即为核心代码, index.ts
文件作为入口文件。
.d.ts声明文件
发布一个包最好要生成对应的 .d.ts
文件,提供代码补全和接口提示的功能, 没提供的话一般IDE会有报错提醒。
在该项目中我们是通过@babel/preset-typescript
去处理TS文件的, 但是@babel/preset-typescript
在处理typescript
的时候是没有提供生成声明文件这个功能的, 故可以通过tsc --emitDeclarationOnly
去生成声明文件。
或者使用ts-loader
去处理, 这个就直接提供声明文件
搞定声明文件后, 需要在package.json
的types
字段去指定声明文件: "types": "dist/main.d.ts",
webpack配置
源码使用webpack
作为打包工具,内部主要提供三条命令, 根据不同的命令使用不同的webpack
配置文件
demo
: 构建生成demo
, 可以通过HTML
文件直接体验效果dev
:开发中用于调试功能, 使用webpack-dev-server
build
: 构建生成发包产物
使用webpack
需要先进行安装npm install --save-dev webpack webpack-cli
对于build
构建而言, 命令行为: webpack --mode=production
, 默认的配置文件为webpack.config.js
js
const { join } = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
entry: join(__dirname, './src/index.ts'), // 打包入口
output: {
filename: '[name].js', // 产物名称
// 产物目录
// 这里都收归到dist目录下, 最后发包的package.json指定files为dist即可
path: join(__dirname, './dist'),
// 每次构建齐纳都先清空dist目录
clean: true,
publicPath: '/',
// 暴露从入口导出的内容, 如果你构建之后发现产物基本没东西那么就是忘记配置这个了
library: {
name: '"webAudioRecorder', // 构建产物的名称, 这里需要与入口数量匹配
type: 'umd' // 构建产物支持的方式,
},
},
resolve: {
// webpackh会尝试按顺序解析这些后缀名, 列入使用到的文件后缀即可
extensions: ['.ts','.js']
},
plugins: [
// 业务内容中涉及到process.js文件是通过addModule的方法
// 放在Web Audio rending thread中运行
// 在构建中webpack是识别不到他的, 故需要将它复制到产物中, 这里使用CopyPlugin
//类型文件同理
new CopyPlugin({
patterns: [{
from: './src/recorder/processor.js',
to: './processor.js'
}, {
from: './index.d.ts',
to: './main.d.ts',
}]
})
],
optimization: {
minimize: false // 是否压缩,这里看个人需求就好了
},
// 这里就使用babel处理, 没啥了
module: {
rules: [
{
test: /.(ts)$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-typescript'
]
}
},
}
],
},
}
output.library.type
支持的类型指步:output.library.type
对于dev
和demo
而言, 录音功能其实通过一些按钮调用就好了, 故先在example
目录下生成对应的HTML
的模板以及对应的调用文件。 如果是开发中, 调用文件则使用src
目录下的代码。 如果是生成demo
的话, 则调用dist
目录下的构建产物(如果发版了也可以使用包产物)。
dev
的命令行则使用webpack-dev-server
去启动dev": "webpack-dev-server --mode=development --config webpack.dev.js"
demo
的命令行则使用webpack
去启动"demo": "webpack --mode=production -c webpack.dev.js"
。
两者的配置文件都为webpack.dev.js
js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
// 入口
entry: path.join(__dirname, './example/index.js'), // 调用文件作为入口
devtool: 'source-map',
devServer: {
port: 3000, // 服务端口号
hot: true, // 开启热更新
host: 'localhost', // 在本项目中,相关API需要在安全上下文调用, 故需要指定host
historyApiFallback: true, // 解决history路由404问题
},
output: {
filename: 'index.js',
clean: true,
path: path.join(__dirname, './demo') // 构建产物放在demo
},
module: { ... }, // 省略
resolve: { ... }, // 省略
plugins: [
// 使用模板HTML , 生成产物
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './example/index.html'),
filename: 'index.html',
inject: true
}),
// 将静态资源copy过去
new CopyPlugin({
patterns: [{
from: './src/recorder/processor.js',
to: './processor.js'
}]
})
]
};
当然如何要应用在其他项目中进行测试, 还可以用npm link
相关功能。 比如在开发业务专属eslint
规则包的时候, 直接npm link
过去业务项目中测试会高效很多