Customizing Changelog

By default, Changesets will use @changesets/cli/changelog to generate changelog. If the default changelog cannot meet the requirements, you can customize the generation of changelog.

Customizing Changelog Content

Changelog mainly includes the following two types of information:

  • Changelog written in the changeset.

  • Version change information of related packages in this version upgrade.

The custom logic mainly implements two functions, getReleaseLine and getDependencyReleaseLine, which are used to define the above two types of information, respectively.

getReleaseLine

Params

  • changeset
export type VersionType = 'major' | 'minor' | 'patch' | 'none';

export type Release = { name: string; type: VersionType };

export type Changeset = {
  id: string; // changeset id
  commit?: string; // changeset commit id
  summary: string; // changeset summary content
  releases: Array<Release>; // The name and type information of the current computed changeset upgrade package.
};
  • type

The upgraded version type corresponding to the current package, which is of type VersionType mentioned above.

Returns

Changelog content.

Default Implementation

The default processing logic of @changesets/cli/changelog is to split the summary information according to the newline \n, add - as the list header before the first line, and organize other content as the supplement of the first line below the list.

async function getReleaseLine(changeset, type) {
  const [firstLine, ...futureLines] = changeset.summary
    .split('\n')
    .map(l => l.trimRight());

  let returnVal = `- ${
    changeset.commit ? `${changeset.commit}: ` : ''
  }${firstLine}`;

  if (futureLines.length > 0) {
    returnVal += `\n${futureLines.map(l => `  ${l}`).join('\n')}`;
  }

  return returnVal;
}

getDependencyReleaseLine

Params

  • changesets

All associated changeset information, which is an array of getReleaseLine changeset types.

  • dependenciesUpdated
type ModCompWithPackage = {
  name: string; // Name of the dependent module
  type: VersionType; // Upgrade type of the dependent module
  oldVersion: string; // Current version of the dependent module
  newVersion: string; // New version of the dependent module
  changesets: string[]; // List of associated changeset ids
  packageJson: PackageJSON; // Complete package.json content of the dependent module
  dir: string; // Path (absolute path) of the dependent module
};

type DependenciesUpdated = ModCompWithPackage[];

Returns

Changelog content.

Default Implementation

By default, @changesets/cli/changelog will display the corresponding Updated dependencies + commit id information of the changesets as a list. Then, based on the dependenciesUpdated information, it will display the package name and new version of the corresponding dependency package as a child list item of the list.

async function getDependencyReleaseLine(changesets, dependenciesUpdated) {
  console.log('getDependencyReleaseLine', changesets, dependenciesUpdated);
  if (dependenciesUpdated.length === 0) return '';

  const changesetLinks = changesets.map(
    changeset =>
      `- Updated dependencies${
        changeset.commit ? ` [${changeset.commit}]` : ''
      }`,
  );

  const updatedDepenenciesList = dependenciesUpdated.map(
    dependency => `  - ${dependency.name}@${dependency.newVersion}`,
  );

  return [...changesetLinks, ...updatedDepenenciesList].join('\n');
}

It is displayed as follows:

- Updated dependencies [f0438ab]
- Updated dependencies [f0438ab]
  - module-3@2.0.0
  - module-1@0.2.0

Configuration

The changelog field in the changesets configuration file is used to mark the way to get changelog.

This configuration can be a string, directly declaring the module name or path of the changelog module.

This configuration also supports configuring arrays. The first element in the array is the module name or path of the changelog module, and the second element is the parameter value passed to the corresponding function, which will be passed as the third parameter of the getReleaseLine and getDependencyReleaseLine functions.

Configuring Relative Paths

If the changelog configuration is a relative path, it is a relative path under the .changesets directory.

For example, create the .changeset/my-changelog-config.js file and define the following content:

.changeset/my-changelog-config.js
async function getReleaseLine(changeset, type) {}

async function getDependencyReleaseLine(changesets, dependenciesUpdated) {}

module.exports = {
  getReleaseLine,
  getDependencyReleaseLine,
};

Configure changlog as ./my-changelog-config.js:

.changesets/config.json
{
  "changelog": "./my-changelog-config.js",
   ...
}

Using Modern.js Module

Customizing changelog can also be managed using the Modern.js Module to provide a common solution.

Use npx @modern-js/create@latest to create a Modern.js Module.

? Please select the type of project you want to create: Npm Module
? Please fill in the project name: custom-changelog
? Please select the programming language: TS
? Please select the package manager: pnpm

Implement Custom Content

src/index.ts
export async function getReleaseLine() {}

export async function getDependencyReleaseLine() {}

Publish the module to NPM

Install the module in the root directory of the target repository, such as custom-changelog.

Configure the changelog configuration of changesets as the package name.

.changesets/config.json
{
  "changelog": "custom-changelog",
   ...
}

Using Monorepo Sub-Project

If your current repository is Monorepo, you can directly manage it using NPM module sub-projects.

Run pnpm run new to create a NPM module sub-project

? Please select the type of project you want to create: Npm Module
? Please fill in the sub-project name: custom-changelog
? Please fill in the sub-project directory name: custom-changelog
? Please select the programming language: TS

Implement Custom Content

src/index.ts
export async function getReleaseLine() {}

export async function getDependencyReleaseLine() {}

Add the sub-project module dependency, such as custom-changelog, to the Monorepo root directory

package.json
{
  "devDependencies": {
    "custom-changelog": "workspace:*",
    ...
  }
}

Configure the changelog configuration of Changesets as the package name

.changesets/config.json
{
  "changelog": "custom-changelog",
   ...
}

After the module is published to NPM, it can still be used like a module type for other repositories.