webpack-dev-server 404 & how to set it up correctly?

Marian picture Marian · Sep 1, 2016 · Viewed 8.3k times · Source

Where I'm coming from

I've been working with webpack for quite a while now but this is the first time I'm not modifying a starter kit for it, trying to set up everything from ground up.

I followed along this nice article on survivejs.com and inherited some of the approaches described there combining them with some of my earlier setups (like setting different names and paths depending on a production variable sent).

I tried to run "build" and "start" as much as possible during the lecture as to not get caught by some unexpected behaviour that I wouldn't be able to track back. This worked fine.

Then at some point while fiddling with the chapter about excluding unused css from third party frameworks I somehow broke my dev server setup. ("run build" still works!)

THE ISSUE

My hot server is defined at 192.168.1.2:3000 (that's just how I want it). When I run webpack-dev-server with the settings shown further below I get a 404 ( Cannot GET / ) at that location. Now I've read a lot about how to set up webpack dev server correctly but I still don't get it right...(most probably not alone here...) due to the fact that I still not fully understand how the paths work.

This is my understanding (generic dev server setup):

(Please help me if I'm wrong on any of this)

  • The output path of my webpack.config.js will only be served in the memory while running the dev server, thus not being physically visible (If the output was path: path.join(__dirname, 'devServerFolder' for example I would never see that folder anywhere in my project structure if it wasn't for me creating it)
  • A static index.html pointing to my bundle.js would be needed in a folder where I point to with publicPath as well as with contentBase (which could be my devServerFolder which I'd need to create with that index.html in it; usually in most setups around the web the same public folder used to save the production build in)
  • If I use html-webpack-plugin the plugin will generate that file for me automatically without the need to point to anything because the bundle.js gets written into it by the plugin

These are some of the points that really bother me to understand well. I have tried lots . of . different . combinations playing around with the publicPath and contentBase settings without luck to re-establish my dev server (worked fine first). Please take note that I'm not having any problems with code or with compiling my build with run build, which works fine and just like it should.

CONFIGS

Folder Structure

webpack.test
|
| - app                    // App folder
     |
     | - index.js          // Entry point
     | - greet.js          // Hello World called by index.js
     | - sass              // Sass assets folder
     | - pug               // Pug (formerly jade) template and assets folder
| - node_modules
| - public                 // Production output folder
| - webpack-config-chunks  // Split up webpack configs folder
| - .babelrc 
| - package.json
| - webpack.config.js


Webpack.config.js

// Irrelevant parts omitted

const paths: {
  app:   path.join(__dirname, 'app'),    // The obvious one
  dev:   path.join(__dirname, 'bin'),
  /* As mentioned above, from my understanding,
     the output path for the dev server doesn't really matter at all
     when using html-webpack-plugin, am I wrong here? */
  build: path.join(__dirname, 'public')  // Another obvious one
  ...
};

...
entry: {
  app: production ? paths.app : [
    'webpack-dev-server/client?192.168.1.2:3000',
    'webpack/hot/only-dev-server',
     paths.app
  ]
  /* I can modify the entry to just be paths.app for every case
     but it won't change a thing regarding my problem. */
},

output: {
  path: production ? paths.build : paths.dev,
  publicPath: production ? '' : paths.dev + '/',
  /* ^ This is where I've tried just '' or paths.app or paths.build
       instead of paths.dev and delete publicPath all together. */
  filename: production ? '[name].[chunkhash].js' : '[name].js',
  chunkFilename: '[chunkhash].js'
},

devServer: {
  contentBase: paths.dev,
  /* ^ This = "webpack.test/bin" – See above.
       Tried several different paths here as well without luck. */
  hot: true,
  inline: true,
  stats: 'minimal',
  compress: true,
  host: '192.168.1.2',
  port: '3000',
},

plugins: [
  new HtmlWebpackPlugin(),
  new webpack.HotModuleReplacementPlugin(){
    multiStep: true
  }
]
...

Answer

Brandon Patterson picture Brandon Patterson · Sep 9, 2016

If you haven't already, try putting your command into the npm script "start". Note that it's one of the few commands that doesn't need "run", so "npm start" runs the command.

Also, if you don't mind having webpack installed globally, npm can take the webpack command.

    npm install webpack -g

Below I am using the global webpack command (run the file), then telling npm to watch my files I listed for changes, run the build command, start the webpack-dev-server, and then open the server at my desired location.

    "scripts": {
     "build": "node-sass --output-style compressed src/css -o src/css",
     "start": "webpack --watch & webpack-dev-server --content-base dist --inline  & npm run build & open http://localhost:8080"
     },

Notice that I declared the --content-base dist --inline. You declared that in the webpack.config.js file so you don't need to declare it again in package.json. I currently do not have any devServer configs in my webpack.config file and everything is still running perfectly through npm.

From what I understand npm triggers the server and webpack.config.js holds the configuration for the webpack command.