highlight: github
theme: juejin
pnpm workspace practice
The project architecture adopts pnpm workspace + changelog + husky
github example address 1 – Vue + Nest full stack template
github example address 2 – Vue + TS front-end template
pnpm
Initialize the project and modify private:true in the package.json file generated by the car to prevent root directory publishing.
pnpm init
Create pnpm-workspace.yaml
file in the root directory
Configure the monorepo workspace of pnpm. For example, here we configure blog as the main blog, play for testing, and packages under packages can have theme packages, component packages, tool packages, etc.
Note here that if it is a multi-project mode, the name in the root directory package.json is the project name (set it according to what you want)
The name in the package.json file in the sub-project needs to be @ + the name in the root directory package.json + / + the sub-project name
packages: - 'packages/*' - 'doc'
Specify the running version of Node and pnpm
{<!-- --> "engines": {<!-- --> "node": ">=20", "pnpm": ">=8" } }
Next we switch to the packages directory and create subprojects
For example, I want to create a vitepress project here
cddoc pnpm dlx vitepress init
Create a vue project and use
pnpm create vite
Only pnpm is allowed
If you don’t want others to use package managers such as yarn and npm, just add the following command to the package.json file
{<!-- --> "scripts": {<!-- --> "preinstall": "npx only-allow pnpm" } }
As long as someone uses other package managers to install dependencies, an error will be reported!
Add dependencies
- Global dependencies
pnpm add xxx -D -W # or pnpm add xxx -Dw
-W: workspace-root installs dependencies into global node_modules
-D: development dependencies
Dependency difference:
dependencies: production dependencies
devDependencies: development dependencies
peerDependencies: host dependencies (running main dependencies), specify the dependencies that need to be installed when using the current module package
- local dependency
# The path is in the directory where dependencies need to be introduced pnpm add xxx -D # In the root directory @xxx/xxx is the name of the subproject pnpm add xxx -F @xxx/xxx
Global startup command
The pnpm -C
command can execute multiple commands in sequence, which allows us to run the script commands in package.json
in the root directory
e.g.:
{<!-- --> "scripts":{<!-- --> "dev:docs": "pnpm -C ./packages/doc docs:dev", } }
ESLint & amp; & amp; Prettier
Introduce dependencies
pnpm add eslint prettier -Dw #Initialize eslint configuration pnpm eslint --init # Other dependencies pnpm add -Dw @typescript-eslint/parser eslint-plugin-vue @typescript-eslint/eslint-plugin # Resolve conflicts pnpm add eslint-config-prettier eslint-plugin-prettier -Dw
resolve conflicts
.eslintrc.cjs
{<!-- --> extends: [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:vue/vue3-essential", //Put prettier at the end to give it a lower priority than eslint "plugin:prettier/recommended", ], }
Add check command
{<!-- --> "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx", "format": "prettier --write ./**/*.{vue,ts,tsx,js,jsx,css,less,scss,json,md}", }
Internal package references
husky + lint-staged code pre-check
Introduce dependencies
pnpm add husky lint-staged -Dw
Add script commands to json
{<!-- --> "prepare": "husky install" }
Run the command to create a pre-commit hook
#Manual run pnpm prepare #Add pre-commit hook npx husky add .husky/pre-commit "npx --no-install lint-staged"
pre-commit
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # This was added by myself echo "--------- Code pre-check ---------" npx --no-install lint-staged
To configure lint-staged, add the following configuration information in package.json
//Same level as scripts {<!-- --> "lint-staged": {<!-- --> "*.{js,vue,ts,jsx,tsx}": [ "prettier --write", "eslint --fix" ], "*.{html,css,less,scss,md}": [ "prettier --write" ] }, }
Submission specifications
Introduce dependencies
pnpm add @commitlint/cli @commitlint/config-conventional cz-git -Dw
Add command
{<!-- --> "type":"module", "scripts": {<!-- --> "cz": "git cz", }, "config": {<!-- --> "commitizen": {<!-- --> "path": "node_modules/cz-git" } }, }
We use it to limit submission information that does not comply with the specification. Create a commitlint.config.js file in the root directory – if an error is reported later, you need to change the file to .cjs
and also modify some contents.
// commitlint.config.js /** @type {import('cz-git').UserConfig} */ export default {<!-- --> extends: ["@commitlint/config-conventional"], rules: {<!-- --> "type-enum": [ 2, "always", [ "feat", "fix", "docs", "style", "refactor", "test", "build", "chore", "perf", "ci", "revert", ], ], "type-case": [2, "always", "lower-case"], "type-empty": [2, "never"], "subject-full-stop": [2, "never", "."], "header-max-length": [2, "always", 100], "subject-case": [ 2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"], ], }, prompt: {<!-- --> useEmoji: true, allowCustomIssuePrefix: true, allowEmptyIssuePrefix: true, confirmColorize: true, messages: {<!-- --> type: "Select the type you want to submit:", scope: "Select a submission scope (optional):", customScope: "Please enter a custom submission scope:", subject: "Fill in a short and concise description of the change:\ ", body: "Fill in a more detailed description of the change (optional). Use '|' for line breaks:\ ", breaking: "List non-compatible breaking changes (optional). Use '|' for line breaks:\ ", footerPrefixesSelect: "Select the associated issue prefix (optional):", customFooterPrefix: "Enter custom issue prefix:", footer: "List related issues (optional) For example: #31, #I3244:\ ", confirmCommit: "Do you want to submit or modify the commit?", }, types: [ {<!-- --> value: "feat", emoji: "?", name: "feat: new feature | A new feature", }, {<!-- --> value: "fix", name: "fix: A bug fix" }, {<!-- --> value: "docs", emoji: "", name: "docs: Documentation updates | Documentation only changes", }, {<!-- --> value: "style", emoji: "", name: "style: code format | Changes that do not affect the meaning of the code", }, {<!-- --> value: "refactor", emoji: "", name: "refactor: code refactoring | A code change that neither fixes a bug nor adds a feature", }, {<!-- --> value: "perf", emoji: "", name: "perf: performance improvement | A code change that improves performance", }, {<!-- --> value: "test", emoji: "", name: "test: test related | Adding missing tests or correcting existing tests", }, {<!-- --> value: "build", emoji: "", name: "build: Build related | Changes that affect the build system or external dependencies", }, {<!-- --> value: "ci", emoji: "", name: "ci: Continuous Integration | Changes to our CI configuration files and scripts", }, {<!-- --> value: "revert", emoji: "", name: "revert: rollback code | Revert to a commit", }, {<!-- --> value: "chore", emoji: "", name: "chore: Other changes | Other changes that do not modify src or test files", }, ], }, };
Use husky to generate commit-msg file and verify submission information
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
commit-msg
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # Added by myself echo "--------- Perform commit-msg verification ---------" npx --no-install commitlint --edit $1
changeset
Introduce dependencies and initialize
# -D development dependencies # -w public dependencies pnpm add -Dw @changesets/cli # initialization pnpm changeset init
After initialization, a .changeset folder will be generated in the root directory
Among them config.json is used as the default changeset configuration file
- changelog: changelog generation method
- commit: Don’t let changeset do git add for us when publishing
- linked: Configure which packages should share versions
- access: public and private security settings, restricted is recommended for intranet, public is used for open source
- baseBranch: the main branch of the project
- updateInternalDependencies: The measurement unit (magnitude) that ensures that the package that a certain package depends on undergoes an upgrade, and that the package also undergoes a version upgrade.
- ignore: packages that do not need to change version
- ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH: Every time the version changes, there must be no reason to patch to upgrade the versions of the packages that depend on it to prevent major priority non-update problems.
changeset common commands and instructions
# Use changeset to record version modifications npx changeset add # Use changeset version to submit version modifications npx changeset version # Use changeset publish to send packages npx changeset publish
The version number generally has three parts, separated by .
, like X.Y.Z
, where
- X: major version number, incompatible major changes, major
- Y: minor version number, functional changes, minor
- Z: revision number, bug fix, patch
changeset version Submit version changes
.npmrc
pnpm commonly used
strict-peer-dependencies=false shell-emulator=true auto-install-peers=false