How to tree-shake Lodash and Mui imports in Storybook 5 - material-ui

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

What should the publicPath in webpack config be for a dynamic port?

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",
}),
],
};

Babelrc configuration for IE11 support

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...

What routing format should I use for storybook routes in an angular project?

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;

Gerkin and Cucumber in Angular 5: Undefined

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.

Can't set breakpoint in Chrome with Babel and Webpack

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!