Angular 6 CLI → как сделать проект сборки сборки + библиотеки

Итак, вопрос довольно простой, но я не могу его найти.

Я создал новое приложение через ng new my-project, а затем ng g library my-library. Затем я выполнил команду ng build, но это только создание моего приложения, а не моей библиотеки или моих проектов e2e. Это связано с тем, что в angular.json defaultProject установлен my-project. Я могу изменить его на мою библиотеку, а затем ng build построит lib.

Есть ли способ позволить angular собрать весь проект и библиотеки в одной ng-сборке?

Ответ 1

Я только что добавил script в package.json, чтобы не найти лучший способ.

  "scripts": {
    "build-all": "ng build lib1 && ng build lib2 && ng build",
    "build-all-prod": "ng build lib1 --prod && ng build lib2 --prod && ng build --prod"
  },

а затем

yarn run build-all

Ответ 2

В настоящее время нет поддерживаемого способа сделать это из коробки. Как было предложено @oklymenk, вы должны теперь пойти с пользовательским script, который свяжет все эти команды сборки.

Также ссылка, разделяемая с помощью @Eutrepe, вы можете видеть, что они планируют избавиться от этой вещи re build каждый раз, когда вы вносите изменения в свою библиотеку.

Запуск ng build my-lib при каждом изменении файла является назойливым и требует времени.

Некоторые аналогичные настройки вместо этого добавляют путь к исходному коду непосредственно внутри tsconfig. Это ускорит просмотр изменений в вашем приложении.

Но делать это рискованно. Когда вы это делаете, система сборки для вашего приложения также создает библиотеку. Но ваша библиотека построена с использованием другой системы сборки, чем ваше приложение.

Эти две системы сборки могут создавать вещи немного иначе или поддерживать совершенно разные функции.

Это приводит к тонким ошибкам, когда ваша опубликованная библиотека ведет себя не так, как в настройках вашей разработки.

По этой причине мы решили ошибиться на стороне осторожности и сделать рекомендуемое использование безопасным.

В будущем мы хотим добавить поддержку часов для создания библиотек, чтобы быстрее видеть изменения.

Мы также планируем добавить внутреннюю поддержку зависимостей в CLI Angular. Это означает, что Angular CLI будет знать, что ваше приложение зависит от вашей библиотеки и автоматически перестраивает библиотеку, когда приложение нуждается в ней.

Зачем мне создавать библиотеку каждый раз, когда я вношу изменения?

Ответ 4

Может быть, это работает для вас:

Соберите библиотеку с помощью ng build --prod --project=your-library, затем в ваших зависимостях package.json:

"example-ng6-lib": "file:../example-ng6-lib/dist/example-ng6-lib/example-ng6-lib-0.0.1.tgz",

Затем ng build --prod ваш корневой проект.

Пример взят здесь: https://blog.angularindepth.com/creating-a-library-in-angular-6-part-2-6e2bc1e14121

Ответ 5

Я создал скрипт, который, будучи помещенным в ту же папку, что и angular.json, будет извлекать файл, перебирать проекты и асинхронно angular.json их в пакеты.

Здесь краткий обзор, вы можете переключать выходной путь и количество асинхронных сборок. Я исключил E2E на данный момент, но вы можете удалить ссылку на filteredProjects функцию, и она будет работать для e2e как проекты. Также было бы легко добавить это в package.json как скрипт запуска npm. Пока это работает хорошо.

https://gist.github.com/bmarti44/f6b8d3d7b331cd79305ca8f45eb8997b

const fs = require('fs'),
  spawn = require('child_process').spawn,
  // Custom output path.
  outputPath = '/nba-angular',
  // Number of projects to build asynchronously.
  batch = 3;

let ngCli;

function buildProject(project) {
  return new Promise((resolve, reject) => {
    let child = spawn('ng', ['build', '--project', project, '--prod', '--extract-licenses', '--build-optimizer', '--output-path=${outputPath}/dist/' + project]);

    child.stdout.on('data', (data) => {
      console.log(data.toString());
    });

    child.stderr.on('data', (data) => {
      process.stdout.write('.');
    });

    child.on('close', (code) => {
      if (code === 0) {
        resolve(code);
      } else {
        reject(code);
      }
    });
  })
}

function filterProjects(projects) {
  return Object.keys(projects).filter(project => project.indexOf('e2e') === -1);
}

function batchProjects(projects) {
  let currentBatch = 0,
    i,
    batches = {};

  for (i = 0; i < projects.length; i += 1) {
    if ((i) % batch === 0) {
      currentBatch += 1;
    }
    if (typeof (batches['batch' + currentBatch]) === 'undefined') {
      batches['batch' + currentBatch] = [];
    }

    batches['batch' + currentBatch].push(projects[i]);
  }
  return batches;
}

fs.readFile('angular.json', 'utf8', async (err, data) => {
  let batches = {},
    batchesArray = [],
    i;

  if (err) {
    throw err;
  }

  ngCli = JSON.parse(data);

  batches = batchProjects(filterProjects(ngCli.projects));
  batchesArray = Object.keys(batches);

  for (i = 0; i < batchesArray.length; i += 1) {
    let promises = [];

    batches[batchesArray[i]].forEach((project) => {
      promises.push(buildProject(project));
    });

    console.log('Building projects ' + batches[batchesArray[i]].join(','));

    await Promise.all(promises).then(statusCode => {
      console.log('Projects ' + batches[batchesArray[i]].join(',') + ' built successfully!');
      if (i + 1 === batchesArray.length) {
        process.exit(0);
      }
    }, (reject) => {
      console.log(reject);
      process.exit(1);
    });
  }
});

Ответ 6

ng-build уже включает ваши библиотеки в пакет main.js. Не нужно отдельно строить каждую библиотеку.

Ответ 7

Насколько я знаю, в текущей версии нет встроенного способа сделать это (Angular 8).
Возможно, можно будет использовать новый builders, но я пока не очень разбираюсь в них.
Вместо этого я создал сценарий, который читает файл angular.json и определяет все проекты application и все configuration.
Затем он выполняет ng build для каждого проекта и конфигурации.
Кроме того, он соберет все неудачные сборки и в конце зарегистрирует их на консоли.
Этот скрипт выглядит следующим образом:

import { ProjectType, WorkspaceSchema } from "@schematics/angular/utility/workspace-models";
import { execSync } from "child_process";
import { readFileSync } from "fs";

interface ExecParams {
  project: string;
  config: string;
}

interface ExecError extends ExecParams {
  message: string;
}

function buildAll() {
  const json: WorkspaceSchema = JSON.parse(readFileSync("./angular.json").toString());
  const errors: ExecError[] = Object.keys(json.projects)
    // Filter application-projects
    .filter(name => json.projects[name].projectType === ProjectType.Application)
    // Determine parameters needed for the build command
    .reduce<ExecParams[]>((arr, project) => {
      const proj = json.projects[project];
      let build = proj.architect && proj.architect.build;
      if (build) {
        arr = arr.concat(...Object.keys(build.configurations || {})
          .map(config => ({ project, config }))
        );
      }
      return arr;
    }, [])
    // Execute 'ng build' and collect errors.
    .reduce<ExecError[]>((err, exec) => {
      try {
        console.log('Building ${exec.project} (${exec.config}):');
        execSync('ng build --prod --project ${exec.project} --configuration ${exec.config}', {stdio: "inherit"});
      }
      catch (error) {
        err.push({
          project: exec.project,
          config: exec.config,
          message: error.message
        });
      }
      console.log("\n");
      return err;
    }, []);

  // Conditionally log errors
  if (errors.length === 0)
    console.log("Completed");
  else {
    console.log("\n");
    errors.forEach(error => {
      console.error('Building ${error.project} (${error.config}) failed:\n\t${error.message}');
    });
  }
}

buildAll();

Вы можете скомпилировать его, используя tsc, а затем запустить его с NodeJs.