I'm using Mui and Lodash in my CRA project with Storybook 5.
I successfully tree-shake both Mui and Lodash imports using babel-plugin-import in CRA, using the following .bablerc.js
module.exports = {
presets: ["react-app", "#babel/preset-typescript"],
plugins: [
[
"babel-plugin-import",
{
libraryName: "#material-ui/core",
libraryDirectory: "esm",
camel2DashComponentName: false,
},
"core",
],
[
"babel-plugin-import",
{
libraryName: "#material-ui/icons",
libraryDirectory: "esm",
camel2DashComponentName: false,
},
"icons",
],
["lodash"],
],
};
However I am unable to do the same in Storybook 5. When I try using the same config in Storybook (copying over to .storybook/.babelrc.js), the babel config gets loaded, but results in no improvement in Storybook load times (Mui icons still seem to be loading for about a minute). Removing the presets
from babel config doesn't help either.
Storybook is hosted in the same root directory as my CRA, sharing node_modules.
How can I get the import tree-shaking to work in Storybook 5?
Here are my configs:
// .storybook/presets.js
module.exports = ['#storybook/preset-create-react-app'];
// .storybook/webpack.config.js
module.exports = function({ config }) {
// https://github.com/storybookjs/storybook/issues/6974#issuecomment-499903328
config.module.rules.unshift({
test: /\.stories.js$|\.stories.jsx$|\.stories.tsx$|\.stories.ts$/,
loaders: [require.resolve('#storybook/source-loader')],
enforce: 'pre',
});
return config;
};
// .storybook/.babelrc.js
module.exports = {
presets: ["react-app", "#babel/preset-typescript"],
plugins: [
[
"babel-plugin-import",
{
libraryName: "#material-ui/core",
libraryDirectory: "esm",
camel2DashComponentName: false,
},
"core",
],
[
"babel-plugin-import",
{
libraryName: "#material-ui/icons",
libraryDirectory: "esm",
camel2DashComponentName: false,
},
"icons",
],
["lodash"],
],
};
// .storybook/config.js
iimport { addDecorator, addParameters, configure } from "#storybook/react";
import { withKnobs } from "#storybook/addon-knobs";
import { withConsole } from "#storybook/addon-console";
import { INITIAL_VIEWPORTS } from "#storybook/addon-viewport";
import "../src/config";
import withIntl from "./decorators/intl";
import withReduxStoreAndConnectedRouter from "./decorators/reduxStoreWithDependentProviders";
import stylesProvider from "./decorators/stylesProvider";
import setup from "./decorators/setup";
const req = require.context("../src", true, /stories.tsx$|stories.ts$/);
const loadStories = () => req.keys().forEach((filename) => req(filename));
addDecorator(setup);
addDecorator(stylesProvider);
addDecorator(withKnobs);
addDecorator(withIntl);
addDecorator(withReduxStoreAndConnectedRouter);
addDecorator((storyFn, context) =>
withConsole(consoleConfig)(storyFn)(context)
);
addParameters({
viewport: {
viewports: INITIAL_VIEWPORTS,
},
});
addParameters({
backgrounds: [
{ name: "darkGray", value: "#34373c" },
{ name: "gray", value: "#A0A0A0" },
{ name: "lightGray", value: "#F0F0F0" },
],
});
configure(loadStories, module);
Related
I'm currently building a microfrontend using webpack's module federation, however when I create a deployment in kubernetes it's not resolving because of an incorrect publicPath. It's still a bit complex to me and I'm not sure what to set the publicPath to as the localhost port keeps changing every deployment.
So it looks like: http://127.0.0.1:TUNNEL_PORT, whereby TUNNEL_PORT is dynamic. How would I account for this when defining my output.publicPath?
Webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;
module.exports = {
output: {
publicPath: "http://localhost:3000/",
// publicPath: 'auto',
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
},
devServer: {
port: 3000,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.m?js/,
type: "javascript/auto",
resolve: {
fullySpecified: false,
},
},
{
test: /\.(css|s[ac]ss)$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "microfrontend1",
filename: "remoteEntry.js",
remotes: {},
exposes: {
"./Header": "./src/Header.tsx",
"./Footer": "./src/Footer.tsx",
},
shared: {
...deps,
react: {
singleton: true,
eager: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
eager: true,
requiredVersion: deps["react-dom"],
},
},
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
};
I am trying to configure .babelrc for my react project but, cant make it work in IE11.
Can someone take a look at my configuration and see if there are things that I am missing, please?
[.babelrc]
{
"presets": [
"#babel/preset-env",
[
"#babel/preset-react",
{
"useBuiltIns": "usage",
"corejs": 3.26
}
]
],
"plugins": ["#babel/plugin-transform-runtime"]
}
[webpack.common.config.js]
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
module.exports = {
// Default. Can be erased for code simplification
entry: "./src/index.js",
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /[\\/]node_modules[\\/]/,
use: {
loader: "babel-loader",
},
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
}),
],
};
I have tried a lot of things(workarounds), but nothing seems to work.
The order of presets, importing core-js at the top of index.js file...
For example, the url to my "getting started" story is:
http://localhost:6006/?path=/story/angular-component-library-getting-started--page
How would I access this page via routerLink in a template of a storybook story? Right now I have:
const navbarMenuItems = [
{
displayText: 'Home',
routerLink: '/story/angular-component-library-getting-started--page',
},
{
displayText: 'About',
routerLink: '/story/angular-component-library-getting-started--page',
},
{
displayText: 'Google',
href: 'https://google.com',
},
];
And I get the error: Error: Cannot match any routes. URL Segment: 'story/angular-component-library-getting-started--page'
I have tried playing around with adding slashes, removing them, removing the --page suffix, I tried using the page title, nothing works.
Here are my imports and export, for reference:
import { moduleMetadata, Meta, Story } from '#storybook/angular';
import { APP_BASE_HREF, CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { SandboxNavbarComponent } from '../../app/sandbox/navbar/navbar.component';
export default {
title: 'Angular Component Library/Navbar',
component: SandboxNavbarComponent,
decorators: [
moduleMetadata({
declarations: [TqlIconComponent],
imports: [
CommonModule,
RouterModule.forRoot([
{
path: 'iframe.html',
component: SandboxNavbarComponent,
pathMatch: 'full',
},
]),
],
providers: [
{
provide: APP_BASE_HREF,
useValue: '/',
},
],
}),
],
} as Meta;
When I try to create a test using Cucumber and Gherkin I get a strange error. I show you the error first, then the files login.step.ts and login.po.ts:
// Error:
Undefined. Implement with the following snippet:
When('Enter the card number in the box', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});
// login.step.ts
import { expect } from 'chai';
const { Given, When, Then, Before } = require('cucumber');
import { browser, by, element } from 'protractor';
import { LoginPage } from './login.po';
let login: LoginPage;
Before(() => {
login = new LoginPage();
});
Given(/^Entering in Login$/, { timeout: 10 * 5000 }, async () => {
await browser.get('http://localhost:49152/login');
});
When(/^Enter the card number in the box$/, () => {
// login.setCardNumber('1234').then((txt) => {
// return 'ready!?';
// })
login.setCardNumber('1234');
});
// login.po.ts
import { browser, by, element, until } from 'protractor';
export class LoginPage {
navigateTo() {
return browser.get('/login');
}
setCardNumber(cardNumber) {
const input = element(by.css('#box'));
return input.sendKeys(cardNumber);
}
}
The first test passes successfully, but in the second test, the process ends in error.
[EDIT]
Adding the protractor.conf.js file:
exports.config = {
allScriptsTimeout: 11000,
specs: [
// './e2e/**/*.e2e-spec.ts',
'./e2e/features/*.feature'
],
capabilities: {
'browserName': 'chrome',
chromeOptions: {
args: ['disable-infobars']
},
metadata: {
browser: {
name: 'chrome',
version: '58'
},
device: 'Xubuntu Linux',
platform: {
name: 'Linux',
version: '16.04'
}
}
},
directConnect: true,
frameworkPath: require.resolve('protractor-cucumber-framework'),
plugins: [{
package: 'protractor-multiple-cucumber-html-reporter-plugin',
options: {
automaticallyGenerateReport: true,
removeExistingJsonReportFile: true
}
}],
cucumberOpts: {
require: ['./e2e/steps/**/*.ts', './e2e/support/*.ts'],
tags: [],
dryRun: false,
compiler: [],
format: 'json:reports/results.json',
strict: true
},
baseUrl: 'http://localhost:4200/',
SELENIUM_PROMISE_MANAGER: false,
framework: 'custom',
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
}
};
remove the double quote " behind box in /^Enter the card number in the box"$/
I found the answer to my problem. I only had to include the following configuration line to my Before() step in my test:
browser.ignoreSynchronization = true;
According to what I read in different places, it seems that Chrome is looking to perform some task with sockets, and with this line we are disabling this task.
I have started a new project using the "new" stack: React+Webpack+Babel.
I am trying to explore of this work, and I am facing an issue with debugging in chrome. I can't set breakpoints on some lines in source files when I use Babel and Webpack. (I create sourcemaps).
I would like to be able to debug JSX files.
I have set a little project to reproduce the problem.
https://github.com/pierre-hilt/babel_webpack_sourcemap.git
Here is my configuration:
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'source-map',
entry: './build/index',
output: {
path: path.join(__dirname, 'static'),
filename: '[name].bundle.js',
publicPath: '/',
},
module: {
preLoaders: [
{
test: /\.jsx?$/,
loader: "source-map-loader"
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
}
babelrc:
{
"presets": [
"es2015",
"react"
],
"plugins": []
}
App.jsx (I try to break on line 6 but it is impossible...)
import React, { Component, PropTypes } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
title: props.title,
};
}
changeTitle(newTitle) {
this.setState({ title: newTitle });
}
render() {
return (
<div>
This is {this.state.title}
</div>
);
}
}
App.propTypes = { title: PropTypes.string };
export default App;
I tried different devtool options (cheap, module, ...).
I also tried Babel loader, but is does not work either.
Do you have any idea? Is it a known issue?
OK, I found a workaround that works fine!
babelrc
{
"presets": [
"react"
],
"plugins": []
}
Babel script
"babel": "babel client -d build --source-maps",
webpack config
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'source-map',
entry: './build/index',
output: {
path: path.join(__dirname, 'static'),
filename: '[name].bundle.js',
publicPath: '/',
},
module: {
preLoaders: [
{
test: /\.jsx?$/,
loader: "source-map-loader"
}
],
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
query: {
presets: ['es2015']
}
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
}
I first transpile JSX with babel only, then I transpile ES2015 with babel loader and webpack.
At the end I got source files where I can set break points anywhere!