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 будет знать, что ваше приложение зависит от вашей библиотеки и автоматически перестраивает библиотеку, когда приложение нуждается в ней.
Зачем мне создавать библиотеку каждый раз, когда я вношу изменения?
Ответ 3
Я нахожу и тестирую это: https://github.com/angular/angular-cli/wiki/stories-create-library
Итак, вместо ng build --prod
вы должны использовать ng build my-lib --prod
Ответ 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
.