我正在将 webpack(3.6.0) 用于同构反应应用程序,并且除了我的 css 文件中的背景图像外,一切正常。所有其他样式都有效,图像正在按预期在我的本地计算机上输出到我的 /dist 文件夹,如果我检查,我会在 localhost 的浏览器中看到正确的文件路径......但是如果我去开发工具中的源/dist/client 下这些静态文件的整个目录丢失。我正在尝试找出同构渲染,所以老实说,我对服务器与客户端渲染舞蹈方面发生了什么只有一点了解,而且我承认我的头脑并没有完全围绕 webpack 配置。到目前为止能够解决我的问题,但这让我真的很难过,任何见解都将不胜感激!
计算机 /dist 文件夹:
/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
浏览器来源(测试 w/chrome):
/localhost:port
---- /dist/client
---- ---- app.bundle.js
---- ---- style.css
目标 DOM 元素背景样式:
background: url(./client/media/bg.58dfa049.jpg) no-repeat center center;
webpack.config.js(客户端):
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(服务器):
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 文件:
.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%;
}
}