neo-cmp-cli
v1.10.13
Published
Neo 自定义组件开发工具,支持react 和 vue2.0技术栈。
Readme
Neo 自定义组件开发工具
neo-cmp-cli 是 Neo 自定义组件开发工具,基于 AKFun 的工程能力,提供初始化、编译构建、预览调试、热更新、多技术栈支持和发布等功能。
📑 目录
✨ 主要特性
- 零配置: 内置默认配置(前端工程最佳实践),开箱可用
- 多技术体系支持: 支持 Vue2、React、React+TypeScript 多种技术栈类型自定义组件的调试、构建与发布
- 多种构建类型: 本地预览(含热更新/代理)、外链调试、库构建(UMD/ESM)、部署&发布
- 灵活可配: 支持构建入口、别名、代理、公共样式注入、ESLint/StyleLint、Babel/Loader/Plugin 扩展等配置
- 样式与规范: 内置 Autoprefixer、Sass、PostCSS、ESLint、StyleLint
- 发布至 NeoCRM 平台: 支持一键发布到 NeoCRM 平台的能力,需自行补充授权配置
📦 内置模板
创建自定义组件时(执行初始化命令 neo init)可选用以下模板:
| 模板名称 | 说明 | 链接 | |---------|------|------| | React + TS | 内置信息卡片列表展示组件示例 | react-ts-custom-cmp-template | | React | React 模板(非 TS) | react-custom-cmp-template | | Antd | 内置 Antd UI 组件实现的数据仪表板展示组件示例 | antd-custom-cmp-template | | Neo | Neo 自定义业务组件(内置平台实体数据对象的增删改查示例组件) | neo-custom-cmp-template | | Neo H5 | Neo H5 自定义业务组件(内置平台实体数据对象的增删改查示例组件) | neo-h5-cmps | | Echarts | Echarts 图表自定义组件(含高德地图展示组件示例) | echarts-custom-cmp-template | | Vue2 | Vue2.0 自定义组件 | vue2-custom-cmp-template |
🚀 快速开始
1. 安装工具
yarn global add neo-cmp-cli
# 或
npm i -g neo-cmp-cli2. 创建项目
# 方式一:创建空的自定义组件项目
neo create project
# 方式二:根据模板创建自定义组件项目(默认 React+TS,可用 -t 指定模板,-n 指定自定义组件名称)
neo init3. 进入项目并安装依赖
cd xxCmpProject
npm install
# 或
yarn install4. 创建自定义组件
# 在当前项目中创建一个自定义组件
neo create cmp默认在当前项目 src/components/ 目录下新增自定义组件。
5. 本地预览
# 预览自定义组件内容
neo preview执行成功后,默认自动打开本地浏览器预览自定义组件内容。
6. 外链调试(在 NeoCRM 端预览与调试)
neo linkDebug提示:需在 NeoCRM / 页面设计器端启动 debug 模式,并添加控制台输出的外链脚本地址,方可在页面设计器端使用当前自定义组件。详细步骤请参考 本地调试自定义组件。
7. 发布到 NeoCRM 平台
neo push cmp提示:发布前请确保
package.json的name唯一、version不重复,并已配置 NeoCRM 平台授权信息。详细说明请参考 发布自定义组件至 NeoCRM。
📋 命令参考
| 命令 | 说明 | 参数 |
|------|------|------|
| neo init | 交互式创建自定义组件 | -t 指定模板,--name 指定组件名称 |
| neo create project | 创建自定义组件空项目(不含任何自定义组件) | --name 指定项目名称 |
| neo create cmp | 在当前项目中创建一个自定义组件 | --name 指定组件名称 |
| neo login | 登录 NeoCRM 平台(OAuth2 授权模式) | - |
| neo logout | 登出 NeoCRM 平台 | - |
| neo preview | 本地预览自定义组件内容,默认支持热更新与接口代理。(备注:当自定义组件使用 neo-ui-common 或者 neo-ui-component-web 时则不支持本地预览。) | --name 指定组件名称 |
| neo linkDebug | 外链调试模式,在平台端页面设计器中调试自定义组件 | --name 指定组件名称 |
| neo push cmp | 构建并发布到 NeoCRM 平台 | --name 指定组件名称 |
| neo pull cmp | 拉取线上自定义组件(NeoCRM 平台)至当前项目 | --name 指定组件名称 |
| neo delete cmp | 删除线上自定义组件(NeoCRM 平台) | --name 指定组件名称 |
常见问题
Q1: 在 Windows VSCode 控制台执行 neo 相关命令出现报错
A: 如果提示“在此系统上禁止运行脚本”,这个可能是 Windows 客户端的默认安全策略影响,可尝试在控制台输入以下命令解决:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser说明:以上命令用于设置 允许当前用户在此 Windows 客户端执行所有脚本。关于 PowerShell 执行策略
🔐 授权配置
使用 neo push cmp、neo pull cmp、neo delete cmp 等命令与 NeoCRM 平台交互时,需要配置授权信息。
方式一:OAuth2 登录授权(推荐)
OAuth2 授权码模式更加安全可靠,无需用户配置账户名和密码。
使用步骤
登录 NeoCRM 平台
neo login执行流程:
- 自动打开浏览器访问授权页面
- 在浏览器中输入 NeoCRM 账号密码进行登录(需选择对应的租户)
- 授权成功后自动跳转回本地(附带 code)
- cli 端 通过 code 获取 Token,并自动保存到项目的
.neo-cli/token.json文件中
登出 NeoCRM 平台
neo logout功能:清除本地保存的 token 文件,下次使用需要重新登录。
neo login 选择「自定义环境」时的授权配置示例
// neo.config.js
module.exports = {
neoConfig: {
neoBaseURL: 'https://crm-xx.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
loginURL: 'https://login-xx.xiaoshouyi.com/auc/oauth2/auth', // 登录授权 URL(用于获取 code)
tokenAPI: 'https://login-xx.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址
},
}Token 有效期
- access_token:默认有效期 2 小时
- refresh_token:默认有效期 30 天
- 系统会在 access_token 过期前 5 分钟自动刷新
- 如果 refresh_token 也过期,需要重新执行
neo login
常见问题
Q1: 浏览器无法自动打开怎么办?
A: 命令行会输出授权 URL,手动复制到浏览器中打开即可。
Q2: Token 刷新失败怎么办?
A: 如果 refresh_token 也过期(默认 30 天),需要重新执行 neo login。同时检查网络连接是否正常。
Q3: 授权登录后没有正常跳回 redirect_uri
A: 可能被浏览器安装的插件影响,目前已知会影响授权登录的浏览器插件有:Neo UI Extension,请关闭插件后重试。
方式二:密码授权配置
在项目根目录的 neo.config.js 文件中添加 NeoCRM 平台授权配置:
module.exports = {
neoConfig: {
neoBaseURL: 'https://crm-cd.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
tokenAPI: 'https://login-cd.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址
// NeoCRM 授权配置
authType: 'password',
auth: {
client_id: 'xx', // 客户端 ID,从创建连接器的客户端信息中获取(Client_Id)
client_secret: 'xxx', // 客户端秘钥,从创建连接器的客户端信息中获取(Client_Secret)
username: 'xx', // 用户在销售易系统中的用户名
/**
* password 为 用户在销售易系统中的账号密码加上 8 位安全令牌。
* 例如,用户密码为 123456,安全令牌为 ABCDEFGH,则 password 的值应为 123456ABCDEFGH。
*/
password: 'xx xx' // 用户账户密码 + 8 位安全令牌
},
},
}授权配置获取方式
客户端 ID 和客户端秘钥:需通过创建连接器获取
- 访问 销售易文档中心 / 创建连接器
- 创建连接器后,从客户端信息中获取
Client_Id和Client_Secret
安全令牌:如何获取安全令牌
- 访问 销售易文档中心 / OAuth安全认证 / 密码模式 / 获取令牌
- 按照文档说明获取 8 位安全令牌
password字段 = 用户账户密码 + 8 位安全令牌(直接拼接,无空格或分隔符)
OAuth2 模式 vs 密码模式
| 特性 | OAuth2 授权码模式 | 密码模式 | |------|------------------|---------| | 安全性 | ✅ 高(无需在配置文件中存储密码) | ⚠️ 较低(需要配置密码和安全令牌) | | Token 刷新 | ✅ 自动刷新 | ✅ 自动刷新 | | 有效期 | 2 小时(可自动刷新) | 永不过期 | | 推荐程度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
📖 开发指南
1. 默认自动识别自定义组件
- 自动生成入口配置:当
entry未配置时,自动从src/components目录下扫描并识别自定义组件,src/components下的子目录名称作为自定义组件的名称,并以其目录下的index.ts/.tsx/.js/.jsx文件作为组件内容文件,model.[tj]s作为模型内容文件 - 自动注册自定义组件:当
entry未配置时,自动生成自定义组件注册文件和模型注册文件,并注入到构建脚本中,无需用户手动编写注册文件(neo-register) - 构建时自动增加样式隔离:发布和 linkDebug 调试自定义组件时会自动给组件增加样式隔离(默认处理组件目录下的 (index|style).(scss|less) 样式文件),避免影响 Neo 平台样式。此模式对自定义组件根节点的样式命名有一定的规范要求(需要和组件名称保持一致),不符合规范会导致根节点样式失效。如需关闭此功能,请在 neo.config.js / webpack 中将 disableAutoAddStyleScope 设置为 true。
2. 设置自定义组件属性配置项
通过 neo init 初始化的自定义组件,默认自带组件模型文件,所有和页面设计器关联的信息均在此文件中定义(详细见 model 文件中的注释说明)。
自定义组件模型文件中可以设置的属性:
| 属性名 | 默认值 | 使用说明 | |-------|------------------|---------------| | cmpType | 在构建时根据当前组件目录名称自动生成 | 组件类型标识,用于标识组件的唯一性 | | label | - | 组件名称,用于设置在编辑器左侧组件面板中展示的名称 | | description | - | 组件描述,用于设置在编辑器左侧组件面板中展示的描述 | | iconUrl | - | 组件图标,用于设置在编辑器左侧组件面板中展示的图标 | | tags | ['自定义组件'] | 分类标签,用于设置在编辑器左侧组件面板哪个分类中展示 | | exposedToDesigner | true | 是否在页面设计器端可见 | | enableDuplicate | true | 在设计器中是否允许多次使用 | | targetPage | ['all'] | 适配的页面类型 | | targetObject | ['all'] | 支持的实体类型 | | targetApplication | ['all'] | 支持的应用类型 | | targetDevice | 'all' | 支持的设备类型 | | defaultComProps | - | 初次插入页面的默认属性数据 | | propsSchema | - | 定义组件在编辑器中可配置的属性 |
说明1:其中 propsSchema 用于添加自定义组件的属性配置面板,可用的配置项类型请见 neo-register 使用文档。
说明2:当前 NeoCRM 平台存在的页面类型:
- all: 所有页面类型
- indexPage: 首页
- entityListPage: 实体列表页
- entityFormPage: 实体表单页
- entityDetailPage: 实体详情页
- customPage: 自定义页面
- bizPage: 业务页面
3. 使用平台实体数据源
可在自定义组件中使用 OpenAPI SDK 对接平台实体数据源,详细使用方法见 neo-open-api。
import { xObject } from 'neo-open-api';
// 查询联系人列表
const {data: contacts} = await xObject.query({
xObjectApiKey: 'Contact',
fields: ['name', 'phone', 'email'],
page: 1,
pageSize: 20,
orderBy: 'createdAt desc'
});
// 创建新联系人
const {data: newContact} = await xObject.create('Contact', {
data: {
name: '王五',
phone: '13700137000',
email: '[email protected]'
}
});
// 更新联系人
const {data: updatedContact} = await xObject.update('Contact', newContact.id, {
data: {
name: '王五(更新)'
}
});
// 获取联系人详情
const {data: contactDetail} = await xObject.get('Contact', newContact.id);
// 删除联系人
await xObject.delete('Contact', newContact.id);4. 使用平台自定义API
可在自定义组件中使用 OpenAPI SDK 对接平台自定义API,详细使用方法见 neo-open-api。
import { customApi } from 'neo-open-api';
// 基本用法
const result = await customApi.run({
apiUrl: '/rest/custom/api/endpoint', // 自定义API地址
methodType: 'POST', // 请求方法,如 'GET', 'POST', 'PUT', 'DELETE' 等(可选,默认为 'POST')
data: { // 请求数据
key1: 'value1',
key2: 'value2'
}
});参数说明:
apiUrl: 自定义API的完整地址(必填)methodType或method: 请求方法,默认为 'POST'data: 请求数据对象,会被包装在data字段中发送
返回结果:
{
status: boolean, // 返回 true 表示执行成功
code: number | string, // 返回码
msg: string, // 一般用于返回错误信息
data: any // API返回的数据
}使用示例:
import { customApi } from 'neo-open-api';
// 执行自定义API
const result = await customApi.run({
apiUrl: '/rest/custom/api/processData',
methodType: 'POST',
data: {
param1: 'value1',
param2: 'value2'
}
});5. 默认复用平台第三方依赖
自定义组件构建过程中默认会剔除掉平台已有依赖模块(比如 antd、echarts、axios、lodash 等),确保自定义组件构建后的资源体积较小。
平台预置的第三方依赖包
自定义组件可直接使用以下第三方依赖包(NeoCRM 平台预置):
| 依赖包 | 版本 | |--------|------| | react | ^16.13.1 | | react-dom | ^16.13.1 | | mobx | ^6.3.0 | | mobx-react | ^7.0.0 | | mobx-state-tree | ^5.4.0 | | echarts | 5.4.2 | | antd | 4.9.4 | | antd-mobile | 2.3.4 | | @ant-design/icons | ^4.8.0 | | video-react | 0.14.1 | | axios | ^0.27.2 | | classnames | ^2.3.2 | | qs | ^6.11.0 | | lodash | ^4.17.21 | | neo-ui-component-web | ^1.0.0 | | neo-ui-common | ^1.0.0 | | neo-open-api | ^1.1.9 | | amis | ^1.1.5 |
注意:自定义组件中请使用依赖包支持的版本,如版本不匹配运行时可能出现异常。
6. 本地调试自定义组件
步骤 1:启动外链调试模式
neo linkDebug启动成功后,当前命令控制台会输出一个可使用的外链脚本地址(通常为 http://localhost:1024/index.js)。
步骤 2:登录 Neo 平台,打开页面设计器,并开启 debug 模式
在页面设计器 URL 后添加 debug=true 参数并重新访问,即可开启 debug 模式。
步骤 3:添加外链脚本地址
页面设计器开启 debug 模式后,左侧会展示外部链接管理面板。将第 1 步生成的「外链脚本地址」添加进来,即可在此页面设计器 / 组件物料面板中看到对应自定义组件。
7. 发布自定义组件至 NeoCRM
执行 neo push cmp 即可构建并发布自定义组件至 NeoCRM 平台,其构建后资源也会上传到 NeoCRM 平台端提供的 CDN 中。
使用方式
# 方式一:交互式选择要发布的自定义组件
neo push cmp
# 方式二:直接指定要发布的自定义组件名称
neo push cmp --name=xxCmp
# 或
neo push cmp -n xxCmp发布前请确保
- ✅ package.json 的 name 唯一:确保当前项目的
package.json中的name字段在 NeoCRM 平台中唯一 - ✅ version 不重复:每次发布时,请更新
package.json中的version字段,确保版本号不重复 - ✅ 已配置 NeoCRM 平台授权信息:在
neo.config.js中配置neoConfig.auth或使用neo login登录 - ✅ 自定义组件已正确构建:确保组件代码可以正常构建,且
dist目录下有对应的构建产物 - ✅ 组件模型文件存在:确保组件目录下有
model.ts或model.js文件,且正确导出了模型类
注意事项
- 版本管理:每次发布前务必更新
package.json中的version字段,避免版本冲突 - 组件名称唯一性:确保
package.json中的name字段在平台中唯一 - 模型文件要求:组件必须包含有效的模型文件(
model.ts或model.js),且正确导出模型类 - 技术栈一致性:确保组件使用的技术栈与项目配置一致(React、React+TS、Vue2 等)
- 构建产物完整性:确保
dist目录下包含组件的 JS 文件和模型文件(xxCmp.js和xxCmpModel.js) - 网络连接:发布过程需要网络连接,确保可以访问 NeoCRM 平台和 OSS 服务
常见问题
Q: 发布失败,提示"未找到 NeoCRM 平台授权配置"
A: 请检查 neo.config.js 文件中是否配置了 neoConfig.auth,或使用 neo login 进行 OAuth2 登录授权。
Q: 发布失败,提示"未找到自定义组件模型文件"
A: 请确保组件目录下有 model.ts 或 model.js 文件,且构建后在 dist 目录下生成了对应的 xxCmpModel.js 文件。
Q: 发布失败,提示"获取 token 失败(授权配置错误)"
A: 请检查 neo.config.js 文件中是否配置了 neoConfig.auth,确保所有授权字段都已正确填写。
线上 NeoCRM 端使用
发布成功后,即可在对应租户环境下的页面设计器和表单设计器中使用此自定义组件。
8. 拉取线上自定义组件至本地项目
执行 neo pull cmp 即可从 NeoCRM 平台拉取自定义组件源码到当前项目。该命令会将线上自定义组件的源码下载并解析到当前项目的 src/components 目录下。
使用方式
# 方式一:交互式选择要拉取的自定义组件
neo pull cmp
# 方式二:直接指定要拉取的自定义组件名称
neo pull cmp --name=xxCmp
# 或
neo pull cmp -n xxCmp拉取前请确保
- ✅ 已配置 NeoCRM 平台授权信息(
neo.config.js中的neoConfig.auth或使用neo login) - ✅ 当前项目目录中不存在同名自定义组件(
./src/components目录下) - ✅ 拉取的组件与当前项目技术栈一致(React、React+TS、Vue2 等)
注意事项
- 拉取的自定义组件会覆盖本地同名组件,请谨慎操作
- 如果组件源码中包含新增的依赖包,拉取完成后会提示执行
npm install或yarn install - zip 源文件会保留在
.neo-cli/zip-source目录下,可手动删除
9. 删除线上自定义组件
执行 neo delete cmp 即可从 NeoCRM 平台删除指定的自定义组件。该命令会删除平台上的自定义组件,删除后该组件将无法在页面设计器和表单设计器中使用。
使用方式
# 方式一:交互式选择要删除的自定义组件
neo delete cmp
# 方式二:直接指定要删除的自定义组件名称
neo delete cmp --name=xxCmp
# 或
neo delete cmp -n xxCmp删除前请确保
- ✅ 已配置 NeoCRM 平台授权信息(
neo.config.js中的neoConfig.auth或使用neo login) - ✅ 确认要删除的组件名称正确,删除操作不可恢复
注意事项
- ⚠️ 删除操作不可恢复:删除后的自定义组件将无法恢复,请谨慎操作
- ⚠️ 影响范围:删除组件后,所有使用该组件的页面和表单将受到影响,请确保没有正在使用的场景
- 💡 建议先备份:删除前建议先使用
neo pull cmp拉取组件源码到本地进行备份
10. 自定义组件之间实现模块共享
步骤 1:在自定义组件A(customCmpA)/ 配置文件中定义要共享出来的模块A(xxModuleA)
// customCmpA 组件的 neo.config.js
module.exports = {
neoCommonModule: {
// exports: ['xxModule'], // 数组写法,用于导出当前自定义组件中的第三方依赖模块
exports: { 'xxModuleA': path.resolve('./src/components/xxModuleA') }, // 对象写法,可用于导出自定义组件中的某个内容模块(需要使用绝对路径导出)
},
}步骤 2:在自定义组件B(customCmpB)/ 配置文件中声明需要使用自定义组件 A 分享出来的模块(xxModuleA)
// customCmpB 组件的 neo.config.js
module.exports = {
neoCommonModule: {
remoteDeps: ['customCmpA'], // 远程依赖(自定义组件),表示当前自定义组件 B 会用到哪些自定义组件
externals: ['xxModuleA'], // 自定义组件中需要剔除的外部模块(远程自定义组件中分享出来的模块),仅支持数组写法,需要和 remoteDeps 配合使用
},
}步骤 3:在自定义组件B 中使用自定义组件 A 分享出来的模块(xxModuleA)
import xxModuleA from 'xxModuleA'; // 导入自定义组件 A 共享出来的模块⚙️ 配置说明
neo-cmp-cli 默认提供完整配置;如需自定义,使用 neo config init 生成 neo.config.js 并按需修改。
以下为常用配置示例(片段可自由组合)。
基础配置
1. 代码规范与检查相关配置
module.exports = {
settings: {
enableESLint: true, // 是否开启ESLint,默认开启ESLint检测代码格式
enableESLintFix: false, // 是否ESLint自动修正代码格式
enableStyleLint: true, // 是否开启StyleLint,默认开启StyleLint检测代码格式
enableStyleLintFix: false // 是否需要StyleLint自动修正代码格式
},
}2. 构建入口配置
提示:当未配置
entry时,cli 默认从src/components目录下扫描并识别自定义组件,并自动生成对应的 entry 构建入口配置。
优先级:linkDebug/build2lib/pushCmp.entry > webpack.entry
如需自定义构建入口配置,请按如下结构调整项目工程配置文件(neo.config.js):
module.exports = {
webpack: {
entry: { index: './src/index.js' },
},
linkDebug: { entry: {} },
build2lib: { entry: {} },
pushCmp: { entry: {} },
}备注:详细配置方法请查看 Webpack 官网 关于entry的配置方法。
3. 解析配置(extensions/alias)
module.exports = {
webpack: {
resolve: {
extensions: ['.js', '.jsx', '.vue', 'json'],
alias: {},
},
},
}备注:
- extensions 的详细配置方法请查看 Webpack 官网 关于resolve-extensions的配置方法
- alias 的详细配置方法请查看 Webpack 官网 关于resolve-alias的配置方法
4. 页面模板与公共样式资源
module.exports = {
webpack: {
template: '', // 自定义页面模板路径
sassResources: [], // sassResources 中添加的 样式文件会作为项目的公共SASS内容(变量、mixin、function等)
},
}高级配置
5. 依赖打包策略(忽略 node_modules)
module.exports = {
webpack: {
ignoreNodeModules: true, // 打包时是否忽略 node_modules,默认为false
allowList: [], // 用于配置会注入bundle中的依赖包(ignoreNodeModules 为 true 时生效)
},
}6. TypeScript 声明文件与工程目录
module.exports = {
webpack: {
createDeclaration: false, // 可选择是否生成ts声明文件,默认为false
projectDir: ['./src'], // 构建项目中,设置生效的目录(可同时设置多个目录),用于提高前端工程执行效率。可以不配置,默认为['./src']
},
}7. 环境变量替换(params-replace-loader)
module.exports = {
envParams: {
common: { '#version#': '20250822.1' },
local: {
'#dataApiBase#': 'http://localhost:1024',
'#assetsPublicPath#': 'http://localhost:1024',
'#routeBasePath#': '/',
},
},
}8. 本地开发代理与 HTTPS
module.exports = {
preview: {
proxyTable: {},
https: false,
},
}备注:
- 关于proxyTable的配置方法
- 启用 HTTPS 后,若浏览器提示不安全,可在 Chrome 地址栏打开
chrome://flags/#allow-insecure-localhost并设置为 Enabled
9. 库构建(UMD/ESM)
module.exports = {
build2lib: {
NODE_ENV: 'production',
libraryName: '',
assetsRoot: resolve('dist'),
assetsPublicPath: '/',
assetsSubDirectory: '',
productionSourceMap: false,
productionGzip: false,
productionGzipExtensions: ['js', 'css', 'json'],
bundleAnalyzerReport: false,
ignoreNodeModules: true,
allowList: [],
},
}10. 自定义 Loader / Plugin / Babel Plugins
module.exports = {
webpack: {
moduleRules: [], // 用于添加自定义 loaders
plugins: [], // 用于添加自定义 plugins
babelPlugins: [ // 用于添加自定义 Babel plugins
[
'component',
{ libraryName: 'element-ui', styleLibraryName: 'theme-chalk' },
],
],
},
}备注:以上自定义 babelPlugins 用于实现 element-ui 组件按需引入。
也支持以函数形式动态调整内置 Babel Plugins:
module.exports = {
webpack: {
babelPlugins: (curBabelPlugins) => {
curBabelPlugins.push(/* your plugin */)
return curBabelPlugins
},
},
}如需更多细节与高级用法,请参考模板项目与源码注释。
