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%;
}
}