基本介绍
npm是Node.js的包管理工具,它的诞生也极大的促进了前端的发展,在现代前端开发中都离不开npm的身影,在工程化的前端项目中,npm的作用越来越大,对前端发展有着极大的推进,npm让您的 JavaScript 开发更上一层楼。npm官网提供了大概250万个包供开源使用,都可在项目中进行使用。
常见包的结构
模块化规范
- cjs: 同步导入模块,commonJS规范
module.exports = obj; const obj = require('"/test.js");
- esm: 异步导入,ES6 Module 简称 ESM
export const add = () => { count++;}; import { count, add } from '/a.js'
- umd: 通用模块定义,可以同时支持esm和cjs;
React umd
包结构
- dist
- lib
- es
- node_modules
- plugins
- scripts
- src
- LICENSE
- package.json
- README.md
基本命令
npm i 或 install
: 默认全部安装
npm i react
: 默认安装react模块 latest 标签上的最新版本
npm uninstall react
: 卸载项目中的react
npm i react@next
: 安装react模块 next 标签上的最新版本
npm i react@16.8.1
: 安装react模块16.8.1的版本
npm update react
: 升级项目中的react
npm install -g react
: 全局卸载react
npm run xxx
: 根据package.json中配置的scripts进行指定命令运行
npm login
: 登陆npm
npm link
: 链接本地npm
npm config
: 用来管理 npm 的配置
package.json
package.json 是一个用于描述和配置项目的重要文件,其中包含了许多字段和选项,可以影响项目的构建、依赖管理、脚本执行等方面。
{
"name": "npmtest", // 定义项目的名称,不能以"."和"_"开头,不能包含大写字母
"description": "这是一个npm教学项目", // 项目描述
"main": "dist/index.js", // 项目入口
"version": "1.6.3", // 版本号
"bin": "index.js", // 定义在全局安装时可执行的命令,脚手架必用
"private": true, // 是否私有,防止私有包发布到npm服务器,要发布到npm上设为false
"type": "module", // 在 node 支持 ES 模块后,要求 ES 模块采用 .mjs 后缀文件名。只要遇到 .mjs 文件,就认为它是 ES 模块。如果不想修改文件后缀,就可以在 package.json文件中,指定 type 字段为 module
"author": "bo.wang", // 项目作者
// 脚本入口,可通过`npm start`或`npm run start`执行对应的脚本
"scripts": {
"start": "cross-env PORT=9001 REACT_APP_ENV=local umi dev"
},
// 生产环境的依赖包
"dependencies": {
"antd": "^4.16.11",
},
// 开发环境依赖的包
"devDependencies": {
"typescript": "^4.3.4"
},
// 声明对npm或node的版本要求
"engines": {
"node": ">=10.0.0",
"npm": ">=6.9.0"
},
// 要检查的文件类型
"checkFiles": [
"src/**/*.js*",
"src/**/*.ts*",
"src/**/*.less",
"config/**/*.js*",
"scripts/**/*.js"
],
"keywords": ['npm', 'react'], // 项目关键词
// 项目贡献者
"contributors": [
"name <bo.wang1016@outlook.com> (http://blgo.wangboweb.site)"
],
"homepage": "http://blgo.wangboweb.site", // 项目主页
"repository": "https://github.com/Bowang816/weekly", // 项目仓库地址
// bug提交地址
"bugs": {
"url" : "https://github.com/Bowang816/weekly/issues",
"email" : "xxxxx@xx.com"
},
// 发布仓库配置
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
}
// git钩子
"gitHooks": {
"pre-commit": "lint-staged"
},
// Git暂存文件上运行linters的工具,通常配合gitHooks一起使用
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"license": "MIT", 指定开源协议
}
实战-脚手架的基础开发
-
创建项目
创建一个名称为账号_npmtest
的项目 -
新建package.json
{
"name": "npmtest",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"description": "wangbb npm test",
"author": "bo.wang",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+http://git项目地址.git"
},
"bugs": {
"url": "http://git项目地址/issues"
},
"homepage": "http://git项目地址#readme",
"dependencies": {
},
"devDependencies": {
}
}
- 新建入口文件index.js
新建src
文件夹,下面新建一个index.js
文件,内容如下
/**
* index.js
* @author 恪晨
* @since 2023/8/17
*/
// 方式1
// const hello = function(key){
// console.log('Hello World!');
// };
// exports.hello = hello;
//
// 方式2
class WangTest {
static print() {
console.log(11);
}
}
export default WangTest;
// 方式3
// const test1 = function () {
// return 'test1';
// }
//
// const test2 = function () {
// console.log('test2');
// }
//
// module.exports = {
// test1,
// test2
// }
-
配置入口文件启动命令
在package.json中配置"main": "index.js"
,默认是src文件夹下面index.js为入口 -
本地开发
在根目录新增一个文件夹demo,在下面新建一个index.js
和一个index.html
,- index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> hello,看控制台 </body> // 这里记得加type <script type="module" src="./index.js"></script> </html>
- index.js
/** * index.js * @author 恪晨 * @since 2023/8/17 */ // 方式1 // const {hello} = require('../src/index'); // console.log(hello); // 方式2 // 这里必须是index.js加上后缀名 import WangTest from "../src/index.js"; WangTest.print('11'); // 方式3 // const {test1, test2} = require('../src/index'); // console.log(test1(222)); // test2();
-
错误1:
Uncaught SyntaxError: Cannot use import statement outside a module (at index.js:12:1)
需要添加type:<script type="module" src="./index.js"></script>
-
错误2:
ReferenceError: require is not defined in ES module scope, you can use import instead
去掉package.json中的"type": "module"
-
错误3: Unknown file extension “.json” for ‘xx/x/xx/xx.json’
使用node --experimental-json-modules demo/index.js
执行即可
-
本地调试
- 方式1
在demo中的index.js中引用src下面的index.js,然后在html中通过script标签引入,浏览器打开html文件即可执行; - 方式2
直接在控制台通过node命令执行demo下的index.js文件
- 方式1
-
其他
在实际使用时会发现有些npm包内部代码是经过压缩混淆的,实际上在比较正规的包开发中,需要使用相关的构建工具如webpack、vite等工具对项目进行打包压缩,在内部业务开发过程中与正常项目开发无异,可能会使用到nodejs相关的东西,大家可以根据自己的需要进行实际开发,如脚手架的开发与上述内容就存在差异,详细的开发可以参考脚手架开发
发布-公共
开发完成后,注意最后打包出来的文件路径,可通过不同的打包工具如webpack、vite等进行项目打包,支持导出各种模块化规范的包,如果要发布到npm则需要有npm账号。
-
登陆账号
npm login
: 登陆npm
npm publish
: 进行发布
账号、密码、邮箱要保证正确
-
执行npm publish进行发布,发布成功在npm官网就能看到了
-
使用
在项目的package.json中安装后,使用import WangTest from "包名";
引入使用即可。
发布-私服
需要在package.json中配置
"publishConfig": {
"registry": "私服地址"
}
配置好私服地址以后,同上一样执行相关的命令即可,默认院内的包名前面需要添加@xasrd
保证这些包在这个域下面
- 自动发布可配合github action进行npm自动发布:https://blog.wangboweb.site/archives/607
取消发布
npm unpublish 包名 [-f]
: 删除整个包
npm unpublish 包名@0.0.1
: 删除0.0.1这个版本
版本管理
每次发布需要更新package.json中的version,可以手动修改,也可以通过命令修改,如下可根据自己的包的功能进行版本升级。
npm version major : 主版本号加 1,其余版本号归 0。
npm version minor : 次版本号加 1,修订号归 0。
npm version patch : 修订号加 1。
npm version 版本号 : 设置版本号为指定的版本号
npm version prerelease : 先行版本号增加1
npm version prerelease --preid=<prerelease-id> : 指定先行版本的名字
主版本号(major):一般改动很大,不兼容低版本。
次版本号(minor):兼容同一个大版本的API和用法。
修订号(patch):一般用来修复bug。
有的时候在修订号后面可能还会有先行版本号,例如 1.0.0-alpha.1 , 1.0.0-beta.4 , 2.0.0-rc.1 等。常用的先行版本一般为 alpha ,beta ,rc ,stable ,csp 等。
npm私服包使用
npm私服的包在使用时需要配置相关的私服源,或者也可以在项目中新建.npmrc
配置文件,通过配置以后,在安装相关依赖包的时候就会根据配置的内容找不同的源进行包的安装。
- 全局配置
npm config set @xxx:pkgname 源地址
# 验证是否配置成功,输出上面配置的地址则成功
npm config get @xxx:pkgname
- .npmrc
@xxx:pkgname = 源地址
其他
- package.json中版本符号含义
- “React”: “17.1.1”, 固定版本,只会安装17.1.1
- “React”: “^17.1.1”, 安装时更新到17.X.X的最新版本,但不会更新到18.X.X版本
- “React”: “~17.1.1”,安装时会更新到17.1.X的最新版本,但不会更新到17.2.X版本
- package-lock.json
- 锁定安装模块的版本号,package-lock.json文件锁定所有模块的版本号,包括主模块和所有依赖子模块
- 当你执行npm install的时候,node从package.json文件读取模块名称,从package-lock.json文件中获取版本号,然后进行下载或者更新
- npm install packagename@x.x.x(指定版本号)来进行安装才会更新,package-lock.json文件中的版本号也会随着更新
- 多人协同工作,将package-lock.json上传至代码仓库,保证各个开发者依赖包版本一致,避免因为依赖包小版本升级导致不同开发人员依赖安装不一致问题;
总结
通过以上内容的讲解,我们就可以从0开始实现一个npm包的开发到发布了,同时也了解到了在开发npm包时的相关注意事项,可以自己动手实现一个。
评论区