Skip to content

Commit

Permalink
Merge pull request #3491 from storybooks/new-angular-cli-integration
Browse files Browse the repository at this point in the history
angular-cli 6 (with webpack 4) compatibility
  • Loading branch information
igor-dv authored Jun 7, 2018
2 parents a4c7365 + 9b13bfc commit b4d4704
Show file tree
Hide file tree
Showing 31 changed files with 979 additions and 1,070 deletions.
13 changes: 7 additions & 6 deletions app/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@
"zone.js": "^0.8.26"
},
"peerDependencies": {
"@angular/common": ">=4.0.0",
"@angular/compiler": ">=4.0.0",
"@angular/core": ">=4.0.0",
"@angular/forms": ">=4.0.0",
"@angular/platform-browser": ">=4.0.0",
"@angular/platform-browser-dynamic": ">=4.0.0"
"@angular-devkit/core": "^0.6.1",
"@angular/common": ">=6.0.0",
"@angular/compiler": ">=6.0.0",
"@angular/core": ">=6.0.0",
"@angular/forms": ">=6.0.0",
"@angular/platform-browser": ">=6.0.0",
"@angular/platform-browser-dynamic": ">=6.0.0"
}
}
64 changes: 39 additions & 25 deletions app/angular/src/server/angular-cli_config.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,63 @@
import path from 'path';
import fs from 'fs';
import { logger } from '@storybook/node-logger';
import { isBuildAngularInstalled, normalizeAssetPatterns } from './angular-cli_utils';

function isAngularCliInstalled() {
try {
require.resolve('@angular/cli');
return true;
} catch (e) {
return false;
}
}
export function getAngularCliWebpackConfigOptions(dirToSearch) {
const fname = path.join(dirToSearch, 'angular.json');

export function getAngularCliWebpackConfigOptions(dirToSearch, appIndex = 0) {
const fname = path.join(dirToSearch, '.angular-cli.json');
if (!fs.existsSync(fname)) {
return null;
}
const cliConfig = JSON.parse(fs.readFileSync(fname, 'utf8'));
if (!cliConfig.apps || !cliConfig.apps.length) {
throw new Error('.angular-cli.json must have apps entry.');

const angularJson = JSON.parse(fs.readFileSync(fname, 'utf8'));
const { projects, defaultProject } = angularJson;

if (!projects || !Object.keys(projects).length) {
throw new Error('angular.json must have projects entry.');
}

let project = projects[Object.keys(projects)[0]];

if (defaultProject) {
project = projects[defaultProject];
}
const appConfig = cliConfig.apps[appIndex];

const cliWebpackConfigOptions = {
const { options: projectOptions } = project.architect.build;

const normalizedAssets = normalizeAssetPatterns(
projectOptions.assets,
dirToSearch,
project.sourceRoot
);

return {
root: project.root,
projectRoot: dirToSearch,
appConfig,
supportES2015: false,
tsConfig: {
options: {},
fileNames: [],
errors: [],
},
tsConfigPath: path.resolve(dirToSearch, 'src/tsconfig.app.json'),
buildOptions: {
outputPath: 'outputPath', // It's dummy value to avoid to Angular CLI's error
...projectOptions,
assets: normalizedAssets,
},
supportES2015: false,
};

return cliWebpackConfigOptions;
}

export function applyAngularCliWebpackConfig(baseConfig, cliWebpackConfigOptions) {
if (!cliWebpackConfigOptions) return baseConfig;

if (!isAngularCliInstalled()) {
logger.info('=> Using base config because @angular/cli is not installed.');
if (!isBuildAngularInstalled()) {
logger.info('=> Using base config because @angular-devkit/build-angular is not installed.');
return baseConfig;
}

// eslint-disable-next-line global-require, import/no-extraneous-dependencies
const ngcliConfigFactory = require('@angular/cli/models/webpack-configs');
const ngcliConfigFactory = require('@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs');

let cliCommonConfig;
let cliStyleConfig;
Expand All @@ -56,8 +70,8 @@ export function applyAngularCliWebpackConfig(baseConfig, cliWebpackConfigOptions
}
logger.info('=> Get angular-cli webpack config.');

// Don't use storybooks .css/.scss rules because we have to use rules created by @angualr/cli
// because @angular/cli created rules have include/exclude for global style files.
// Don't use storybooks .css/.scss rules because we have to use rules created by @angular-devkit/build-angular
// because @angular-devkit/build-angular created rules have include/exclude for global style files.
const rulesExcludingStyles = baseConfig.module.rules.filter(
rule =>
!rule.test || (rule.test.toString() !== '/\\.css$/' && rule.test.toString() !== '/\\.scss$/')
Expand Down
55 changes: 55 additions & 0 deletions app/angular/src/server/angular-cli_utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import fs from 'fs';
import { basename, dirname, normalize, relative, resolve } from '@angular-devkit/core';

function isDirectory(assetPath) {
try {
return fs.statSync(assetPath).isDirectory();
} catch (e) {
return false;
}
}

function getAssetsParts(resolvedAssetPath, assetPath) {
if (isDirectory(resolvedAssetPath)) {
return {
glob: '**/*', // Folders get a recursive star glob.
input: assetPath, // Input directory is their original path.
};
}

return {
glob: basename(assetPath), // Files are their own glob.
input: dirname(assetPath), // Input directory is their original dirname.
};
}

export function isBuildAngularInstalled() {
try {
require.resolve('@angular-devkit/build-angular');
return true;
} catch (e) {
return false;
}
}

export function normalizeAssetPatterns(assetPatterns, dirToSearch, sourceRoot) {
if (!assetPatterns || !assetPatterns.length) {
return [];
}

return assetPatterns.map(assetPattern => {
const assetPath = normalize(assetPattern);
const resolvedSourceRoot = resolve(dirToSearch, sourceRoot);
const resolvedAssetPath = resolve(dirToSearch, assetPath);
const parts = getAssetsParts(resolvedAssetPath, assetPath);

// Output directory for both is the relative path from source root to input.
const output = relative(resolvedSourceRoot, resolve(dirToSearch, parts.input));

// Return the asset pattern in object format.
return {
...parts,
output,
};
});
}
4 changes: 4 additions & 0 deletions app/angular/src/server/wrapInitialConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export default (config, configDir) => ({
require.resolve('angular2-template-loader'),
],
},
{
test: /[/\\]@angular[/\\]core[/\\].+\.js$/,
parser: { system: true },
},
{
test: /\.html$/,
loader: 'raw-loader',
Expand Down
2 changes: 1 addition & 1 deletion app/react-native/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ First follow the instructions [here](https://github.com/ds300/react-native-types
Now update your storybook `package.json` script to the following

"scripts": {
"storybook": "storybook start -p 7007 --metro-config $PWD/rn-cli.config.js"
"storybook": "storybook --metro-config $PWD/rn-cli.config.js"
}

The metro bundler requires an absolute path to the config. The above setup assumes the `rn-cli.config.js` is in the root of your project or next to your `package.json`
Expand Down
60 changes: 0 additions & 60 deletions examples/angular-cli/.angular-cli.json

This file was deleted.

9 changes: 1 addition & 8 deletions examples/angular-cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,10 @@
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
yarn-error.log

# e2e
/e2e/*.js
/e2e/*.map

# System Files
.DS_Store
Thumbs.db

/jest_0
.jest-test-results.json
7 changes: 3 additions & 4 deletions examples/angular-cli/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Ng5test
# AngularCli

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.3.0.
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.0.

## Development server

Expand All @@ -12,7 +12,7 @@ Run `ng generate component component-name` to generate a new component. You can

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.

## Running unit tests

Expand All @@ -21,7 +21,6 @@ Run `ng test` to execute the unit tests via [Jest](https://facebook.github.io/je
## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Before running the tests make sure you are serving the app via `ng serve`.

## Further help

Expand Down
Loading

0 comments on commit b4d4704

Please sign in to comment.