Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Angular 6 Builder #3995

Closed
2 of 24 tasks
jogelin opened this issue Aug 10, 2018 · 14 comments
Closed
2 of 24 tasks

[Feature] Angular 6 Builder #3995

jogelin opened this issue Aug 10, 2018 · 14 comments

Comments

@jogelin
Copy link

jogelin commented Aug 10, 2018

I think it could be useful to have an Angular-Cli builder provided by storybook.

Then in angular.json, we could just do:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,  
  "projects": {
    "storybook": {
      "root": "projects/storybook",
      "sourceRoot": "projects/storybook/src",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@storybook/storybook-builder:build",
          "options": {
            "outputPath": "dist/projects/.out",
            "tsConfig": "projects/storybook/tsconfig.app.json",
            "assets": [
	      "projects/storybook/favicon.ico",
              "projects/storybook/assets"
	    ],
            "styles": [
              "libs/core/theme.scss",
	      "projects/storybook/styles.scss"
            ]
          }
        },
	"serve": {
          "builder": "@storybook/storybook-builder:dev-server",
          "options": {
            "browserTarget": "storybook:build"
          }
        },
	"test": {
          "builder": "@storybook/storybook-builder:test",
          "options": {
            "browserTarget": "storybook:build",
	    "tsConfig": "projects/storybook/tsconfig.spec.json",
          }
        }
      }
    }
  }
}	

Improvements:

More infos: Customizing Angular CLI 6 build — an alternative to ng eject

Tasks to get there:

  • Create schema skeleton for builder @storybook/angular:start: tsConfig, port, host, staticDirs, configDir, quiet
  • Create schema skeleton for builder @storybook/angular:build: tsConfig, host, staticDirs, outputDir, configDir, watch
  • IN PROGRESS Start with @storybook/angular:build and include the storybook/app/angular/server functionalities
    • use tsConfig option to get typescript configurations instead of default tsconfig in the configDir
    • Wrap initial webpack configs (ts-loader, angular2-template-loader, raw-loader, sass-loader)
    • Wrap default webpack configs from builder options:
      • get @angular/cli webpack configs
      • get styles and add to webpack configs
      • get assets and add to webpack configs
    • Wrap basic webpack configs (same as default webpack configs)
  • Extend @storybook/angular:build to create the builder @storybook/angular:start
  • Create schema skeleton for builder @storybook/angular:test to run tests in storybook
  • include the builders in the storybook repository
    • replace storybook/app/angular/server by the builder
    • adapt storybook/examples/angular-cli
      • simple an multiple packages examples
      • jest test using @angular-builders/jest
    • adapt storybook/lib/cli/generators/ANGULAR to inject storybook project with builders in angular.json

Later improvments:

  • Include storybook/app/angular/client functionalities (!!! don't know yet the faisability)
    • try to use builder option to configure storybook instead of the config.ts file:
      • Load stories from tsconfig instead of a method in conf
      • List of addons could be speicy in a array in option addons in the builder spec
      • the custom webpack config should be specify by a path option webpackConfig in the builder spec
      • ...
@igor-dv
Copy link
Member

igor-dv commented Aug 12, 2018

Interesting suggestion. It can definitely be a package in the storybook org. Would you like to PR this?

@jogelin
Copy link
Author

jogelin commented Aug 16, 2018

@igor-dv I started to have a look but to be honest, I am not an expert of storybook and I just started to understand how @storybook/angular is working with a client and a server. I am not at all an expert in webpack ;).

I'll try to make a small repo with a builder that could cover what the @storybook/angular/server is doing today. Then I'll probably need helps to integrate that in the storybook repository.

@igor-dv
Copy link
Member

igor-dv commented Aug 16, 2018

Sure, LMK if you need something, also we have a slack

@jogelin
Copy link
Author

jogelin commented Aug 25, 2018

I didn't really progress on the builders...I don't have a lot of time and not a 'builder/webpack' guy so I have some technicals issues...

But I had time to analyze and think about the list of tasks needed to make the builders, so I updated the ticket description. If anyone has any other ideas, do not hesitate to tell me and I will add them.

@jogelin
Copy link
Author

jogelin commented Aug 25, 2018

@igor-dv
I simply made a builder that reflect the existing code in storybook/app/angular/serve:

import { Builder, BuilderConfiguration, BuilderContext, BuildEvent } from '@angular-devkit/architect';
import { from, Observable, of } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { StartStorybookSchema } from './schema';
import { buildDev } from '@storybook/core/server';

import storyBookOptions from '@storybook/angular/dist/server/options';

export default class StartStorybookBuilder implements Builder<StartStorybookSchema> {
  constructor(private context: BuilderContext) {}

  run(builderConfig: BuilderConfiguration<Partial<StartStorybookSchema>>): Observable<BuildEvent> {
    console.log('OK');

    return of(null).pipe(
      tap(_ => buildDev(storyBookOptions)),
      map(() => ({ success: true }))
    );
  }
}

But when I run it I have this issue:

Cannot find module '@babel/plugin-proposal-class-properties'
Error: Cannot find module '@babel/plugin-proposal-class-properties'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.resolve (internal/module.js:18:19)
    at Object.<anonymous> (/mnt/c/Users/jo/dev/build-storybook/example/node_modules/@storybook/core/dist/server/config/babel.js:13:117)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)

Why do I need to add this dependency in my project ? Isn't a dependency provided by storybook ?

Another question for my info, what is the differences between wrapInitialConfig, wrapDefaultConfig and wrapBasicConfig ? Why storybook needs these 3 configurations ? Why don't we merge all configs in the initial ?

@igor-dv
Copy link
Member

igor-dv commented Aug 25, 2018

This issue was solved today https://github.com/storybooks/storybook/releases/tag/v4.0.0-alpha.18

@stale stale bot added the inactive label Sep 17, 2018
@storybookjs storybookjs deleted a comment from stale bot Sep 17, 2018
@stale stale bot removed the inactive label Sep 17, 2018
@igor-dv igor-dv added the todo label Sep 17, 2018
@jogelin
Copy link
Author

jogelin commented Sep 17, 2018

Small update to avoid deletion of the issue ;)

Repository of the POC: https://github.com/jogelin/storybook-builders

Next step: integrate in the storybook repository to see how could we build the builders and update the core that could match the builders "way"

@anoopsinghbayes
Copy link

Is this still on the roadmap ?

@Jordan-Hall
Copy link

Jordan-Hall commented Sep 16, 2019

For anyone that's looking for an Angular 6+ builder. They a PR which been placed for NX which contains a storybook builder. The builder is also cross platform so would work in mono-repo and micro frontends

nrwl/nx#1582

"storybook": {
          "builder": "@nrwl/storybook:storybook",
          "options": {
            "uiFramework": "@storybook/angular",
            "config": {
              "configFolder": "apps/rina-eas/.storybook"
            }
          }
        }

It has other config options such as the path to tsconfig etc. Will try and build it out more if you have suggestions

@cmurczek-it
Copy link

@igor-dv I have created such a builder as a standalone package, but if you're interested I'd be happy to convert it into a PR in this repo.
I've also created an Angular schematic to install the builder via ng add and generate stories (currently only CSF) along with components.
It works with Angular 10/Storybook 6, but should be backwards compatible to Angular 8 (when the builder API was released). Have a look at it here, try it, and let me know.

@shilman
Copy link
Member

shilman commented Oct 3, 2020

cc @Marklb @kroeder @gaetanmaisse what do you guys think?

@Marklb
Copy link
Member

Marklb commented Oct 3, 2020

I like the idea of providing a builder, since it fits more naturally with Angular's configuration. The main users I could see it benefiting are the ones with multiple projects that they want to have an independent storybook build for.

I can't think of a reason Storybook should add a builder for any of Angular's targets, such as build, serve, test, etc, because Storybook is not meant to replace their functionality. The exception may be a project that is only for Storybook and builds a single Storybook with all the projects stories, maybe a builder that outputs a build that is configured to compose all the individual projects with Storybooks using Storybook's Composition.

What I think would be useful is a storybook and build-storybook builder that could be added as their own targets. That way each project could configure Storybook without interfering with any Angular targets. I have never used a custom target myself, but from Angular's docs it looks like it's mainly just a matter of configuring it. Adding a target This issue may have already been considering this, but my interpretation was that this builder would be used in the build target.

I have never used Nx, but from the few repos I have looked at that use Nx, it looks like their schematics configure the projects with storybook and build-storybook targets like this.

I don't have anything to add to the target's configuration, that hasn't already been mentioned, but an example of what I would expect the angular.json configuration to look like with @storybook/storybook-builder:* builders would be the following:

{
  "projects": {
    "example-app": {
      "projectType": "application",
      "root": "projects/example-app",
      "sourceRoot": "projects/example-app/src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": { ... }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": { ... }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": { ... }
        },
        "storybook": {
          "builder": "@storybook/build-storybook:dev-server",
          "options": { ... }
        },
        "build-storybook": {
          "builder": "@storybook/build-storybook:build",
          "options": { ... }
        },
      }
    },
    "example-lib": {
      "projectType": "library",
      "root": "projects/example-lib",
      "sourceRoot": "projects/example-lib/src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": { ... }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": { ... }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": { ... }
        },
        "storybook": {
          "builder": "@storybook/build-storybook:dev-server",
          "options": { ... }
        },
        "build-storybook": {
          "builder": "@storybook/build-storybook:build",
          "options": { ... }
        },
      }
    },
    // I am still deciding if something like this one would even be worth it.
    "composed-sb-docs": {
      "projectType": "application",
      "root": "projects/composed-sb-docs",
      "sourceRoot": "projects/composed-sb-docs/src",
      "prefix": "app",
      "architect": {
        "storybook": {
          "builder": "@storybook/build-storybook:dev-server-composed",
          "options": { ... }
        },
        "build-storybook": {
          "builder": "@storybook/build-storybook:build-composed",
          "options": { ... }
        },
      }
    },
  },
  "schematics": {
    "@storybook/angular:application": { ... },
    "@storybook/angular:library": { ... }
  },
}

Even though this issue is about builders, I like the use of schematics in @cmurczek's package. I have some simple VSCode snippets for stories that I sometimes use to scaffold the minor boilerplate in story files, but I have considered building schematics for them eventually.

I almost always run a schematic to generate my component files and immediately create a *.stories.ts file after. For building the generator command I normally use a VSCode extension that lists the options and it would be nice to have an option to have the generator create the *.stories.ts or *.stories.mdx file at the same time.

Not that it would affect the implementation, this is the extension I was talking about when I said that I choose the schematic inputs from a list.
image

@cmurczek-it
Copy link

The builder I created actually uses a custom target rather than replacing one of Angular's targets. I considered serve, but then figured that there might be cases where serving the actual app would be beneficial (e.g. manual testing). The benefit of overriding an Angular target would be that it could be invoked like ng serve app, whereas custom targets need a little quirkier syntax like ng run app:storybook.

Contrary to @jogelin's approach, my implementation builds on the way Storybook is currently configured, i.e. via the main.js and preview.js files. From the Angular dev's point of view it would indeed be preferable to have the settings directly in the options of the builder rather than in files on disk (especially when there are multiple projects with Storybook in an Angular workspace). However, moving the configuration there would need considerable refactoring of the storybook core server. In addition to the configuration via the main and preview files and their processing, the server would need to provide an API that accepts the settings and passes them to the relevant functions. If you decided to switch to a builder, the server and builder could be gradually refactored under the hood to get there.

@shilman
Copy link
Member

shilman commented Jun 1, 2021

Yee-haw!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.3.0-beta.7 containing PR #15061 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed Jun 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants