与 Lerna 一起开发

Developing with Lerna

我在一个 10 人的团队中工作,我们刚刚开始使用 Lerna。但是当我们都在开发新功能并修复现有包时,我们发现了一些问题。

有时,有人不将更改推送到 master 分支,而是执行 lerna 发布,这样他们就可以安装该软件包的最新版本并在他们的项目中使用它。

这给我们所有人带来了麻烦,因为我们没有与包版本同步,并且 lerna 发现包中的更改是人们没有更新的,并迫使他们发布未更改的包(由他们)。 你有一些关于如何在尚未发布到 npm 的地方使用 Lerna 包 'in progress' 的技巧吗? 现在我们使用命令从本地文件安装它:

 npm install - save file:path_to_npm_package

为什么我发现这个不好?因为这样它不知道 lerna 的符号链接,我应该在我的项目中安装 lerna 包依赖的所有依赖项。

PS。使用lerna包的项目不是其他lerna包。

Sometimes it happens that someone don't push changes to master branch and they do lerna publish just so they can install the newest version of that package and use it in their project.

为防止这种情况发生,您可以使用发布脚本来确保:

  1. 不在叉子上
  2. master
  3. 已提交所有更改
  4. 有最新的远程更改
  5. 所有测试都通过

这应该可以防止您不同步,并确保发布的版本是干净的。

$ node scripts/prerelease.js && lerna publish

scripts/prerelease.js

const {promisify} = require('util');

const execa = require('execa');
const parse = require('git-url-parse');
const rimraf = promisify(require('rimraf'));
const Listr = require('listr');

const pkg = require('../package');

const tasks = new Listr([
    {
        task: () =>
            execa.stdout('git', ['remote', 'get-url', 'origin']).then((result) => {
                const pkgUrlParsed = parse(pkg.repository.url);
                const gitUrlParsed = parse(result);
                const pkgUrl = pkgUrlParsed.resource + pkgUrlParsed.pathname;
                const gitUrl = gitUrlParsed.resource + gitUrlParsed.pathname;

                if (pkgUrl !== gitUrl) {
                    throw new Error(
                        'Cannot publish from a fork. Please clone source repository directly or ensure that the `package.json` file has a `repository.url` set.'
                    );
                }
            }),
        title: 'Not publishing from fork'
    },
    {
        task: () =>
            execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then((result) => {
                if (result !== 'master') {
                    throw new Error('Not on `master` branch. Please switch to `master` branch before publishing.');
                }
            }),
        title: 'On `master` branch'
    },
    {
        task: () =>
            execa.stdout('git', ['status', '--porcelain']).then((result) => {
                if (result !== '') {
                    throw new Error('Unclean working tree. Please commit or stash changes first.');
                }
            }),
        title: 'No uncommitted changes'
    },
    {
        task: () =>
            execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then((result) => {
                if (result !== '0') {
                    throw new Error('Remote has changes you do not have locally. Please pull changes.');
                }
            }),
        title: 'Have latest remote changes'
    },
    {
        task: () => rimraf('**/node_modules'),
        title: 'Removing `node_modules`'
    },
    {
        task: () => execa('yarn'),
        title: 'Installing dependencies using yarn'
    },
    {
        task: () => execa('yarn', ['bootstrap']),
        title: 'Bootstrap packages together with Lerna'
    },
    {
        enabled: () => pkg.scripts.test !== undefined,
        task: () => execa('yarn', ['test']),
        title: 'Running tests'
    },
    {
        enabled: () => pkg.scripts.build !== undefined,
        task: () => execa('yarn', ['build']),
        title: 'Building assets'
    }
]);

tasks
    .run()
    .then(() => console.log('Finished! `'))
    .catch((error) => {
        console.error(error);
        process.exit(1);
    });