Angular 6 CLI - >如何使构建构建项目+库

时间:2018-05-04 18:30:36

标签: angular angular-cli angular6

所以这个问题很基本,但我找不到。

我通过ng new my-project创建了一个新应用,然后是ng g library my-library。 然后我执行了命令ng build,但它只是构建我的应用程序,而不是我的库或我的e2e项目。这是因为在angular.json中,defaultProject设置为my-project。我可以将它更改为my-library,然后ng build将构建lib。

有没有办法让角度在一个ng-build中构建所有项目和库?

9 个答案:

答案 0 :(得分:11)

我刚刚在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

答案 1 :(得分:3)

目前没有支持的方法来开箱即用。 正如@oklymenk所建议的,你现在应该使用自定义脚本来链接所有这些构建命令。

同样是@Eutrepe共享的链接,你可以看到,每当你对库进行更改时,他们都计划摆脱这种重新构建的东西。

  

每次更改文件时运行ng build my-lib都很麻烦,需要时间。

     

一些类似的设置改为直接在tsconfig中添加源代码的路径。这样可以更快地查看应用中的更改。

     

但这样做有风险。当您这样做时,您的应用程序的构建系统也在构建库。但是您的库是使用与您的应用程序不同的构建系统构建的。

     

这两个构建系统可以构建略有不同的东西,或者支持完全不同的功能。

     

这会导致您发布的库与开发设置中的库行为不同的细微错误。

     

出于这个原因,我们决定谨慎行事,并建议使用安全的使用方法。

     

将来我们希望为构建库添加监视支持,以便更快地查看更改。

     

我们还计划为Angular CLI添加内部依赖性支持。这意味着Angular CLI会知道您的应用程序取决于您的库,并在应用程序需要时自动重建库。

Why do I need to build the library everytime I make changes?

答案 2 :(得分:0)

我找到并测试了这个:https://github.com/angular/angular-cli/wiki/stories-create-library

因此,ng build --prod应使用ng build my-lib --prod

答案 3 :(得分:0)

我创建了一个脚本,该脚本与angular.json放在同一文件夹中时,将拉入文件,遍历项目,并异步批量构建它们。

这是一个快速要点,您可以切换输出路径和异步构建的数量。我暂时不包括e2e,但是您可以删除对filteredProjects函数的引用,它也将作为项目运行在e2e上。将其作为npm运行脚本添加到package.json也很容易。到目前为止,它运行良好。

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);
    });
  }
});

答案 4 :(得分:0)

也许这对您有用:

使用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 :(得分:0)

ng-build已将您的库包含在main.js包中。无需分别构建每个库。

答案 6 :(得分:0)

据我所知,当前版本(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对其进行运行。

答案 7 :(得分:0)

与简单的node js一起使用,如下所示:

在〜App根目录中创建js文件(例如:build.js)。

然后在文件中放置以下代码。

var child_process = require('child_process');

console.log("building all packages...\n");

var files = GetProjectList();
var count = files.length;
var counter = 1;

files.forEach(item => 
{
    try 
    {
        console.log(`${counter++} of ${count} building ${item.fileName}...`);
        child_process.execSync(`ng b ${item.fileName}`);
        console.log(`${item.fileName} built successfully.\n`);
    } 
    catch (er) 
    {
        console.error(` Couldn't build ${item.fileName} .\n`);
    }
});



function GetProjectList()
{
    // enter list of projects here.
    var lst = [];
    lst.push({ fileName : 'project1' });
    lst.push({ fileName : 'project2' });
    lst.push({ fileName : 'project3' });
    //...
    return lst;
}

最后,使用node js命令运行文件。像这样:

node build.js             // `build.js` is name of your created file on above
  

请注意文件的unicode。 // build.js

运行良好。

我希望是有用的。

答案 8 :(得分:0)

"build-all": "for PROJ in lib1 lib ''; do ng build $PROJ --prod || break; done"
  • ''为循环提供了一个空字符串,用于构建顶级项目
  • 一旦库构建失败,|| break就会停止for循环

或者,如果以下情况起作用,则

  • 构建系统具有jq
  • 您的任何一个库都不相互依赖
    • 这盲目地建立在angular.json中的项目列表中
  • 为您的库使用范围限定的包
    • 你为什么不呢?!
    • 查看下一个项目符号的原因
  • 顶级项目没有范围
    • 通常我的顶层是一个演示项目,从未发布过,所以从未讨论过
    • 这样做的原因是jq总是在数组中首先循环返回@前缀的键

"build-all": "for PROJ in $(cat angular.json | jq -r '.projects | keys[]'); do ng build $PROJ --prod; done"

在某个时候,我想研究一下基于在每个项目中找到的package.json(一个或多个)的依赖树,并根据该树对要构建的项目进行排序。相对于从第一个建议中保留硬编码列表而言,这并不是一个高优先级:)