javascriptwebpackassetswebpack-dev-serverserving

How to make assets available by absolute url while serving and after building with webpack?


I have a following output project structure:

img
  ...
portfolio
  masttech
    index.html
  index.html
...
index.html

And a following source project structure:

components
  ...
  Portfolio
    img
      ...
    Masttech
      img
        ...
      index.js
      template.pug
      style.sass
    index.js
    template.pug
    style.sass
  Index
    img
      ...
    index.js
    template.pug
    style.sass
  layout.pug
index.js

And a following webpack config:

context: __dirname,
entry: [
  './src/index.js'
],
output: {
  filename: 'main.js',
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/'
},
devServer: {
  publicPath: '/'
},
module: {
  rules: [
    ...
    {
      test: /\.(png|svg|jpg|jpeg|gif)$/,
      use: [
        {
          loader: 'url-loader',
          options: {
            limit: 8192,
            name: 'img/[name].[hash:7].[ext]'
          }
        }
      ]
    }
  ]
},
plugins: [
  ...
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: './src/components/Index/template.pug'
  }),
  new HtmlWebpackPlugin({
    filename: 'portfolio/masttech/index.html',
    template: './src/components/Portfolio/Masttech/template.pug'
  })
]
...

The problem is all my image urls are just img/..., it's okay for index.html located in root but unsuitable for pages inside subdirectories. If I'd change their urls to absolute starting from / I think the problem will be solved but I don't know how to do it. If I prefix name option of the loader with /, the images can't be accessed at all.

For example this is how I require an image inside src/components/Portfolio/Masttech/template.pug: img(src=require('./img/pic__structure.png') While serving it transforms to img/pic__structure.7b94b5f.png, so that it can't be accessed from the output img directory since img folder is located in root while the page is located in portfolio/masttech folder.


Solution

  • Adding publicPath: '/' to the loader options has solved the problem:

    {
      loader: 'url-loader',
      options: {
        limit: 8192,
        name: 'img/[name].[hash:7].[ext]',
        publicPath: '/'
      }
    }
    

    Moreover I found out my frustrating fail - in the very end of webpack conf I had another output rule where publicPath wasn't defined, so that it rewrote the right rule with it. As a conclusion, you don't need publicPath: '/' in the loader options if you already have it in output.