Webpack not serving background image nested folder + images - reactjs

I am using webpack(3.6.0) for an isomorphic react app and have everything working except the background image in my css file. All other styles work, the image is being output to my /dist folder as expected on my local machine, I see the correct file path in the browser at localhost if I inspect...but if I go to sources in dev-tools the entire directory under /dist/client for these static files is missing. I am trying to figure out isomorphic rendering, so I honestly only have a little idea of what is going on in terms of the server vs client render dance, on top of admittedly not having my head totally around webpack configuration. Been able to troubleshoot my way thus far but this has me truly stumped and any insight would be greatly appreciated!
computer /dist folder:
/dist
---- /client // client bundled
---- ---- /media // where webpack moved static stuff
---- ---- ---- image.hash.jpg // where webpack ouput img
---- ---- app.bundle.js // webpack js bundle
---- ---- style.css // webpack bundled+extracted css
---- /media // server-side webpacked media
---- index-main.html // index file
---- server.js // server-side webpack js bundle
---- style.css // server-side webpack bundled+ext css
browser Sources (testing w/chrome):
/localhost:port
---- /dist/client
---- ---- app.bundle.js
---- ---- style.css
targeted DOM element background style:
background: url(./client/media/bg.58dfa049.jpg) no-repeat center center;
webpack.config.js (client):
const path = require('path'),
autoprefixer = require('autoprefixer'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
webpack = require('webpack');
module.exports = {
context: path.resolve(__dirname, './src'),
entry: {
app: './client/index.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, './dist/client/'),
publicPath: './client/',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: [{
loader: 'babel-loader',
options: { presets: ['es2015', 'react'], plugins: ['transform-object-rest-spread', 'async-to-promises'] }
}],
},
//loaders for other file types can go here
{
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.css$/,
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
],
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]',
},
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: 'url-loader',
options: {
limit: 10000,
name: 'media/[name].[hash:8].[ext]',
},
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:[
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]_[local]--[hash:base64:8]',
importLoaders: 1
},
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
}],
}),
},
]
},
plugins: [
new ExtractTextPlugin('style.css'),
new webpack.HotModuleReplacementPlugin(),
],
};
webpack.config.server.js (server):
const nodeExternals = require('webpack-node-externals'),
autoprefixer = require('autoprefixer'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
path = require('path');
module.exports = {
context: path.resolve(__dirname, './src'),
entry: './server/server.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'server.js',
libraryTarget: 'commonjs',
publicPath: './server/'
},
target: 'node',
node: {
__dirname: false,
__filename: false
},
externals: nodeExternals({
modulesFromFile: true,
}),
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: [{
loader: 'babel-loader',
options: { presets: ['es2015', 'react'], plugins: ['transform-object-rest-spread'] }
}],
},
//loaders for other file types can go here
{
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.css$/,
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
],
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]',
},
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: 'url-loader',
options: {
limit: 10000,
name: 'media/[name].[hash:8].[ext]',
},
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:[
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]_[local]--[hash:base64:8]',
importLoaders: 1
},
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
}],
}),
},
]
},
plugins: [
new ExtractTextPlugin('style.css'),
],
};
css file:
.adoptly {
margin: 0;
padding: 0;
font-family: 'Montserrat', sans-serif;
}
.header {
background-color: #30627E;
}
.container {
/*max-width: 940px;*/
margin: 0 auto;
padding: 0;
}
.header ul {
list-style: none;
text-align: center;
margin: 0;
padding: 0;
}
.header .main {
font-size: 28px;
background-color: #e52364;
}
.header li {
color: #fff;
display: inline-block;
font-size: 20px;
text-align: center;
padding: 20px 30px;
margin: 0;
}
.header li a:link {
color:white;
text-decoration: none;
}
.header li a:visited {
color:white;
text-decoration: none;
}
.header li a:hover {
color:blue;
text-decoration: none;
}
.jumbotron {
background: url('../img/bg.jpg') no-repeat center center;
background-size: cover;
height: 500px;
text-align: center;
margin-bottom: 0;
}
.jumbotron .container {
max-width: 100%;
}
.jumbotron h1 {
color: #e52364;
font-weight: 700;
}
.supporting {
text-align: center;
padding: 60px 30px 80px;
}
.row {
margin-right: -15px;
margin-left: -15px;
}
.supporting p {
font-family: 'Open Sans', sans-serif;
font-size: 14px;
min-height: 80px;
}
.btn {
font-size: 16px;
border-radius: 0px;
margin: 20px auto 60px;
padding: 10px 20px;
color: #30627E;
width: 200px;
border: 1px solid #30627E;
text-transform: uppercase;
}
.footer {
color: #fff;
background-color: #e52364;
padding: 20px;
}
.copy {
padding-top: 10px;
}
.pull-right {
float: right!important;
}
.nav-pills>li {
float: left;
}
.nav li a {
color: #fff;
}
.nav-pills>li>a {
border-radius: 4px;
}
.nav>li>a {
position: relative;
display: block;
padding: 10px 15px;
}
#media (min-width: 992px) {
.col-md-4 {
width: 33.33333333%;
}
}
#media (max-width: 500px) {
ul li {
width: 100%;
}
}

Related

Problems with fonts and images when I use my library in a project

I am creating React UI library with #emotion. I have problems with fonts and images when I use my library in a project.
My lib (emotion-lib)
enter image description here
Project when I use my library
enter image description here
Web-pack modules (emotion-lib):
module: {
rules: [
{
test: /\.(ttf|otf)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: false,
name: '[name].[ext]',
outputPath: 'fonts',
},
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(ts|tsx)?$/,
use: ['babel-loader', 'ts-loader'],
exclude: /node_modules/,
},
{
test: /\.svg$/,
loader: require.resolve('#svgr/webpack'),
options: {
svgoConfig: {
plugins: [
{
name: 'removeViewBox',
active: false,
},
],
},
},
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images',
},
},
],
},
],
},
global.ts (emotion-lib)
import { css } from '#emotion/react';
import SFPro from '../../../assets/fonts/SF-Pro/SF-Pro.ttf';
export const global = css`
/* SF Pro */
#font-face {
font-family: 'SF Pro';
src: url('${SFPro}');
}
html,
body {
margin: 0;
padding: 0;
font-family: 'SF Pro', sans-serif;
font-weight: 500;
font-size: 16px;
line-height: 28px;
}
a {
text-decoration: none;
color: inherit;
}
* {
box-sizing: border-box;
font-family: 'SF Pro Text', sans-serif;
}
`;
I tried to import fonts and images in my project, but there was a mistake ('not found').

How I run storybook with tsx and sass files

I'm using TSDX to create a library with storybook.
My problem is when I run storybook with:
npm run start-storybook -p 6006
show me next errors:
ERROR in ./src/sidenav/functions/index.tsx Module not found: Error: Can't resolve '../../../constants/global-constants'
ERROR in ./src/alarmbar/styles/alarmbar.scss 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
It seems that cant load tsx and sass files.
In scss files I'm using this to use dark and light mode on each component.
$color-text-black-base: #343434;
$color-text-white-base: #ffffff;
#function themed($key) {
#return map-get($theme-map, $key);
}
$a-tags: "a, a:active, a:hover, a:visited";
$a-tags-hover: "a:active, a:hover";
/*
* Implementation of themes
*/
#mixin themify($themes) {
#each $theme, $map in $themes {
.#{$theme} & {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), "#{$key}");
$theme-map: map-merge(
$theme-map,
(
$key: $value,
)
) !global;
}
#content;
$theme-map: null !global;
}
}
}
$themes: (
light: (
textColorBase: $color-text-black-base,
),
dark: (
textColorBase: $color-text-white-base,
),
);
So, with that each component change if theme is dark or light:
#import "./styles-utils.scss";
.breadcrumb-item {
font-weight: 500;
#include themify($themes) {
color: themed("textColorBase");
}
margin-right: 5px;
user-select: none;
.normal {
#include themify($themes) {
color: themed("textColorBase");
}
text-decoration: none;
}
.normal:active,
.normal:visited,
.normal:hover {
#include themify($themes) {
color: themed("textColorBase");
}
}
}
.breadcrumb-item--active {
font-weight: 700;
#include themify($themes) {
color: themed("textColorBase");
}
}
Any idea how to fix it?
SOLUTION:
Update "#storybook/react": "^6.1.11"
Add "#storybook/preset-create-react-app": "^3.1.5"
Add this on main.js inside .storybook:
const path = require("path");
module.exports = {
stories: ["../src/**/*.stories.#(ts|tsx|js|jsx|mdx)"],
addons: [
"#storybook/addon-links",
{
name: "#storybook/addon-docs",
options: {
configureJSX: true,
},
},
"#storybook/addon-essentials",
"#storybook/preset-create-react-app",
"#storybook/addon-knobs",
"#storybook/addon-actions",
],
// https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration
typescript: {
check: true, // type-check stories during Storybook build
},
module: {
rules: [
{
test: /\.(scss|css)$/,
use: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "../"),
},
// { test: /\.css$/, loader: 'style-loader!css-loader', include: __dirname },
{
test: /\.(woff|woff2)$/,
use: {
loader: "url-loader",
options: {
name: "fonts/[hash].[ext]",
limit: 5000,
mimetype: "application/font-woff",
},
},
},
{
test: /\.(ttf|eot|svg|png)$/,
use: {
loader: "file-loader",
options: {
name: "fonts/[hash].[ext]",
},
},
},
],
},
};

Correct use of MiniCssExtractPlugin in a SSR React-TypeScript app

I have a SSR React-TypeScript app, built on Webpack 4 and I use SCSS for each React component. I use two Webpack config files, one for the client bundle and one for the server bundle.
I am in a bind as to how to use the MiniCssExtractPlugin to load my SCSS on the client Webpack config. The documentation isn't very helpful. It is evident that this rule is necessary inside modules:
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
But it isn't clear what file should go here:
plugins: [
new webpack.HotModuleReplacementPlugin(),
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
})
],
My SCSS files are spread throughout my application: each React component has its own SCSS file. I don't know how to pass these files to MiniCssExtractPlugin.
For the server Webpack config, I have the following to load my SCSS files and I don't know whether or not it's sufficient:
{
test: /\.scss$/,
use: ["css-loader", "sass-loader"]
}
I would love to see an actual working example of a similar app, if possible.
My css file as generated by MiniCSS:
.home {
text-align: center; }
.home-logo {
animation: home-logo-spin infinite 20s linear;
height: 40vmin;
pointer-events: none; }
.home-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white; }
.home-link {
color: #61dafb; }
#keyframes home-logo-spin {
from {
transform: rotate(0deg); }
to {
transform: rotate(360deg); } }
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvY2xpZW50L3ByZXNlbnRhdGlvbmFsLWNvbXBvbmVudHMvaG9tZS9Ib21lLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQSxxQkFBcUI7O0FBRXJCO0FBQ0E7QUFDQTtBQUNBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7O0FBRWY7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQSw4QkFBOEIsRUFBRSIsImZpbGUiOiJzdHlsZXMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmhvbWUge1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7IH1cblxuLmhvbWUtbG9nbyB7XG4gIGFuaW1hdGlvbjogaG9tZS1sb2dvLXNwaW4gaW5maW5pdGUgMjBzIGxpbmVhcjtcbiAgaGVpZ2h0OiA0MHZtaW47XG4gIHBvaW50ZXItZXZlbnRzOiBub25lOyB9XG5cbi5ob21lLWhlYWRlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyODJjMzQ7XG4gIG1pbi1oZWlnaHQ6IDEwMHZoO1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgZm9udC1zaXplOiBjYWxjKDEwcHggKyAydm1pbik7XG4gIGNvbG9yOiB3aGl0ZTsgfVxuXG4uaG9tZS1saW5rIHtcbiAgY29sb3I6ICM2MWRhZmI7IH1cblxuQGtleWZyYW1lcyBob21lLWxvZ28tc3BpbiB7XG4gIGZyb20ge1xuICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpOyB9XG4gIHRvIHtcbiAgICB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB9IH1cbiJdLCJzb3VyY2VSb290IjoiIn0=*/

SCSS file cannot import node_module

Tried #import "~react-icons" in an SCSS file.
I get an error: Module build failed:
#import "~react-icons";
^
File to import not found or unreadable: ~react-icons.
This was an npm module that I installed and is on package-json.
My scss code looks like this, the error is at the first line:
#import "~react-icons";
input {
width: 100%;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 20px;
margin-bottom: 20px;
}
My webpack configuration looks like this:
const webpack = require('webpack');
const path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
let BUILD_DIR = path.resolve(__dirname, 'dist');
let APP_DIR = path.resolve(__dirname, 'src');
let config = {
entry: path.join(APP_DIR, '/index.js'),
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?/,
include: APP_DIR,
loaders: ['babel-loader']
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader'],
publicPath: "/dist"
})
},
{
test: /\.(ttf|eot|svg|gif|woff(2)?)(\?[a-z0-9]+)?(\?v=
[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
devServer: {
contentBase: path.join(__dirname),
// serve index.html in place of 404 responses to allow HTML5
// history
historyApiFallback: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: 'Project',
minify: {
collapseWhitespace: true
},
hash: true,
template: './index.html'
}),
new ExtractTextPlugin({
filename: 'style.css',
disable: false,
allChunks: true
})
]
};
module.exports = config;
There is not an scss file to import for react-icons. You have to import the icons in the file you want to use:
import FaSearch from 'react-icons/lib/fa/search';
class Search extends React.Component {
render() {
return <FaSearch />
}
}

React webpack application not loading Roboto Font

I am working on React application where i want to use Roboto Font.I have followed the process to load the roboto Font. Following is my Project Structure :
My Index.css file
#font-face {
font-family: 'Roboto-Light';
src: url('./Roboto-Light.eot');
src: url('./Roboto-Light.eot?#iefix') format('embedded-opentype'),
url('./Roboto-Light.woff') format('woff'),
url('./Roboto-Light.ttf') format('truetype'),
url('./Roboto-Light.svg#RobotoLight') format('svg');
font-weight: 100;
font-style: normal;
}
My webpack.config.js :
const webpack = require('webpack');
const { resolve } = require('path');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
resolve(__dirname, 'src', 'js/index'),
],
output: {
filename: '[name].[hash].js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.s?css$/,
use: [
'style-loader',
'css-loader?sourceMap&camelCase&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
'sass-loader?sourceMap'
]
},
{
test: /\.(jpg|jpeg|gif|png)$/,
exclude: /node_modules/,
use: [
'url-loader?limit=1024&name=images/[name].[ext]'
]
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
use: ['file-loader?name=src/fonts/[name].[ext]']
},
{
test: /\.(json)$/,
use: ['file-loader?name=[name].[ext]']
}
]
}
}
and using css to load font as :
body {
font-family: 'Roboto-Light' !important;
}
I have followed this tutorial but its not working as expected and font is not loaded on webpage. Thanks in advance.
I didnt got any solution as of now.
Added Screenshot as per requested
Look like the app couldn't load the font face.
Please try:
in src/js/index.js: remove the line
import '../fonts/index.css';
rename file index.css to roboto.scss
in src/fonts/roboto.scss use absolute path instead of relative path:
#font-face {
font-family: 'Roboto-Light';
src: url('/src/fonts/Roboto-Light.eot');
src: url('/src/fonts/Roboto-Light.eot?#iefix') format('embedded-opentype'),
url('/src/fonts/Roboto-Light.woff') format('woff'),
url('/src/fonts/Roboto-Light.ttf') format('truetype'),
url('/src/fonts/Roboto-Light.svg#RobotoLight') format('svg');
font-weight: 100;
font-style: normal;
}
in src/css/styles.scss add:
#import "../fonts/roboto";
You can also take a look at this commit.
Update 1
You can use WhatFont chrome extension to check. it's Roboto Light.
Update 2
I found that you must use absolute http url because app can't find your font with normal path.
src/fonts/roboto.scss
#font-face {
font-family: 'Roboto-Light';
src: url('http://localhost:8089/fonts/Roboto-Light.eot');
src: url('http://localhost:8089/fonts/Roboto-Light.eot?#iefix') format('embedded-opentype'),
url('http://localhost:8089/fonts/Roboto-Light.woff') format('woff'),
url('http://localhost:8089/fonts/Roboto-Light.ttf') format('truetype'),
url('http://localhost:8089/fonts/Roboto-Light.svg#RobotoLight') format('svg');
font-weight: 100;
font-style: normal;
}
And the result:

Resources