Reputation: 1466
I struggle to get webpack configured as I want it to be. I run my dev-server on localhost:8080 and want to serve my app through localhost:8080/static/js/bundle.js and that is what I get with this webpack.config.js file I've attached below. in my file structure i've alse attached I want to serve also the other files located in dist/static as static files, so localhost:8080/static/css/style.css will be serving this dist/static/css/style.css file for example.
it is probably something wrong i did in the config file, and i'm not that familiar with webpack so i don't know if im asking the question so you can understand.
My directory tree is:
client
-- /dist
-- /templates
-- /admin
-- index.html
-- /static
-- /css
-- style.css
-- /js
-- /node_modules
-- /src
-- /test
-- package.json
-- webpack.config.json
webpack.config.js
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var plugins = [
new webpack.ProvidePlugin({
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
}),
new ExtractTextPlugin('app.css', {
allChunks: true
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
})
];
var cssLoader = {};
if(process.env.NODE_ENV == 'production'){
plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
cssLoader = {
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
};
} else {
cssLoader = {
test: /\.css$/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
]
}
}
module.exports = {
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js'
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['babel']
},
cssLoader
]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
output: {
path: __dirname + '/dist/static',
publicPath: '/static/js',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist/templates/admin',
hot: true,
historyApiFallback: true
},
plugins: plugins
};
dist/templates/admin/index.html
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link href="static/css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script src="static/js/bundle.js"></script>
</body>
</html>
thanks guys :)
Upvotes: 15
Views: 28220
Reputation: 6347
The origin of the problem is that the WebpackDevServer only serves from one folder. The folder that you should be serving from is the folder containing the index.html, which is what you're correctly doing.
So far you're serving only the content of ./dist/templates/admin
, therefore when you look for files in other directories you get a 404. The only exception here is your bundle, because you're setting a publicPath
that makes any request to the route /static/js
be redirected to your output, which is stored in memory.
You would need the WebpackDevServer to be able to serve from other folders. In your specific case, you need to serve also from ./dist/static/css
when you request the path /static/css
.
You need to set some middlewares in your WebpackDevServer. You can do so as described in the documentation of devServer.setup
. To do so, I suggest you use express.static
, as you're probably already using Express.
You need to require Express:
const express = require('express')
And then, just modify the devServer
as follows:
devServer: {
contentBase: './dist/templates/admin',
hot: true,
historyApiFallback: true,
setup (app) {
app.use('/static/css/',
express.static(path.join(__dirname, 'dist', 'static', 'css')));
/* Using this commented code will break the HMR, see edit
app.use('/static/js/',
express.static(path.join(__dirname, 'dist', 'static', 'js')));
*/
// in general
app.use('/public/route/',
express.static('/your/local/path'));
}
}
This way your devs and build paths stay the same, and the WebpackDevServer serves the static files you need, at the routes you need.
I just discovered that the code above breaks the Hot Module Replacement. The reason is that the middleware in the setup is handling /static/js/
, so the bundle is served from the file system instead of memory.
To keep fetching the bundle from memory define a publicPath
in the output
property, and don't handle it from a custom middleware inside devServer.setup
.
module.exports = {
output: {
path: ...,
filename: ...,
publicPath: '/static/js/'
},
devServer: {
contentBase: './dist/templates/admin',
hot: true,
historyApiFallback: true,
setup (app) {
app.use('/static/css/',
express.static(path.join(__dirname, 'dist', 'static', 'css')));
}
},
// other properties: entry, module, etc.
}
Upvotes: 14
Reputation: 1466
So apparently, and it make sense in a way, webpack-dev-server is not supposed to be used as a backend to load static files such as CSS or other static JS when you are running another server aside. when you set the contentBase key to a specific directory, the documentation says that you have to make there an index.html file and you can serve files base on this directory.
If you want to serve static files from other dir and you have another server doing it running side by side with webpack-dev-server, please pay attention to this section of the documentation.
What I did is run webpack-dev-server on localhost:8080 and my backend server on localhost:3000 and my backend server serves the admin/index.html from the root rout of it, on localhost:3000/, and in the html file itself changed the import of the bundle.js to be absolute path <script src="http://localhost:8080/static/js/bundle.js"></script>
.
Hot reload now works fine, and now i could also remove the contentBase param off of my webpack config file.
Important:
webpack-dev-server --progress --colors --hot --config ./webpack.config.js --inline
Upvotes: 1
Reputation: 7621
You are serving the app on port 8080. In your webpack config I see that you set content base dist/template/Admin but I don't see that folder any where. When you set content base it will serve Admin.html from that folder and if you have declared dependencies in that file it will load from you. You can take a look at this seed to learn more about it.
Upvotes: 2