{"bugs":{"url":"https://github.com/ice-lab/iceworks-cli/issues"},"dist":{"shasum":"248f725ac56b4e715add800e1ba75a80a0a5da1a","tarball":"https://registry.npmjs.org/build-plugin-component/-/build-plugin-component-1.12.2-beta.1.tgz","fileCount":106,"integrity":"sha512-q6auDXsSWPCDypKwRYQfuLx43lZnx6DOvyc7l/Z0evh9m/mLOQwUs6sfLj9ByioX3i+9vuIvMb+S6srOOBOj1g==","signatures":[{"sig":"MEYCIQCdnMDB8zh+a+wMPzneuJLVIgdl6hlGfq0ONyl1rOIA0gIhAPyDEAdDYmIhWxyGoIygY7yRgtOdGsWvQSYxGhVA8jD6","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":316613},"main":"src/index.js","name":"build-plugin-component","author":"","readme":"# build-plugin-component\n\n通过 [build-scripts](https://github.com/ice-lab/build-scripts) 和 build-plugin-component 支持业务组件（即 NPM 包）的开发，功能：\n\n- 支持构建 ES5 + ES Module 产物，对应 `es/`，使用 babel 构建\n- 支持构建 ES5 + Commonjs 产物，对应 `lib/`，使用 babel 构建\n- 支持构建 UMD 产物，对应 `dist/`，使用 webpack 构建\n- 支持使用 markdown 写 demo 同时构建文档产物，对应 `build/`，使用 webpack 构建\n\n**该方案同时支持 React 和 Rax 业务组件开发，如果是开发 Rax 组件请查阅 [Rax 官方文档](https://rax.js.org/docs/guide/com-dev)，本文档主要介绍 React 组件开发。**\n\n## 目录\n\n- [创建组件](#创建组件)\n- [组件调试构建](#组件调试构建)\n- [组件目录](#组件目录)\n- [工程配置](#工程配置)\n- [版本升级](#版本升级)\n- [高阶用法](#高阶用法)\n\n## 创建组件\n\n通过命令行初始化一个业务组件项目：\n\n```bash\n# 安装全局 CLI\n$ npm i -g iceworks\n# 新建组件文件夹\n$ mkdir my-component && cd my-component\n# 初始化\n$ iceworks init component\n```\n\n> 如果是**阿里内部**的同学并且想接入 DEF 发布 NPM 包，可以参考文档 [组件开发接入 DEF](https://yuque.alibaba-inc.com/ice/rdy99p/gbekwv)\n\n## 组件调试构建\n\n```bash\n$ cd my-component\n$ npm install\n$ npm start\n\n# 实时编译 lib&es 产物\n$ npm start -- --watch\n\n# 实时编译 dist 产物\n$ npm start -- --watch-dist\n\n# 启动 https 服务\n$ npm start -- --https\n\n# 跳过 demo 构建\n$ npm start -- --skip-demo\n$ npm build -- --skip-demo\n\n# 跳过自动打开预览链接\n$ npm start -- --disable-open\n```\n\n## 组件目录\n\n### 目录结构\n\n```\n├── src/                  # 组件源码\n│  └── index.js\n├── demo                  # 组件 demo\n│  └── usage.md\n├── lib/                  # 构建产物，编译为 ES5 + Commonjs 规范的代码\n├── es/                   # 构建产物，编译为 ES5 + ES Module 规范的代码\n├── dist/                 # 构建产物，UMD 相关产物，默认不生成，需要通过设置 library 参数开启\n├── build/                # 构建产物，用于组件文档预览\n├── build.json            # 工程配置\n├── README.md\n└── package.json\n```\n\n### 组件入口\n\n组件入口文件为 `src/index.tsx`：\n\n```js\nimport React from 'react';\n\nexport default function ExampleComponent(props) {\n  const { type, ...others } = props;\n  return <>Hello</>;\n}\n```\n\n### 样式文件\n\n默认生成样式文件为 `src/index.css`，根据需求可调整成 sass 或 less 文件。\n\n推荐在 `src/index.tsx` 中引入组件样式：\n\n```diff\nimport React from 'react';\n+ import './index.css';\n\nexport default function ExampleComponent(props) {}\n```\n\n### 组件 demo\n\n组件的 demo 演示文件，位于 `demo` 目录下，使用 `yaml-markdown` 语法。可以通过修改默认的 `usage.md` 来调整组件 demo，或通过增加 example.md 文件来创建多个 demo。\n\n每个 demo 的格式如下：\n\n````\n---\ntitle: Simple Usage\norder: 1\n---\n\n本 demo 演示一行文字的用法。\n\n```jsx\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport ExampleComponent from 'my-component';\n\nfunction App() {\n  return <ExampleComponent />;\n}\n\nReactDOM.render(<App />, mountNode);\n```\n````\n\n### 组件文档\n\n在执行 `npm run build` 时，会通过 `demo/` 以及 `README.md` 生成 `build/index.html`，将 html 进行托管即可完整预览组件的文档。\n\n以 `@icedesign/qrcode` 组件的文档为例，通过 unpkg 的服务即可查阅文档：[文档地址](https://unpkg.com/@icedesign/qrcode@1.0.5/build/index.html) 。\n\n注意：构建 `build` 会加长 `npm run build` 的时间，如不需要可通过 `--skip-demo` 的命令行参数关闭。\n\n## 工程配置\n\n基于 build-scripts 的项目统一使用 `build.json` 作为工程配置的文件：\n\n```json\n{\n  \"type\": \"react\",\n  \"plugins\": [[\"build-plugin-component\"]]\n}\n```\n\n通过 build-plugin-component 这个基础插件，我们支持了以下配置项：\n\n### alias\n\n- 类型：object\n- 默认值：`{}`\n\n```json\n{\n  \"alias\": {\n    \"@\": \"./src\"\n  }\n}\n```\n\n### babelPlugins\n\n- 类型：array\n- 默认值：[]\n\n> 注意：该选项仅影响 es/lib 目录构建产物，如需要修改 demo 预览时的 babel 配置，请通过 webpack-chain 形式进行自定义。\n\n### devServer\n\n- 类型：object\n- 默认值：`{ hot: true, disableHostCheck: true, clientLogLevel: 'silent' }`\n\n同 [webpack devServer 配置](https://webpack.js.org/configuration/dev-server/)，自定义配置将会与默认配置合并。\n\n### filename\n\n- 类型： string\n- 默认值：`null`\n\n如果打包 library 到 dist 目录，用来配置打包文件的名字。\n\n### library\n\n- 类型： string\n- 默认值：`null`\n\n如果打包 library 到 dist 目录，用来配置 library 名字。\n\n### libraryExport\n\n- 类型： string\n- 默认值：`null`\n\n如果打包 library 到 dist 目录，用来配置 library 出口配型，如可配置 default，对应的组件出口为 export default MyComponent。\n\n### libraryTarget\n\n- 类型： string\n- 默认值：`null`\n\n如果打包 library 到 dist 目录，用来配置 library 的类型，如 umd、amd 等。\n\n### sourceMap\n\n- 类型： boolean\n- 默认值：`false`\n\n如果打包 library 到 dist 目录，用来配置是否产出 sourceMap 文件。\n\n### define\n\n- 类型：object\n- 默认：`null`\n\n### minify\n\n- 类型：boolean\n- 默认：`false`\n\n如果打包 library 到 dist 目录，配置打包文件是否压缩。\n\n### generateTypesForJs\n\n- 类型：boolean\n- 默认值：`false`\n\n### htmlInjection\n\n- 类型：object\n- 默认值：`{}`\n\n向 demo 预览的 html 里注入内容，比如插入一些静态脚本等：\n\n```\n{\n  \"htmlInjection\": {\n    \"headAppend\": [\n      \"<script src='http://foo.com/a.js' />\",\n      \"<link href='http://foo.com/a.css' />\"\n    ],\n    \"headPrepend\": [],\n    \"bodyAppend\": [],\n    \"bodyPrepend\": [],\n  }\n}\n```\n\n### externals\n\n- 类型： object\n- 默认值：`null`\n\n如果打包 library 到 dist 目录，用来配置是否需要外部 externals，用来避免三方包被打包。\n\n### babelOptions\n\n- 类型：array\n- 默认值：[]\n\n比如修改 preset-env 的配置：\n\n```json\n{\n  \"babelOptions\": [{ \"name\": \"@babel/preset-env\", \"options\": { \"module\": false } }]\n}\n```\n\n> 注意 babelOptions 仅影响 es/lib 目录构建产物，如需要修改 demo 预览时的 babel 配置，请通过 webpack-chain 形式进行自定义\n\n### basicComponents\n\n- 类型： array\n- 默认值：`[]`\n- 备注：当设置 `disableGenerateStyle: true` 时，该功能也会随之关闭\n\n插件内置了 `['antd', '@alifd/next']` 两个 NPM 包，开发者配置的数组会跟内置数组做合并。配置在该数组里的 NPM 包会在构建时经过 babel-plugin-import 处理，也就是会经过一下转换：\n\n```\n// src/index.tsx\nimport { Button } from 'antd';\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// es/index.js\nimport Button from 'antd/es/button';\n// lib/index.js\nvar _button = require('antd/lib/button');\n```\n\n应用级的项目在使用 webpack + babel-loader 时，一般都会设置 `exclude: /node_modules/` 的选项，这会导致 babel-plugin-import 无法处理 NPM 包里的此类语法，因此我们在 NPM 包打包时前置做了该项转换。\n\n**当下的构建工具都已经内置支持 tree-shaking，不再需要使用 babel-plugin-import 做一层转换，因此该选项不推荐使用，建议通过设置 `disableGenerateStyle: true` 来关闭该能力。**\n\n### disableGenerateStyle\n\n- 类型：boolean\n- 默认值：false\n- 备注：**推荐将该选项置为 true**\n\n如果不设置该选项或者设置为 false，组件打包时会自动分析 `src/` 代码并生成 `[es|lib]/style.js` 的文件，内容格式如下：\n\n```js\n// es/style.js\nimport '@formily/next-components/esm/time-picker/style';\nimport '@alifd/next/es/input/style';\nimport '@alifd/next/es/tag/style';\n```\n\n代码里依赖的 NPM 包符合下述规则之一则会被生成到 `style.js` 中：\n\n- 配置在 basicComponents 中的包名，如 `antd`, `@alifd/next`\n- 对应包的 package.json 里有 `stylePath` 字段\n\n功能设计初衷：假设业务组件依赖了 antd 里面的 N 个组件，在应用项目里使用该业务组件时如何有效引入 antd 这 N 个组件的样式？要么显视的一个一个 `import`，要么直接引入 antd 的全量样式，前者手写成本太高，后者无法按需引入样式，因此我们设计了这个功能，项目里只需要引入这个业务组件的 `style.js` 即可（如果使用了 icejs 框架那么应用会自动分析并引入 `style.js`，开发者完全不需要关心样式引入问题）。\n\n经过一些实践之后，我们发现按需引入大包组件样式的收益并不大，参考 [issue](https://github.com/ant-design/ant-design/issues/16600#issuecomment-492572520)，另外还会引入一些复杂的工程问题，**因此我们不再推荐使用该能力，建议应用项目里直接全量引入大包（antd/fusion）组件的样式。**\n\n### subComponents\n\n- 类型：Boolean\n- 默认值：false\n\n是否包含子组件，一般用于开发类似 fusion/antd 这种大包，开启该选项之后，会为每个组件生成对应的 `style.js` 文件。\n\n### demoTemplate\n\n- 类型：array | string\n- 默认值：`template-component-demo`\n\n插件内置了 npm 包 `template-component-demo` 作为组件开发及构建时的 demo 预览，可以通过指定 `demoTemplate` 对进行自定义。\n\ndemo 预览组件默认接受如下参数：\n\n- `readmeData`：readme.md 文件中的解析数据\n- `demoData`：demo 文件夹下 markdowm 内容解析的数据\n- `env`：当前运行环境 `development|production`\n- `templateProps`：模版自定义参数，可以通过设置 `\"demoTemplate\": [\"template-component-demo\", { \"platform\": \"h5\" }]` 的方式为模版定义参数\n\n### docGenIncludes\n\n- 类型：Array<string>\n- 默认值：`[]`\n\n使用 [react-docgen](https://github.com/reactjs/react-docgen) 自动生成 demo api 预览。需要配置代码扫描路径才会生效，例如：\n\n```json\n{\n  \"plugins\": [\"build-plugin-component\"],\n  \"docGenIncludes\": [\"src/*.tsx\"]\n}\n```\n\n便会扫描代码文件 `src` 文件夹下的所有 `*.tsx` 文件（不包含子文件夹）：\n\n```js\ninterface ComponentProps {\n  /** Title of the example  */\n  title: string;\n  /** Type of the example  */\n  type?: 'native' | 'hybrid';\n}\n\nexport default function ExampleComponent(props: ComponentProps) {\n  ...\n}\n```\n\n则会生成对应的 api 预览：\n\n![](https://gw.alicdn.com/imgextra/i1/O1CN01y2GRoH1thMar8I3Be_!!6000000005933-2-tps-2200-624.png)\n\n该能力目前支持 PropType、TypeScript 等方式的类型注解，具体可详见 [react-docgen 文档](https://github.com/reactjs/react-docgen#proptypes)。需要注意的是，`react-docgen` 不支持为匿名组件生成 api 预览：\n\n```js\n// 不支持匿名组件\nexport default (props: ComponentProps) => {\n  ...\n}\n```\n\n如果是多组件项目，且配置了多页文档，例如文件结构为：\n\n- demo\n  - List\n    - usage.md\n    - customize-styles.md\n\n可以在 demo/List/ 下面新建 api.md 文件，并在头部配置此页面包含哪些接口文档。（正文可以留空，也可以补充内容）\n\n```md\n---\ntitle: 列表组件 API\norder: 3\ndocGenIncludes:\n  - src/components/List.tsx\n  - src/components/ListItem.tsx\n---\n```\n\n## 版本升级\n\n### 0.x -> 1.x\n\nbuild-plugin-component@1.x 完全向前兼容，因此直接修改 `package.json` 中的对应依赖即可。\n\n## 高阶用法\n\n### 定制 demo 样式\n\n`demo/usage.md`:\n\n````diff\n---\ntitle: Simple Usage\norder: 1\n---\n\n```jsx\nReactDOM.render(<div className=\"ttt\">hello<>, mountNode);\n```\n\n+ ```css\n+ .ttt {\n+   background: red;\n+ }\n+ ```\n````\n\n### 使用 js/ts 文件编写 demo\n\n新建 `demo/usage.jsx`：\n\n```jsx\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport ExampleComponent from 'my-component';\n\nfunction App() {\n  return <ExampleComponent />;\n}\n\nexport default App;\n```\n\n修改 `demo/usage.md`：\n\n````diff\n---\ntitle: Simple Usage\norder: 1\n---\n\n本 demo 演示一行文字的用法。\n\n```jsx\n+ <DemoCode src=\"./usage.jsx\" />\n```\n````\n\n工程上将自动将路径中的源码获取，并展示在 Demo 预览页面中。通过上述的方式开发 Demo 可以享受编辑器带来的代码提示、语法高亮等便捷功能。\n\n### 生成 UMD 文件\n\n通过设置工程上的 UMD 的相关配置，可以将业务组件以 UMD 模块方式打包，比如对上述示例组件进行设置：\n\n```json\n{\n  \"library\": \"ExampleComponent\",\n  \"libraryTarget\": \"umd\"\n}\n```\n\n### 多组件文档\n\n默认情况下，`demo/` 目录里的文件都是扁平的，适合展示单个组件的文档，比如：\n\n```bash\ndemo/\n├── simple.md\n└── usage.md\n```\n\n但是某些情况下，我们的业务组件可能会导出多个组件，此时可以通过目录嵌套来展示多个组件的文档：\n\n```\n├── demo/\n│   ├── ComponentA/\n│   │  ├── simple.md\n│   │  └── simple2.md\n│   ├── ComponentB/\n│   │  ├── simple.md\n│   └──└── simple2.md\n```\n\n最终效果如下，其中每个目录对应一个组件，即左侧的一个导航：\n\n![](https://img.alicdn.com/tfs/TB1nQrZk5DsXe8jSZR0XXXK6FXa-1426-700.png)\n","engines":{"node":">=12"},"gitHead":"7faf9bc324d2c502933508319e061c4579f87632","license":"MIT","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"rax-publisher","email":"rax-public@alibaba-inc.com"},"homepage":"https://ice.work/docs/materials/about","keywords":["plugin"],"repository":{"url":"git+https://github.com/ice-lab/iceworks-cli.git","type":"git"},"_npmVersion":"9.8.1","description":"build plugin for component development","directories":{},"maintainers":[{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@gmail.com"},{"name":"shiftj","email":"stjkl@foxmail.com"},{"name":"oraaange","email":"oraaangecolin@gmail.com"},{"name":"yacheng","email":"narutosun2@163.com"},{"name":"maoxiaoke","email":"thebigyellowbee@qq.com"},{"name":"rax-publisher","email":"rax-public@alibaba-inc.com"}],"_nodeVersion":"20.6.1","dependencies":{"ip":"^1.1.5","chalk":"^4.1.0","utils":"^0.3.1","marked":"^2.0.0","core-js":"^3.6.4","js-yaml":"^4.0.0","prismjs":"^1.17.1","webpack":"^4.41.1","chokidar":"^3.3.1","fs-extra":"^8.1.0","url-join":"^4.0.1","camelcase":"^6.2.0","user-home":"^2.0.0","handlebars":"^4.5.3","typescript":"^4.0.0","webpackbar":"^5.0.0-3","@babel/core":"^7.1.2","json-loader":"^0.5.7","sass-loader":"^10.0.5","@babel/types":"^7.7.2","loader-utils":"^1.4.0","react-docgen":"^5.4.0","style-loader":"^1.2.1","@babel/parser":"^7.7.3","console-clear":"^1.1.1","ice-npm-utils":"^3.0.0","webpack-chain":"^6.5.1","jsx2mp-runtime":"^0.4.15","@babel/traverse":"^7.7.2","qrcode-terminal":"^0.12.0","rax-jest-config":"^0.0.4","react-dev-utils":"^10.0.0","time-fix-plugin":"^2.0.7","@babel/generator":"^7.7.2","rax-babel-config":"^0.1.2","handlebars-loader":"^1.7.1","error-stack-tracey":"^0.1.3","postcss-preset-env":"^6.7.0","rax-compile-config":"^0.2.15","webpack-dev-server":"^3.11.2","babel-plugin-import":"^1.12.2","html-webpack-plugin":"^4.5.0","image-source-loader":"^0.6.5","rax-server-renderer":"^1.2.0","build-scripts-config":"^3.0.0","postcss-plugin-rpx2vw":"^0.0.2","terser-webpack-plugin":"^4.1.0","miniapp-builder-shared":"^0.2.10","miniapp-compile-config":"^0.2.5","webpack-node-externals":"^2.5.2","react-docgen-typescript":"^2.2.2","template-component-demo":"^2.0.0","babel-plugin-module-resolver":"^4.0.0","babel-plugin-transform-define":"^2.0.0","@babel/plugin-transform-runtime":"^7.6.2","optimize-css-assets-webpack-plugin":"^5.0.4","case-sensitive-paths-webpack-plugin":"^2.3.0","@babel/plugin-proposal-private-methods":"^7.16.0","@babel/plugin-proposal-class-properties":"^7.16.0","@babel/plugin-proposal-private-property-in-object":"^7.16.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"@types/node":"^12.12.18"},"_npmOperationalInternal":{"tmp":"tmp/build-plugin-component_1.12.2-beta.1_1698820339035_0.4200364789276838","host":"s3://npm-registry-packages"},"_id":"build-plugin-component@1.12.2-beta.1","version":"1.12.2-beta.1"}