80

I run webpack-dev-server from the root folder of my project. I have assets folder in /src/assets that is copied by CopyWebPackPlugin:

new CopyWebpackPlugin([ { from: 'src/assets', to: 'assets' } ])

If I put logo.png inside assets folder then After running webpack-dev-server I can't access http://localhost/assets/logo.png file, but can access http://localhost/src/assets/logo.png file. However if I run in production mode the situation turns upside down.

How to configure webpack server to make http://localhost/assets/logo.png file accessible in development mode?

Roman Kolesnikov
  • 11,777
  • 11
  • 44
  • 67

5 Answers5

57

I would add that it was the opposite for me. I originally had my images and .obj/.mtl files in a public folder that existed at the root of my application. I moved them into an assets folder that was created in the app folder.

Performing an npm install --save-dev copy-webpack-plugin and adding the

new CopyWebpackPlugin([ { from: 'src/assets', to: 'assets' } ])

to the webpack.common.js file fixed my problem.

Katana24
  • 8,706
  • 19
  • 76
  • 118
  • 5
    Thanks, gave me what I needed. In my case, `publicPath` needed to be `/` for my `index.html` file to be built properly but I needed my static files in `/static/`. This sorted it. – webnoob Dec 14 '16 at 23:23
  • Same here as i was already using publicpath for something else, worked perfectly ! – foufrix Apr 23 '18 at 10:08
  • 1
    For the record, YES this plugin DOES work with webpack dev server! The name is slightly confusing because this does not have to literally copy files around. – animatedgif Nov 06 '19 at 20:18
41

You can tell webpack to use a different path when loading from the browser.

In the output section of your webpack config file add a publicPath field pointing to your assets folder.

webpack.config.js

output: {
  // your stuff
  publicPath: '/assets/'
}
dreyescat
  • 13,558
  • 5
  • 50
  • 38
11

Update (webpack-dev-server 4)

Since the latest version. You have to replace contentBasePublicPath and contentBase (see original solution below) with static.directory and static.publicPath. The feature still works.

webpack.config.js

{
  devServer: {
    static: { 
      directory: path.resolve(__dirname, './assets'), 
      publicPath: '/assets'
    }
  }
}

Tested with webpack 5.58.2, webpack-cli 4.9.0, webpack-dev-server 4.3.1.

Keep reading the Original solution for further information.


Original (webpack-dev-server 3)

For everyone who wants real static files without copying them and landed here. The Webpack output configuration publicPath does not work.

You need the DevServer property contentBase and optional contentBasePublicPath.

The documentation really lacks on these properties. So let me explain:

Use case: You want to use static files like videos, sounds and images without copying them. In this example create a folder assets in your project root directory. The rest configuration is default (src, dist).

webpack.config.js

{
  devServer: {
    contentBase: path.resolve(__dirname, './assets'),
    contentBasePublicPath: '/assets'
  }  
}

Without contentBasePublicPath the assets are accessible with root URL. Since contentBase only defines the folder content.

Example: Place an image file "test.png" into your assets folder.

Without contentBasePublicPath you can access it with e.g. <img src="test.png">. With contentBasePublicPath you can use <img src="assets/test.png">.

your-project
|- assets
|  |- test.png
|- dist (...)
|- src (...)

You can use any path you want. E.g. move the assets to your src folder. Just place all assets here. It will not be processed / touched by the build. And the app is still loading from the default root (dist) path. This is what we want. The simplest and best solution in my opinion.

Tested with a TypeScript project and Webpack 5 (webpack-cli 4, webpack-dev-server 3).

Domske
  • 4,795
  • 2
  • 20
  • 35
  • 1
    This has been changed to the static field now (presumably because they hate us): ```static { directory: resolve_app_path('./example/static'), publicPath: '/static' } }``` – gct Sep 26 '21 at 17:07
10

You can do:

const path = require('path');
const express = require('express');

module.exports = {
  devServer: {
    setupMiddlewares: (middlewares, devServer) => {
      devServer.app.use('/assets/', express.static(path.resolve(__dirname, 'src/assets')));
      return middlewares;
    }
  }
}

My case was to serve files from outside the project root path, and then CopyWebpackPlugin felt like the wrong approach.

If you are using webpack-dev-server >=4,<4.7 it's onBeforeSetupMiddleware or using v3 it's devServer.before.

  • Thanks! This is what helped me. Easiest solution I found. – isaacsan 123 Aug 30 '21 at 09:23
  • 1
    If you use webpack 5 it's `devServer.setupMiddlewares` instead of `devServer.onBeforeSetupMiddleware` )))) – Vadim Jan 08 '22 at 15:31
  • Can't resolve for ... font face .woff file, .ttf,, .eot though – Steve Tomlin Oct 04 '22 at 09:45
  • Note: it won't resolve for ... font face .woff file, .ttf,, .eot from scss file, but it will work when accessing these assets from the public/index.html file. I suspect the setupMiddlewares for devServer.app.use does not work as it ddid - onBeforeSetup... – Steve Tomlin Oct 04 '22 at 10:26
3

i use proxy:

proxy: {
  '/static': {
      target: 'http://localhost:3333',
      pathRewrite: {'^/static' : '/app/static'}
   }
}
insub
  • 41
  • 2
  • `this feature is available with react-scripts@0.2.3 and higher.` https://create-react-app.dev/docs/proxying-api-requests-in-development – conny Aug 14 '19 at 06:27