Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work with webpack-dev-server #19

Closed
jefvlamings opened this issue Nov 3, 2018 · 9 comments
Closed

Does not work with webpack-dev-server #19

jefvlamings opened this issue Nov 3, 2018 · 9 comments

Comments

@jefvlamings
Copy link

This plugin assumes that images are written to disk. When running webpack-dev-server the assets are not copied to the destination folder and therefor will not be able to be read.

The fs.readFile throws an error because it's not finding the image in the destination folder:

{ Error: ENOENT: no such file or directory, open '.../dist/img/menu-1d840d305cccb544781eccb64422f684.svg'
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '.../dist/img/menu-1d840d305cccb544781eccb64422f684.svg' }

Please note that the plugin is working fine when just building with webpack.

@tr1s
Copy link

tr1s commented Dec 12, 2018

+1

I'm having the same issue @jefvlamings. It's looking in dist/ which is the problem.

Any ways to fix this? How do we make it look in src when on webpack-dev-server and dist/ when built?

@ngtinsmith
Copy link

Setting runPreEmit to true fixes it for me (refer to this)

plugins: [
    new HtmlWebpackInlineSVGPlugin({
        runPreEmit: true,
    })
]

Then set your src path relative to your package.json file. e.g,

my-project
-- package.json
-- webpack-config.js
-- <node_modules>
-- <src>
---- index.html
---- <images>
------ icons.svg
------ foo.svg

so your path will be <img inline src="src/images/icons.svg">

@juanramoncarceles
Copy link

juanramoncarceles commented May 25, 2019

@antesgeist It is not working even with runPreEmit: true.
I have the same project structure and I get this error:

Module not found: Error: Can't resolve './src/svg-drawings/GROUND-FLOOR.svg' in '/mnt/c/Users/JuanRamón/Desktop/svg-interactive-drawings/src':
Error: Can't resolve './src/svg-drawings/GROUND-FLOOR.svg' in '/mnt/c/Users/JuanRamón/Desktop/svg-interactive-drawings/src'

The only thing it is doing is replacing <img inline src="src/svg-drawings/GROUND-FLOOR.svg"> with <img inline="" src="GROUND-FLOOR.svg">

Maybe I have some incompatible webpack.config.js settings. Which were yours?

@victorcrbt
Copy link

Does someone manage to fix this?

When I build the project it works fine, but in the Dev Server it's just a regular 'img' tag.

@ngtinsmith
Copy link

@juanramoncarceles Didn't see the notifications for this man, but yeah, it is still working on my previous project.

It might indeed be a Webpack config issue based on your as I see the plugin isn't picking up the correct project path for your SVG.

See below for further instructions if you're still trying to get this working.

--

@victorcrbt

Here's my relative project repo with this SVG plugin setup. https://github.com/antesgeist/todd. Tested it just now and it's still working.

Dev server: npm start

Check over my comments on my webpack config and see how the rest of the config/directories are setup.

I've run into similar pathing issues before and tested different config types, found this one below that works for my setup.

webpack.config.js [loaders/svg]

    /**
    * SVG Loader
    * 
    * [path] = relative to template url: 
    * e.g, if template is in src/public/index.html then [path] = src/public/
    * [path] is prefixed to "name" to allow html template
    * pre-parsing with inline-svg-plugin
    * 
    * emitFile: false since we don't need to write/emit assets on the
    * final build, we are handling that with inline-svg-plugin instead
    **/

    {
        test: /\.svg$/,
        use: [
            
            {
                loader: 'file-loader',
                options: {
                    name: '[path][name].[ext]',
                    emitFile: false
                }
            },
        ]
    },

webpack.config.js [plugins]

    plugins: [
        new CleanWebpackPlugin('dist', {}),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'src/public/index.html',
            svgoConfig: {
                removeTitle: false,
                removeViewBox: true,
            }
        }),
        new HtmlWebpackInlineSVGPlugin({
            /** 
             * runPreEmit: true so it'll run "before" the html
             * template is parsed by html-webpack-plugin
             */
            runPreEmit: true,
        }),
        new MiniCssExtractPlugin({
            filename: 'static/styles/[name].[contenthash].css',
            chunkFilename: '[id].css'
        }),
    ]

On my setup, I am pulling SVG assets from node_modules packages but you can also use directories relative to your html template as noted on the snippet above. Here's how you can do so:

--

From node_modules folder.: The tilde "~" prefix signifies that you are looking in the node_modules directory, I think this is default webpack behaviour.

    <img inline src="~jam-icons/svg/airbnb.svg">

--

From template relative directories. e.g,

HTML template: src/public/index.html
Relative SVG folder: src/public/svg/airbnb.svg

    <img inline src="svg/airbnb.svg">

@slavafomin
Copy link

I'm facing the same issue. I've managed to fix it with runPreEmit: true, but I don't like the idea of specifying the path from the project's root directory, such paths look ugly and unintuitive.

@ngtinsmith
Copy link

@slavafomin

I agree it does look verbose if you have to pass the full path, but as mentioned on my previous reply, you can use this plugin without specifying the project root path by letting Webpack handle the path resolution.

Simply configure your SVG loader like this:

{
        test: /\.svg$/,
        use: [
            
            {
                loader: 'file-loader', 
                options: {
                    /* here, you are telling webpack to load the assets automatically
                       "relative" to your index.html template, not the project root.
                       That is what the [path] alias is doing */

                    name: '[path][name].[ext]',

                    /* this one is not to be confused with the runPreEmit plugin option,
                       this is just so that webpack won't emit (copy over) the svg file
                       into the dist folder when you build your project */

                    emitFile: false 
                }
            },
        ]
    },

Then you use your SVG assets like this:

template: src/public/index.html
SVG folder: src/public/svg/airbnb.svg

<img inline src="svg/airbnb.svg">

@theGC
Copy link
Owner

theGC commented Apr 27, 2020

hey all, if anyone has a better method than the runPreEmit option then it would be great to integrate it. It was something I never needed but was asked to look into, as such it was rolled up quite quickly and probably isn't the best way of doing this but I don't know of another.

I'll close this for now, but if someone is able to push a PR with a better alternative that would be awesome.

@AntonioRedondo
Copy link
Collaborator

All this confusion with webpack-dev-server and inlined SVGs comes because of the fact in the former documentation it wasn't clear what were the correct paths depending whether loaders were used or not.

Now the documentation has been refactored and it better reflects the three ways SVG files can be referenced:

  • Relative to OUTPUT (no loaders).
  • Relative to ROOT (runPreEmit config option).
  • Relative to SOURCE (with loaders).

Documentation now also has a new webpack-dev-server entry to explain how to use html-webpack-inline-svg-plugin with this dev tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants