If you are reporting a bug or requesting support, start here:
I want to use storybook with Angular 6. It turns out I have to use the 4.0.0 alpha branch to make it through (#3044 ). After I managed to make the story server run, I got another error Expected 'styles' to be an array of strings.
, which I have no idea how to get around.
I followed the instructions in https://storybook.js.org/basics/guide-angular/#docs-content but at the beginning the compilation failed:
node_modules/webpack/lib/DefinePlugin.js:42
compiler.hooks.compilation.tap(
^
TypeError: Cannot read property 'compilation' of undefined
Then I installed @storybook/[email protected]. I managed to run the server, but when I load my component, it shows
Expected 'styles' to be an array of strings.
Error: Expected 'styles' to be an array of strings.
at assertArrayOfStrings (http://localhost:9001/static/preview.bundle.js:8372:19)
at CompileMetadataResolver../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (http://localhost:9001/static/preview.bundle.js:17242:13)
at CompileMetadataResolver../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getEntryComponentMetadata (http://localhost:9001/static/preview.bundle.js:17887:28)
at http://localhost:9001/static/preview.bundle.js:17536:53
at Array.map (<anonymous>)
at CompileMetadataResolver../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (http://localhost:9001/static/preview.bundle.js:17536:18)
at JitCompiler../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (http://localhost:9001/static/preview.bundle.js:29551:51)
at JitCompiler../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (http://localhost:9001/static/preview.bundle.js:29532:36)
at JitCompiler../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync (http://localhost:9001/static/preview.bundle.js:29492:37)
at CompilerImpl../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync (http://localhost:9001/static/preview.bundle.js:54699:31)
This is an update for this issue.
In alpha.6, the aforementioned issues can be resolved by extending the webpack.config.json in .storybook directory:
note that the magic is the to-string-loader that adapt the css to what Angular 6 want.
const path = require("path");
module.exports = (baseConfig) => {
// Extend defaultConfig as you need.
// For example, add typescript loader:
baseConfig.module.rules.push({
test: [/\.stories\.tsx?$/, /index\.ts$/],
loaders: [
{
loader: require.resolve('@storybook/addon-storysource/loader'),
options: {
parser: 'typescript',
},
},
],
include: [path.resolve(__dirname, '../src')],
enforce: 'pre',
});
baseConfig.module.rules.push({
test: /\.css$/,
use: ['to-string-loader', 'css-loader']
});
return baseConfig;
};
After getting this config file, the error becomes to failed to load XXXX.html
. It seems like storybook still want to load the template page even though it has been bundled. To resolve this issue, add moduleId = module.id
to each of the @Component
in your Angular components.
I don't really like this workaround. Thankfully, the failed to load html
problem seems to be fixed in alpha.7. But still the css files need the to-string-loader to work.
It fixes "Expected 'styles' to be an array of strings." error, but works not correct.
Components from angular-material (eg form controls) looks bad in this configuration.
@nglazov I suppose that will be taken care of by the dev teams. :) Really hope it to work soon.
Does interface NgStory correct? How about templateUrl
and stylesUrl
?
// app/angular/src/client/preview/angular/types.ts
export interface NgStory {
component?: any;
props: ICollection;
propsMeta?: ICollection;
moduleMetadata?: NgModuleMetadata;
template?: string;
styles?: string[];
}
Should we update initModule too? It doesn't seem to handle components which use templateUrl
or styleUrls
.
// app/angular/src/client/preview/angular/helpers.ts
const initModule = (currentStory: IGetStory): Function => {
const storyObj = currentStory();
const { component, template, props, styles, moduleMetadata = {} } = storyObj;
let AnnotatedComponent;
if (template) {
AnnotatedComponent = createComponentFromTemplate(template, styles);
} else {
AnnotatedComponent = component;
}
const story = {
component: AnnotatedComponent,
props,
};
return getModule(
[AppComponent, AnnotatedComponent],
[AnnotatedComponent],
[AppComponent],
story,
moduleMetadata
);
};
@wuyuanyi135 your workaround seems to work that's the way it should be shipped (In my case I didn't need the id part but your webpack config is a must)
@agalazis True. I believe it was after alpha 7 where the module.id
line was no longer necessary. I haven't test the later versions since I switch to Angular playground before storybook is stable for Angular.
Has anyone tried the latest alpha? it supports Angular 6.
I'm still struggling to make it work. A part of the issue might be the fact that I'm using .scss
files. @wuyuanyi135 , do you have an idea what webpack configuration to use in this case? I tried the suggested loader, but that didn't work:
{
test: /\.scss$/,
use: [
'style-loader', // creates style nodes from JS strings
'css-loader', // translates CSS into CommonJS
'sass-loader' // compiles Sass to CSS
]
}
If you are using scss and angular-cli, storybook should work without configuring anything.
I fixed this issue by using text-loader
. I'm not using a CSS preprocessor though.
I assume we are ok here, right?
I'm using alpha.14 and experiencing the same issue, but with LESS
files rather than SASS
.
Weback config:
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.less$/,
loaders: ['style-loader', 'css-loader', 'less-loader'],
include: path.resolve(__dirname, '../'),
},
{
test: /\.(jpe?g|png|gif)$/,
use: 'file-loader?name=img/[name]-[hash].[ext]'
},
{
test: /\.(eot|woff2?|svg|ttf)([\?]?.*)$/,
use: 'file-loader',
},
],
},
};
AFAIR, less
is also treated out-of-the-box by angular-cli
, if so, you don't need to define any extra rules for the .less
files.
Sadly, removing the .less
rule does not resolve the issue, but introduces a new one:
ERROR in ./.storybook/container.less 1:0
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type.
> @import '~@org/fe-webapp-styling/src/main.less';
|
@ ./.storybook/config.js 10:0-26
@ multi ./node_modules/@storybook/core/dist/server/config/polyfills.js ./node_modules/@storybook/core/dist/server/config/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true
ERROR in ./src/components/molecules/progress-bar/progress-bar.component.less 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> .progress-bar-warning {
| width: 0;
| }
@ ./src/components/molecules/progress-bar/progress-bar.component.ts 61:21-61
@ ./src/components/molecules/progress-bar/index.ts
@ ./src/components/molecules/index.ts
@ ./src/components/index.ts
@ ./src/components.module.ts
@ ./.storybook/config.js
@ multi ./node_modules/@storybook/core/dist/server/config/polyfills.js ./node_modules/@storybook/core/dist/server/config/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true
By the looks of it, angular-cli
does not add the less
loader to storybook, but it does work when running ng build
.
I've added this š to an official storybook angular example
The only error I got was about the lack of less-loader
, because we didn't choose this option when created our angular-cli example. After manually installing a less-loader
, everything started working for me.
Could you please give me a URL to the example commit? I'm trying to reproduce it locally, but failing.
I fixed the issue by changing the LESS loader to this:
{
test: /\.less$/,
loaders: ['text-loader', 'style-loader', 'css-loader', 'less-loader'],
include: path.resolve(__dirname, '../'),
}
Honestly - no idea why it works now.
I didn't commit this specific example. since there was nothing special. The official example app is here , though, you need to bootstrap the whole monorepo to be able to run it.
Anyway, to understand what is wrong in your setup we need a reproduction š¤·āāļø
Yeah, that's completely understandable. Since I somehow managed to solve the issue on my project, I'll get out of your hair. Thanks for the patience! :)
FYI, this issue will arise if you misspell any part of the file name as well. Like, leaving off the .scss extension.
I followed @wuyuanyi135 solution.
1) I added a .storybook/webpack.config.js
file. The code is below.
2) I added to-string-loader
and @storybook/addon-storysource
(alpha 4.0.0 version)
Here's my webpack code (same as @wuyuanyi135):
const path = require('path');
module.exports = baseConfig => {
// Extend defaultConfig as you need.
baseConfig.module.rules = [
...baseConfig.module.rules,
{
test: [/\.stories\.tsx?$/, /index\.ts$/],
loaders: [
{
loader: require.resolve('@storybook/addon-storysource/loader'),
options: {
parser: 'typescript'
}
}
],
include: [path.resolve(__dirname, '../src')],
enforce: 'pre'
},
{
test: /\.css$/,
use: ['to-string-loader', 'css-loader']
}
];
return baseConfig;
};
Adding .less
to my project looks straightforward now as well. Thank you, @wuyuanyi135 !
i have fixed this issue with changing
styleUrls: ['./app.component.CSS']
to styleUrls: ['./app.component.css']
just lower case styles extensions
now it works fine :)
@DmitryEfimenko Hi Dmitry! How did you solve your issue with .scss
back then? I know that it should "just work", but it doesn't in my case, just like in yours
This error could be caused by a improper (ie too new) version of raw-loader
.
See https://github.com/TheLarkInn/angular2-template-loader/issues/86
Setting it to 1.0.0
fixed the issue in my project.
This error could be caused by a improper (ie too new) version of
raw-loader
.See TheLarkInn/angular2-template-loader#86
Setting it to
1.0.0
fixed the issue in my project.
Thanx man! You saved my day
raw-loader
v. 3.0.0
also has the same issue
To fix the Expected 'styles' to be an array of strings
error, i followed the Custom Webpack Config chapter of the storybook documentation and added a custom rule that handles scss
parsing.
The debug flag --debug-webpack
revealed that storybook adds a scss
rule which needs to removed, as that rule would still take priority of our custom one.
Using the angular-cli setup was not an option for us as we run a custom webpack build.
The final version of the customization looks as follow.
webpack.config.js
) version// Export a function. Accept the base config as the only param.
module.exports = async ({config, mode}) => {
// `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
r = config.module.rules.filter(rule => rule.test != '/\\.s(c|a)ss$/');
// Make whatever fine-grained changes you need
r.push({
test: /\.scss$/,
// test: /\.s(c|a)ss$/,
use: [
'to-string-loader',
{
loader: 'style-loader',
options: {
sourceMap: true,
},
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
});
config.module.rules = r;
// Return the altered config
return config;
};
webpack.config.ts
) version with type hintsimport {Configuration, RuleSetRule} from 'webpack';
module.exports = async ({config, mode}: {config: Configuration, mode: string}) => {
// `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
if (!config.module) {
return config;
}
var rules = config.module.rules.filter((rule: RuleSetRule) => rule.test != '/\\.s(c|a)ss$/');
rules.push({
test: /\.scss$/,
use: [
'to-string-loader',
{
loader: 'style-loader',
options: {
sourceMap: true,
},
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
});
config.module.rules = rules;
// Return the altered config
return config;
};
Instead of āstyle-loaderā, ācss-loaderā, āsass-loaderā
I went with āto-string-loaderā, ācss-loaderā, āsass-loaderā
I used this article:
https://www.freecodecamp.org/news/how-to-configure-webpack-4-with-angular-7-a-complete-guide-9a23c879f471/
Most helpful comment
This is an update for this issue.
In alpha.6, the aforementioned issues can be resolved by extending the webpack.config.json in .storybook directory:
note that the magic is the to-string-loader that adapt the css to what Angular 6 want.
After getting this config file, the error becomes to
failed to load XXXX.html
. It seems like storybook still want to load the template page even though it has been bundled. To resolve this issue, addmoduleId = module.id
to each of the@Component
in your Angular components.I don't really like this workaround. Thankfully, the
failed to load html
problem seems to be fixed in alpha.7. But still the css files need the to-string-loader to work.