cannot use the image inside the storybook - reactjs

I tried to use the images in the storybook. that image also inside the storybook project only.
Here is my storybook webpack.config.js file.
const path = require('path');
module.exports = async ({ config }) => {
config.module.rules.push({
test: /\.(sass|scss)$/,
use: ['resolve-url-loader'],
include: path.resolve(__dirname, '../')
});
config.module.rules.push({
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
use: [
{
loader: 'file-loader',
query: {
name: '[name].[ext]'
}
}
],
include: path.resolve(__dirname, '../')
});
return config;
};
this is how I import the images
import arrow from '../../static/arrow.png';
I got the image source like
<img src="data:image/png;base64,ZXhwb3J0IGRlZmF1bHQgX193ZWJwYWNrX3B1YmxpY19wYXRoX18gKyAiQmFubmVyV2Vla2VuZDIucG5nIjs=" alt="test">

Related

gltf file is not showing in react nextjs

I am trying to load a gltf file in a nextjs application using threejs.But its not working when i try to run it with nextjs application on react project.This is how i configured next.js with webpack:
const withCSS = require('#zeit/next-css');
const withImages = require('next-images');
const withPlugins = require('next-compose-plugins');
module.exports = withPlugins([
[withCSS, { cssModules: true }],
[withImages],
], {
serverRuntimeConfig: { serverRuntimeConfigValue: 'test server' },
publicRuntimeConfig: { publicRuntimeConfigValue: {apiUrl:process.env.apiUrl.trim()} },
webpack: (config, options) => {
config.module.rules.push({
test: /\.(glb|gltf)$/,
use: {
loader: 'file-loader',
}
})
return config; },exportTrailingSlash: true
});
I am importing the file like this:
import React from 'react';
import * as THREE from 'three';
import GLTFLoader from 'three-gltf-loader';
import TransformControls from './TransformControls.js'
import test2 from "../../../static/images/villa.gltf";
I wrote this function in componentDidmount to load gltf:
this.loader.load(test2, gltf => {
this.gltf = gltf.scene
// ADD MODEL TO THE SCENE
this.scene.add(gltf.scene);
});
This is Network tab when rendering the gltf file
In order to serve assets correctly with file-loader, you have to configure with correct location of _next static dir as following:
{
loader: 'file-loader',
options: {
publicPath: "/_next/static/images", // the path access the assets via url
outputPath: "static/images/", // where to store on disk
}
}
But looks like you might need to set up to load .bin file as well and keep the original name since it will be loaded as the .load function is called:
webpack: (config) => {
config.module.rules.push({
test: /\.(glb|gltf)$/,
use: {
loader: 'file-loader',
options: {
publicPath: "/_next/static/images",
outputPath: "static/images/",
}
},
});
// For bin file
config.module.rules.push({
test: /\.(bin)$/,
use: {
loader: 'file-loader',
options: {
publicPath: "/_next/static/images",
outputPath: "static/images/",
name: '[name].[ext]' // keep the original name
}
},
});
}
And also import the bin file in your component too:
import "../../../static/images/villa.bin";

Importing SVG image results in Warning: Prop `src` did not match. Server:

I installed file-loader in my next.js project and configured my next.config.js to be like this:
module.exports = {
entry: './src/index.js',
webpack: config => {
const env = Object.keys(process.env).reduce((acc, curr) => {
acc[`process.env.${curr}`] = JSON.stringify(process.env[curr]);
return acc;
}, {});
config.plugins.push(new webpack.DefinePlugin(env));
config.module.rules.push({
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[hash]-[name].[ext]',
},
},
],
});
return config;
}
};
I then have an image in /public/images/book-reading.svg
So I tried to import the image like this in a component I have within /src/components:
import BookReading from '../../public/images/book-reading.svg';
And using it like this:
<img src={BookReading} />
However the image does not show and I get this warning:
Warning: Prop src did not match. Server:
"images/364068d183bb962a8423031f65bab6ad-book-reading.svg" Client:
"/_next/images/364068d183bb962a8423031f65bab6ad-book-reading.svg"
Any ideas?
You need to add the publicPath and the outputPath to file-loader's options.
module.exports = {
webpack: config => {
config.module.rules.push({
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[hash]-[name].[ext]',
publicPath: `/_next/static/images/`,
outputPath: 'static/images',
},
},
],
});
return config;
}
};
This is not your case but for the sake of completeness: if you had used a different basePath, you'd have needed to add it at the beginning of your publicPath.
Source

Storybook doesn't understand import on demand for antd components

I have followed instructions here to get antd working fine with CRA. But while using it from storybook, I was getting an error as:
Build fails against a mixin with message Inline JavaScript is not
enabled. Is it set in your options?
I had fixed that following suggestions on an issue I raised here.
Now, storybook understands antd but not importing components on demand. Is babel has to be configured separately for storybook?
1. On using import { Button } from "antd";
I get this:
2. On using
import Button from "antd/lib/button";
import "antd/lib/button/style";
I get:
Storybook version: "#storybook/react": "^3.4.8"
Dependency: "antd": "^3.7.3"
I have been stuck (again) with this for quite long hours googling things, any help is appreciated. Thanks!
Using Storybook 4, you can create a webpack.config.js file in the .storybook directory with the following configuration:
const path = require("path");
module.exports = {
module: {
rules: [
{
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.js$/,
options: {
presets: ["#babel/react"],
plugins: [
['import', {libraryName: "antd", style: true}]
]
},
},
{
test: /\.less$/,
loaders: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
modifyVars: {"#primary-color": "#d8df19"},
javascriptEnabled: true
}
}
],
include: path.resolve(__dirname, "../")
}
]
}
};
Note that the above snippet includes a style overwriting of the primary button color in antd. I figured, you might want to eventually edit the default theme so you can remove that line in case you do not intend to do so.
You can now import the Button component in Storybook using:
import {Button} from "antd";
without having to also import the style file.
If you are using AntD Advanced-Guides for React and storybook v5 create .storybook/webpack.config.js with the following:
const path = require('path');
module.exports = async ({ config, mode }) => {
config.module.rules.push({
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.(js|jsx)$/,
options: {
presets: ['#babel/react'],
plugins: [
['import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true
}]
]
},
});
config.module.rules.push({
test: /\.less$/,
loaders: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
modifyVars: {'#primary-color': '#f00'},
javascriptEnabled: true
}
}
],
include: [
path.resolve(__dirname, '../src'),
/[\\/]node_modules[\\/].*antd/
]
});
return config;
};
Then you can use import { Button } from 'antd' to import antd components.
I'm currently using storybook with antd and i got it to play nice, by using this config in my webpack.config.js file in the .storybook folder:
const { injectBabelPlugin } = require('react-app-rewired');
const path = require("path");
module.exports = function override(config, env) {
config = injectBabelPlugin(
['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }],
config,
);
config.module.rules.push({
test: /\.css$/,
loaders: ["style-loader", "css-loader", ],
include: path.resolve(__dirname, "../")
})
return config;
};

How to use CSS Modules with webpack in React isomorphic app?

I am build an isomorphic app using react, react-router, express and webpack. Now I want to use css modules to import css.
I use import './index.css' in index.jsx, it works fine on client, but doesn't work on server rendering. The error is Error: Cannot find module './index.css'.
components/index.jsx
import React, {Component, PropTypes} from 'react';
import style from './index.css';
class App extends Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<div id="login">
// ...
</div>
);
}
};
export default App;
server/router/index.js
import url from 'url';
import express from 'express';
import swig from 'swig';
import React from 'react';
import {renderToString} from 'react-dom/server';
import {match, RouterContext} from 'react-router';
import routes from '../../client/routes/routes';
import DataWrapper from '../../client/container/DataWrapper';
import data from '../module/data';
const router = express.Router();
router.get('*', async(req, res) => {
match({
routes,
location: req.url
}, async(error, redirectLocation, props) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.status(302).redirect(redirectLocation.pathname + redirectLocation.search);
} else if (props) {
let content = renderToString(
<DataWrapper data={data}><RouterContext {...props}/></DataWrapper>
);
let html = swig.renderFile('views/index.html', {
content,
env: process.env.NODE_ENV
});
res.status(200).send(html);
} else {
res.status(404).send('Not found');
}
});
});
export default router;
webpack.config.dev.js(for webpack-dev-server)
var webpack = require('webpack');
var config = require('./config');
module.exports = {
devtool: 'inline-source-map',
entry: [
'webpack-dev-server/client?http://localhost:' + config.webpackPort,
'webpack/hot/only-dev-server',
'./src/client/entry',
],
output: {
path: __dirname + '/public/js',
filename: 'app.js',
publicPath: 'http://localhost:' + config.webpackPort + '/public/js',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify('development')
}
})
],
resolve: {
extensions: ['', '.js', '.jsx', '.css']
},
module: {
loaders: [{
test: /\.jsx?$/,
loader: 'react-hot',
exclude: /node_modules/
}, {
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.css$/,
loader: 'style-loader!css-loader?modules',
exclude: /node_modules/
}, {
test: /\.(png|woff|woff2|svg|ttf|eot)$/,
loader: 'url-loader',
exclude: /node_modules/
}]
}
}
I'd recommend using webpack to compile UI code for both client and server side in that case. Just set target: "node" in webpack config to produce bundle which can executed in Node environment.
That article might help for compiling your server side code with Webpack: http://jlongster.com/Backend-Apps-with-Webpack--Part-I
Especially on how to exclude node_modules with the externals key.
A very bare config might look like:
'use strict';
const path = require('path');
const fs = require('fs');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const rootDir = path.resolve(__dirname, '..');
const distDir = path.join(rootDir, 'dist');
const srcDir = path.join(rootDir, 'src');
const localStyles = new ExtractTextPlugin('local.css', { allChunks: true });
const nodeModules = fs.readdirSync('node_modules')
.filter(dir => !dir.startsWith('.'))
.reduce((acc, prop) => {
acc[prop] = 'commonjs ' + prop;
return acc;
}, {});
const loaders = [
{
test: /\.(js|jsx)$/,
include: srcDir,
exclude: /node_modules/,
loader: 'babel',
query: {
cacheDirectory: true,
},
},
{
test: /\.css$/,
include: srcDir,
loader: localStyles.extract(
'style',
'css?modules&localIdentName=[name]-[local]_[hash:base64:5]'
),
},
{
test: /\.json$/,
loader: 'json',
},
];
module.exports = {
target: 'node',
entry: {
server: ['server/index'],
},
output: {
path: distDir,
filename: '[name].bundle.js',
},
externals: nodeModules,
module: {
loaders,
},
plugins: [
localStyles,
],
};
Another solution (Webpack free) could be to use babel-plugin-css-modules-transform
.

How to render a foo.md markdown file in react?

I have several .md files (containing long texts) and I want to render them through react. I tried to use markedown-it but the loader returns an error. Here is the webpack.config.js file:
var path = require('path');
var webpack = require('webpack');
var subscript = require('markdown-it');
var superscript = require('markdown-it');
module.exports = {
entry: ['./src/first.jsx'],
devtool: 'cheap-module-eval-source-map',
output: { path: __dirname+"/app", filename: 'bundle.js' },
module: {
loaders: [
{ test: /\.jsx?$/,
loader: 'babel-loader',
query: { presets: ['es2015', 'react'] },
include: path.join(__dirname, 'src')
},
{ test: /\.md/,
loader: 'markdown-it'
}
]
},
'markdown-it': {
preset: 'default',
typographer: true,
use: [subscript, superscript]
}
};
Is there something wrong with that file? How else I can add my *.md files to react?
After reading http://www.shoutinginfrench.com/today-i-made-react-load-markdown/ I tried to use markdown-loader. Following that, I added this to webpack.config file:
{ test: /\.md$/,
loader: "html!markdown"
}
which worked with no problem. Then I tried to add the markdown file to the react component as follow:
import React from 'react';
import { Link } from 'react-router'
import markdownFile from './test-file.md';
export const Test = React.createClass({
rawMarkup(){
return { __html: markdownFile };
},
render() {
return (
<div className="something">
<div className="row">
<div className="col-10">
<div dangerouslySetInnerHtml={this.rawMarkup()} />
</div>
</div>
</div>
);
}
});
But I'm getting the following error:
ERROR in ./src/components/tst.jsx
Module not found: Error: Cannot resolve module 'html' in /Users/..../src/components
# ./src/components/tst.jsx 14:15-39
How can I fix it?!
add { test: /\.md$/, loader: "html!markdown" },{ test: /\.json$/, loader: "json" } to your webpack.config.js .
npm install react-markdown --save-dev

Resources