22

As you know, the "ng g library" approach helps us with the creation of libraries of reusable components. But what if I wanted those components to be compiled into web components... through the support of Angular Elements? Not only that but also that each component from the lib was to be compiled into its own folder or JS file. How to configure a dev environment that would allow me to achieve that?

For example:

If I create a Lib and add a custom component, I know that I can compile it, generating a series of folders, such as esm5, esm2015, fesm5, etc. Now, the question is: How can I add, let's say 30 custom components to my lib, and then when I compile, it will create a folder for each of them containing the Web Component version of them... as if Angular Elements went through my lib of components and generated the Web Components version of each of them.

Like this:

lib/
lib/custom/comp1
lib/custom/comp2
lib/custom/comp3
lib/custom/comp4

Turning into something similar to:

Dist/
Dist/custom/
Dist/custom/bundle
Dist/custom/esm5
Dist/custom/esm2015
Dist/custom/comp1_web_independend_component_version
Dist/custom/comp2_web_independend_component_version
Dist/custom/comp3_web_independend_component_version
Dist/custom/comp4_web_independend_component_version

The closest solution I found is this:

https://medium.com/@rahulsahay19/running-multiple-angular-elements-on-the-same-page-5949dac5523

I also requested for Angular CLI team to help with that:

https://github.com/angular/angular-cli/issues/13999

Fabio Nolasco
  • 7,122
  • 6
  • 35
  • 32
  • Have you reviewed this link? https://medium.com/@IMM9O/web-components-with-angular-d0205c9db08f – Marshal Mar 28 '19 at 12:26
  • Yes, I have, actually. In fact, I guess you could consider me experienced in both CLI and Elements as well. – Fabio Nolasco Mar 28 '19 at 13:42
  • I find the [solution](https://medium.com/@rahulsahay19/running-multiple-angular-elements-on-the-same-page-5949dac5523) you found quite promising. How's the out come? – hackape Apr 03 '19 at 15:39

1 Answers1

1

ng build internally use webpack to do the building. So this problem actually breaks down to two parts.

  1. Without ng eject, how to tap into the internal webpackConfig and customize it to our need.
  2. What does desired webpackConfig look like for this use case.

For part 1, there's a solution @angular-builders/custom-webpack out there. Basically it allow you to merge some extra field into the internal webpackConfig, and still use the offical "@angular-devkit/build-angular:browser" as builder.

Now for part 2, your use case is simply a multi-entry-multi-output build problem in webpack. The solution is quite straight forward.

const partialWebpackConfig = {
  entry: {
    'custom/comp1': '/path/to/src/lib/custom/comp1.ts',
    'custom/comp2': '/path/to/src/lib/custom/comp2.ts',
  },
  output: {
    path: path.resolve(__dirname, 'Dist'),
    filename: '[name].js'
  }
}

Below is a step-by-step instruction to setup this config.

  1. npm install @angular-builders/custom-webpack
  2. create a webpack.config.js in your project root:
const path = require('path');
module.exports = {
  entry: {
    'custom/comp1': path.resolve(__dirname, 'src/lib/custom/comp1.ts'),
    'custom/comp2': path.resolve(__dirname, 'src/lib/custom/comp2.ts')
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  }
}
  1. edit "architect.build" field in angular.json:
{
  // ...
  "architect": {
    "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
        "customWebpackConfig": {
          "path": "./webpack.config.js",
        },
        // ...
  1. run ng build, should see the result.

For advance usage, it's worth mentioning that @angular-builders/custom-webpack support exporting webpack config as a function to gain full control of the final webpackConfig used.

hackape
  • 18,643
  • 2
  • 29
  • 57
  • Hi hackape, thank you for your answer! I created a new project and followed your steps. However, the final results are not "web components". In fact, the Angular Elements part is not clear in your answer. In other words, the components compiled cannot be used as stand-alone components on a website without Angular. Here is the repo, in case you want to experiment with it: https://github.com/fabionolasco/stackoverflow-angular-elements – Fabio Nolasco Apr 04 '19 at 12:33
  • I'm not very experienced with angular, but I am experienced dealing with webpack problems. Can you point out what exactly is wrong with the compiled result? – hackape Apr 04 '19 at 12:51
  • The compiled results are not Web Components (W3C). Web Components do not need Angular to run. We can phrase it backward by saying that the compiled results are still Angular components. – Fabio Nolasco Apr 04 '19 at 14:10
  • What's the command to compile valid web components from your example repo? – hackape Apr 04 '19 at 14:30
  • If I get it right, the "Web Components" and the "Angular Components" compile results are built from same source code, so I assume some webpack processes are left out in current config. I'd like to see them side by side to identify the difference. So let's leave the entry/output issue aside for now, could you please guide me to the correct config/command to produce a correct Web Components result first? – hackape Apr 04 '19 at 14:34
  • You would need to check Angular Elements. That is the Angular tool that creates Web Components using Angular: https://angular.io/guide/elements – Fabio Nolasco Apr 04 '19 at 14:47
  • Well, did check. But man, your example repo config has no configuration related to Angular Elements at all. – hackape Apr 04 '19 at 15:25
  • No, it does not. I just replicated your steps. – Fabio Nolasco Apr 04 '19 at 15:27
  • If you're asking for a solution that can go through your NgComponents only codebase, and magically identify each NgComponent then automatically call `export const NgElement = createCustomElement(NgComponent, {injector})` for you, then I don't think it's gonna happen. `@angular/elements` got to appear in your source code somewhere. – hackape Apr 04 '19 at 15:41
  • Hmm, I take that back. On second thought, it's actually possible. With a custom webpack loader you can transform at compile time each entry level NgCompoent module and wrap them with `createCustomElement(NgComponent)` then re-export. – hackape Apr 04 '19 at 15:46
  • This way your codebase would be `@angular/elements` free, that piece of code is tucked away in a loader. – hackape Apr 04 '19 at 15:53
  • @FabioNolasco I didn't fully understand your question at first. Do I get it right now? Anything to add? – hackape Apr 04 '19 at 16:16
  • @FabioNolasco I sent a [github PR](https://github.com/fabionolasco/stackoverflow-angular-elements/pull/1) to you a month ago, have you checked? – hackape May 22 '19 at 15:36
  • Hi @hackape, thank you for your help! However, I don't think you fully understood. As I said at the description, I want to create components on the lib folder and compile them into individual web components (files). – Fabio Nolasco May 23 '19 at 00:09