Open WangShuXian6 opened 2 years ago
mkdir preconstruct-demo
cd preconstruct-demo
yarn init
// 按提示输入仓库信息
package.json添加
workspaces
字段 将private
设置为true
防止将仓库意外发布@my
为 @ + npm账户名称{ "name": "@my", "version": "1.0.0", "private": true, "workspaces": [ "packages/*" ], "license": "MIT" }
在仓库根目录
package.json
添加 修复脚本 该命令可以交互式的修复大部分的配置问题 package.json"scripts": { "fix":"preconstruct fix" }
项目错误修复
yarn fix
packages
目录下创建两个示例包 a,b创建一个
packages/a
目录和packages/b
目录在两个包目录中分别运行
yarn init
并对所有问题回答是cd preconstruct-demo/packages/a yarn init
cd preconstruct-demo/packages/b yarn init
>修改包名为 `@my/a` `@my/b`
### 创建源文件
>packages/a/src/index.js
```js
export default function () {
console.log("a");
}
packages/b/src/index.js
export default function () { console.log("b"); }
在仓库根目录执行 以安装依赖 参数
-W
指定 Yarn 为整个 workspace 安装指定依赖。 所有依赖为组件间共享组件。 在工作空间的根将允许在根 package.json 的脚本中使用yarn add @preconstruct/cli -W
在仓库根目录执行 以设置包
yarn preconstruct init
按提示使用空格键选中需要 preconstruct 处理的包 a,b
注意:parcel 会再次编译umd包导致错误,无法取得全局变量
packages/a/package.json
下添加配置"umd:main": "dist/my-a.umd.min.js", "preconstruct": { "umdName": "My.a" }
packages/b/package.json
下添加配置"umd:main": "dist/my-b.umd.min.js", "preconstruct": { "umdName": "My.b" }
preconstruct.umdName
将指定附加到浏览器window对象上的库的变量名称 例如 a 库将通过 window.My.a 使用 例如 b 库将通过 window.My.a 使用
preconstruct dev是 Preconstruct 中的一个命令,它可以让你导入你的包, 但不需要实时将包的源文件编译到dist目录供其他包导入
把它添加到安装后脚本中,以便yarn在安装包后运行它 在仓库根目录的
package.json
添加脚本preconstruct-demo/package.json
"scripts": { "postinstall": "preconstruct dev", }
添加 Babel,以便我们在编写代码时可以使用现代功能,但消费者在使用它时不会遇到问题
在仓库根目录执行
yarn add -W @babel/core @babel/preset-env
babel.config.js
babel.config.js
module.exports = { presets: ["@babel/preset-env"], };
构建包
preconstruct build
在仓库根目录
package.json
添加脚本"scripts": { "build":"preconstruct build" }
在仓库根目录运行
yarn build
将在 a,b包目录分别构建出包
可以将单个包中的功能模块单独导出,消费者可以为此做摇树优化,去除未使用的功能
注意:禁止在
.npmignore
中排除dist
目录,否则会引发错误error @xxx/xxx the entrypoint func isn't included in the published files for this package, please add it to the files field in the package's package.json
https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package
为 a 包添加 func 功能模块
packages/a/src/func.js
export default function (){ console.log('a.func') }
在a包的默认导出文件中使用并导出 func 功能
packages/a/src/index.js
import func from "./func"; func(); export { func }; export default function () { console.log("a"); }
在 a 包 的
package.json
添加多入口配置packages/a/package.json
entrypoints
文件后缀需与src目录文件后缀保持一致"preconstruct": { "entrypoints": [ "index.js", "func.js" ] }
修复func 按提示输入把func附加到window对象的上的变量名称 [例如
My.a.func
]yarn fix
这将自动创建
packages/a/func/package.json
{ "main": "dist/my-a-func.cjs.js", "module": "dist/my-a-func.esm.js", "umd:main": "dist/my-a-func.umd.min.js", "preconstruct": { "umdName": "My.a.func" } }
将 a 包作为依赖加入b包 如果包未发布必须使用未发布的版本号
packages/b/package.json
添加依赖"dependencies": { "@my/a": "1.0.0" }
在b包目录下安装依赖
cd packages/b yarn
在 b 包引入本地a包并使用
import a, { func } from "@my/a"; a(); func(); export default function () { console.log("b"); }
由于a包使用了
My.a
umd名称,由b包引入a包,故需要指定my 和 a 在 umd模式下的window挂载变量名称 按提示输入 名称即可,例如My.a
My
添加 Manypkg 以帮助验证您的依赖项 从项目根目录运行以下命令
yarn add @manypkg/cli -W
yarn manypkg check
yarn manypkg fix
添加脚本
"scripts": { "check": "manypkg check", "fix:manypkg": "manypkg fix" }
在仓库根目录安装 changesets
yarn add @changesets/cli -W
设置 changesets
yarn changeset init
这将添加一个.changeset包含您的变更集配置
更改:.changeset/config.json 的"access": "restricted"为"access": "public"(假设您想在 npm 上公开发布您的包,如果您希望它们私下发布,请不要这样做)
添加变更集 选择更改的包、更改的 ( semver )类型以及更改的描述
注意:由于types包只包含类型定义,不会监测到改动,需要在每次发包的时候修改index.ts的console方法出发该包变更[或者修改readme.md]
yarn changeset add
版本的格式
major.minor.patch
主版本号.次版本号.修补版本号 patch:修复bug,兼容老版本 minor:新增功能,兼容老版本 major:新的架构调整,不兼容老版本“消耗”变更集 它将消耗并巧妙地组合所有存在的变更集 根据提示输入新的递增的版本号
yarn changeset version
登陆npm 需要从邮箱查看一次性密码
npm adduser
发布包
yarn preconstruct build && yarn changeset publish
在仓库根目录
package.json
添加脚本"scripts": { "postinstall": "preconstruct dev", "build": "preconstruct build", "release:old": "preconstruct build && yarn publish:packages", "fix": "preconstruct fix", "check": "manypkg check", "fix:manypkg": "manypkg fix", "cadd": "changeset add", "version": "changeset version", "release": "preconstruct build && changeset publish" }
node packages/b/dist/my-b.cjs.js
输出
a.func a a.func
完成后源码
package.json
{ "name": "my", "version": "1.0.0", "private": true, "workspaces": [ "packages/*" ], "license": "MIT", "dependencies": { "@babel/core": "^7.16.5", "@babel/preset-env": "^7.16.5", "@preconstruct/cli": "^2.1.5" }, "preconstruct": { "packages": [ "packages/*" ], "globals": { "My": "My" } }, "scripts": { "postinstall": "preconstruct dev", "build": "preconstruct build", "release:old": "preconstruct build && yarn publish:packages", "fix": "preconstruct fix", "check": "manypkg check", "fix:manypkg": "manypkg fix", "cadd": "changeset add", "version": "changeset version", "release": "preconstruct build && changeset publish" } }
>babel.config.js
```js
module.exports = {
presets: ["@babel/preset-env"],
};
packages/a/package.json
{ "name": "@my/a", "version": "1.0.0", "main": "dist/my-a.cjs.js", "module": "dist/my-a.esm.js", "umd:main": "dist/my-a.umd.min.js", "license": "MIT", "preconstruct": { "umdName": "My.a", "entrypoints": [ "index.js", "func.js" ] } }
>packages/a/src/func.js
```js
export default function (){
console.log('a.func')
}
packages/a/src/index.js
import func from "./func"; func(); export { func }; export default function () { console.log("a"); }
>packages/a/func/package.json 自动生成
```JSON
{
"main": "dist/my-a-func.cjs.js",
"module": "dist/my-a-func.esm.js",
"umd:main": "dist/my-a-func.umd.min.js",
"preconstruct": {
"umdName": "My.a.func"
}
}
packages/b/package.json
{ "name": "@my/b", "version": "1.0.0", "main": "dist/my-b.cjs.js", "module": "dist/my-b.esm.js", "umd:main": "dist/my-b.umd.min.js", "license": "MIT", "preconstruct": { "umdName": "My.b" }, "dependencies": { "@my/a": "1.0.0" } }
packages/b/src/index.js
import a, { func } from "@my/a"; a(); func(); export default function () { console.log("b"); }
在仓库根目录下
yarn add typescript @babel/preset-typescript -W
babel.config.js
module.exports = { presets: ["@babel/preset-typescript", "@babel/preset-env"], };
仓库根目录添加公共配置
isolatedModules
必须为 true 因为 Preconstruct 使用 Babel 编译 TypeScript 包,所以建议设置isolatedModules编译器选项以确保您的 TypeScript 源可以使用 Babel 构建。 tsconfig.json{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "noImplicitAny":false, }, "exclude": ["node_modules"] }
>包a,b分别添加配置,继承公共配置
>packages/a/tsconfig.json
```JSON
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
// package-specific options
"esModuleInterop": true,
}
}
packages/b/tsconfig.json
{ "extends": "../../tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
// package-specific options
"esModuleInterop": true,
}
}
>各包所有源码改为 `ts` 后缀
## 更新 entrypoints 文件后缀为 ts
>packages/a/package.json
```JSON
{
"name": "@my/a",
"version": "1.0.0",
"main": "dist/my-a.cjs.js",
"module": "dist/my-a.esm.js",
"umd:main": "dist/my-a.umd.min.js",
"license": "MIT",
"preconstruct": {
"umdName": "My.a",
"entrypoints": [
"index.ts",
"func.ts"
]
}
}
tsx
安装 @babel/preset-react 在仓库根目录下
yarn add @babel/preset-react -W
babel.config.js
module.exports = { presets: ['@babel/preset-react', '@babel/preset-typescript', '@babel/preset-env'] }
tsx
index.tsx
tsconfig.json
compilerOptions.jsx="react-jsx"
react 项目 lint 规则参考 linthttps://github.com/WangShuXian6/blog/issues/132
以下包需要为每个 monorepo 子项目单独安装
yarn add @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-airbnb eslint-config-prettier eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-prettier eslint-plugin-react eslint-plugin-react-hooks husky lint-staged prettier stylelint stylelint-config-prettier stylelint-config-rational-order stylelint-config-standard stylelint-prettier -D
npx husky add .husky/pre-commit "npm run lint"
执行该命令后,会看到
.husky/
目录下新增了一个名为pre-commit
的shell脚本。 这样,在之后执行git commit
命令时会先触发pre-commit
这个脚本。pre-commit
脚本内容如下:#!/bin/sh . "$(dirname "$0")/_/husky.sh"
npm run lint
## 分别为子项目配置脚本
>在 子项目package 根结点添加脚本字段
```JSON
"scripts": {
"lint": "lint-staged"
},
"lint-staged": {
"src/**/*.{html,css,scss,less}": [
"stylelint 'src/**/*.{html,css,scss,less}' --fix",
"prettier --write"
],
"src/**/*.{ts,tsx}": [
"eslint 'src/**/*.{ts,tsx}' --fix",
"prettier --parser=typescript --write"
],
"src/**/*.{js,jsx}": [
"eslint 'src/**/*.{js,jsx}' --fix",
"prettier --write"
]
},
package.json
添加脚本 "scripts": {
"prepare": "husky install",
"lint": "yarn workspaces run lint",
},
prepare
为初始化husky
lint
为运行所有子项目lint
命令如果示例项目没有 lint 命令,可使用
"scripts": { "lint":"npm -v" },
在子项目根目录添加
index.d.ts
declare module '*.scss' { const content: { [key: string]: any } export = content }
declare module '*.css' { const content: { [key: string]: any } export = content }
declare module '*.less' { const content: { [key: string]: any } export = content }
declare module '*.sass' { const content: { [key: string]: any } export = content }
>子项目tsconfig包含该定义
>`tsconfig.json`
```JSON
"include": [ "index.d.ts"],
preconstruct