theGC / html-webpack-inline-svg-plugin

Embed svg inline when using the html webpack plugin
MIT License
66 stars 25 forks source link

absolute path resolve #31

Open cyocun opened 4 years ago

cyocun commented 4 years ago

Hello! Thanks for the great library. I often use svg as inline for animation, so this is very helpful.

Now, I have a problem with my webpack setup and I've fixed it, but I want to pullrequest it. I've never done a pull request for someone else so I'm not sure how to do it πŸ˜‚

There are two points.

Now set the outputPath as options. This is important for my directory structure to pass the outputPath.

-        this.outputPath = ''
+       this.outputPath = _.get(options, 'outputPath', '')

If svgSrc starts with a slash, it's a relative path to . If thesvgSrcstarts with a slash, you need to add a. Also, if the svgSrc contains [hash] (e.g. foo.svg?abcd) Trim to. Added on line 498.

            svgSrc = svgSrc.replace(/^\//,'./').split('?')[0];

I don't know how to write better, as I usually make this alone. If you have a smarter way, please fix the file.

Looking at issues #10 and #6 , this may be an extra fix, but please consider this for absolute paths and for many situations where you want to set the outputPath.

idudinov commented 3 years ago

voting this up. I think this plugin should consider publicPath for images it should inline. In my case, it's /, so output src for all assets start with /assets/..., to make sure it will work from any route on the site.

not sure if the solution above will work though, but I think I could investigate a bit in this and create a PR if no other workaround is found.

cc @theGC hoping for a help!

AntonioRedondo commented 3 years ago

Hi guys,

If SVG file paths are relative to SOURCE, files have to be relative to the source entry template (the template config option in html-webpack-plugin).

output.publicPath is never taken into account by html-webpack-inline-svg-plugin. I'm trying to understand how this variable can be a problem.

So the issue is, if we have the below folder structure:

my-project
β”œβ”€ package.json
β”œβ”€ webpack.config.js
β”œβ”€ node_modules
β”œβ”€ src
β”‚  β”œβ”€ entry.html
β”‚  └─ imagesSource
β”‚     β”œβ”€ icon1.svg
β”‚     └─ image1.png
β”œβ”€ assets
β”‚  └─ bar.svg
└─ output
   β”œβ”€ index.html
   └─ imagesOutput
      β”œβ”€ icon1.svg
      └─ image1.png

with the below webpack config:

// webpack.config.js

exports = {
  output: {
    path: 'output',
    publicPath: 'public'
  },
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'file-loader',
        options: {
          name: 'imagesOutput/[name].[ext]'
        },
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      }
    ]
  },
  // ...
}

If we use loaders and SVG files are relative to SOURCE, the <img> element in the template will look like:

<img src="imagesSource/icon1.svg">

However, when webpack is resolving paths after files have been emitted to the output folder, because we have set output.publicPath to public, the resolving path to icon1.svg will be:

output/public/imagesOutput/icon1.svg

instead of:

output/imagesOutput/icon1.svg

and hence it will fail because that public/ addition breaks the correct path.

I think I understand the issue now. In the next months I will make changes to consider output.publicPath in path resolutions.