html-webpack-partials-plugin icon indicating copy to clipboard operation
html-webpack-partials-plugin copied to clipboard

Image path resolving is incorrect

Open Wouter125 opened this issue 6 years ago • 26 comments

Hi,

First of all thanks for this plugin, really loving it. There is just one issue, and I'm not sure whether it's related to this plugin or not, but let's see.

In my dev environment everything is working fine, and running perfectly. But when I try to compile it, all my paths inside the partials are not getting resolved correctly. They remain the same as they were in my dev environment.

My webpack config looks like this;

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPartialsPlugin = require('html-webpack-partials-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    context: path.resolve('./app'),
    entry: {
        app: './js/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: path.resolve(__dirname, './app/views/index.html'),
            inject: true
        }),
        new HtmlWebpackPartialsPlugin({
            path: path.resolve(__dirname, './app/views/partials/sz-main-footer.html'),
            location: "footer",
            template_filename: "index.html",
            options: {
                footerClass: 'sz-pitchdark',
                gradientClass: 'sz-gradient',
                buttonClass: 'dark'
            }
        }),
        new MiniCssExtractPlugin({
            filename: "styles/[name].css",
        }),
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['minify'],
                        plugins: ["@babel/plugin-proposal-object-rest-spread"]
                    }
                }
            },{
                test: /\.(woff|woff2|eot|ttf)$/,
                loader: "file-loader",
                options: {
                    outputPath: "fonts/",
                    name: "[hash].[ext]",
                }
            }, { 
                test: /\.(html)$/,
                use: {
                    loader: 'html-loader',
                    options: {
                        attrs: ['img:src', ':srcset'],
                        interpolate: require,
                        minimize: true
                    },
                }
              }
        ]
    }
};

------PROD-------

const merge = require('webpack-merge');
const webpack = require('webpack');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = merge(common, {
    mode: 'production',
    devtool: 'source-map',
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new webpack.DefinePlugin({
            'process.ev.NODE_ENV': JSON.stringify('production')
        }),
    ],
    module: {
        rules: [
          {
            test: /\.scss$/,
            use: [{
                loader: MiniCssExtractPlugin.loader,
                options: {
                    publicPath: '../'
                }
            },{
                loader: "css-loader",
            },{
                loader: 'postcss-loader',
                options: {
                    plugins: () => [require('autoprefixer'), require('cssnano')]
                }
            },{
                loader: "sass-loader"
            }]
          },
          {
            test: /\.(gif|png|jpe?g|svg)$/i,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: '[path][name].[ext]'
                    }
                },
                {
                    loader: 'image-webpack-loader',
                    options: {
                      pngquant: {
                        quality: '70-90',
                        speed: 2
                      },
                      optipng: {
                        enabled: false,
                      },
                      mozjpeg: {
                        progressive: true,
                        quality: 70
                      },
                      gifsicle: {
                        enabled: false,
                      }
                    },
                },
            ]
        }
        ]
    }
});

sz-main-footer.html;

<div class="<%= footerClass %>">
    <div class="prefooter">
        <div class="sz-content-wrapper">
            <div class="grid-middle_md-12-center">
                <div class="col-9_md-12">
                    <h2>Let’s brew something together!</h2>
                    <h5>We're ready to be part of your adventure.</h5>
                </div>
                <div class="col-3_md-3_sm-4_xs-7">
                    <a class="sz-primary-button <%= buttonClass %>" href="#">Get in touch</a>
                </div>
            </div>
        </div>
    </div>
    <div class="footer"> 
        <div class="sz-content-wrapper">
            <div class="grid">
                <div class="col-12_md-12">
                    <div class="sz-footer">
                        <ul class="sz-footer-nav">
                            <li>&copy; 2019 Strakzat. All rights reserved.</li>
                            <li><a href="#">Privacy Policy</a></li>
                            <li><a href="#">Terms &amp; Conditions</a></li>
                        </ul>
                        <ul class="sz-footer-social">
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/facebook.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/instagram.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/twitter.svg'></img>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <img type="image/svg+xml" src='../../images/general/linkedin.svg'></img>
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="gradient-line <%= gradientClass %> "></div>
</div>

Any ideas how I can fix this? And let my image path inside a partial be correct when compiling? Or is this related to the html-loader? All images inside the HtmlWebpackPlugin page do work tho.

Wouter125 avatar Mar 24 '19 10:03 Wouter125

hey @Wouter125 any chance you can throw this together in a Github repo where you're able to reproduce the error? it will make it easier to help you debug

colbyfayock avatar Mar 25 '19 00:03 colbyfayock

Aah sure, sounds good! I'll be making a small sample project later this week, currently caught up in loads of other things. Thanks in advance. 🙏

Wouter125 avatar Mar 26 '19 14:03 Wouter125

I'm gonna close this out for now since it's been >2w, feel free to reopen if you get a chance to put together a sample repo

colbyfayock avatar Apr 13 '19 14:04 colbyfayock

Heya, sorry this took almost a whole summer to get back to you, but I'm reopening it now because I finally got around to building a little sample project with the issue located (the other one where I previously had this issues is huge). You can find it over here;

https://github.com/Wouter125/partial-issue

If you run npm install, after that npm run build, you can see what I'm talking about. My html file get's moved towards a different folder on dist causing the path towards an image to change. The htmlwebpackplugin takes care of that for me and everything works as intended.

However all my image files inside partials (the footer image include) does not change and remains the same. Causing it to be incorrect and therefore I need to manually change it by hand after compiling.

Hopefully it's something small, or the fact that I'm doing something wrong. Either way, let me know if you need any additional info so we can sort this out. Once again thanks for building this plugin!

Wouter125 avatar Sep 15 '19 21:09 Wouter125

okay, so unless I'm mistaken, you have to require the image into the partial when using HTML Webpack Plugin itself, so for instance, if you were including this file in index.html, you would include it as:

<img src="${require('../images/footer/foreignrap.png')}" />

However, using that same syntax in the partial isn't working, getting an error stating require isn't defined. I'm guessing thats due to how HTML Webpack Plugin is making it work and it doesn't get included when I inject the partial.

I'll try to find some time to take a look and see what I can figure out.

colbyfayock avatar Sep 16 '19 01:09 colbyfayock

I do not need the ${require } part in this project anymore. That's what the html-loader is for in common webpack configuration. More about it here;

https://github.com/webpack-contrib/html-loader

It might be that it is related to that, not completely sure? But if we do need a require, that will work for me as well. Let me know, happy to help!

Wouter125 avatar Sep 16 '19 06:09 Wouter125

didnt forget about you. been poking at this here and there the last few days, just having trouble finding a solution integrating with html webpack plugin

colbyfayock avatar Sep 22 '19 19:09 colbyfayock

No stress, I'm not in a hurry but would be nice if we can get some kind of solution around this. Appreciate all the efforts. Thanks for the heads up anyways!

Wouter125 avatar Sep 23 '19 07:09 Wouter125

okay, so unless I'm mistaken, you have to require the image into the partial when using HTML Webpack Plugin itself, so for instance, if you were including this file in index.html, you would include it as:

<img src="${require('../images/footer/foreignrap.png')}" />

However, using that same syntax in the partial isn't working, getting an error stating require isn't defined. I'm guessing thats due to how HTML Webpack Plugin is making it work and it doesn't get included when I inject the partial.

I'll try to find some time to take a look and see what I can figure out.

That's actually the same problem I have: require isn't defined

<img src="${require('../img/dummy-user.png').default}" class="circle user">

Legends avatar Dec 29 '19 19:12 Legends

I've forked your repo and reverted it back to use v3.2. Now I can again use require in my template, but still not use require in partials loaded by your plugin.

Perhaps you have to hook into a different webpack event? hm...

Legends avatar Dec 30 '19 00:12 Legends

@colbyfayock

Just a thought, why this isn't working:

Example: My /index-body.html which should be injected into the main tag, contains require in its html page. When I use html-webpack-plugin v3.2 then the require inside of my specified template gets processed. As /index-body.html isn't referenced anywhere in my html/js it will not get picked up and processed by webpack.

Perhaps the injection happens to late in the pipeline when parsing of the require statement and replacing it with the respective content is already done?

The html-webpack-plugin v3.2 should be analyzed further to see in which hook it does the injection, so that the require gets processed correctly.

I've too little knowledge about the innerworkings of webpack, more precisely I don't know what plugin/loader (or webpack itself at a certain stage?) does this parsing and processing exactly.

That's what needs to be found out.

  new HtmlWebpackPartialsPlugin([
            {
                path: path.join(__dirname, './src/partials/index/index-body.html'), // uses `require`
                location: 'main',
                template_filename: 'index.html'
            },

Legends avatar Dec 30 '19 14:12 Legends

Yeah i think you're definitely right there, i've tried poking around some of the earlier stages but i couldn't seem to find one that i would be able to efficiently hook this plugin into.

as far as forking and reverting, does the plugin work "as is" with a simple downgrade? wondering if i should release that on npm until i figure out a way to resolve this

i don't have a ton of immediate time to look back into this, maybe by the weekend or next week after im through holiday travel

it's also interesting as html-webpack-plugin v4 has been in beta for a very long time. not sure what their roadmap looks like in terms of re-adding any of this or completely changing the api again

@Wouter125 if you need a solution still in the meantime, maybe you can try Legends' fork as well

colbyfayock avatar Dec 30 '19 14:12 colbyfayock

Referencing an issue I opened in the html-webpack-plugin repo here

@colbyfayock I like the approach of your plugin.

Unrelated to your plugin, but with html-webpack-plugin@next the require doesn't work anymore, so it's not related to your plugin. At least while it is in beta, don't know if it will be supported again when it's released.

But when I use the current [email protected] I can require resources directly from the template itself, but not from inside the partials. The partial gets injected correctly, but the require inside stays untouched.

We'll find a solution...

To make it more clear, when using [email protected], see comments in code :

 new HtmlWebpackPlugin({       
            template: './src/pages/layout/layout.ejs', // require inside the template works
            templateParameters: {
                'title': 'Index'
            },           
            inject: true,
            chunks: ['index'],
            filename: 'index.html'
        }),
  new HtmlWebpackPartialsPlugin([
            {
                path: path.join(__dirname, './src/../index-body.html'), // require inside the partial DOES NOT WORK!
                location: 'main',
                template_filename: 'index.html'
            }
        ]),

Legends avatar Dec 30 '19 15:12 Legends

thanks - that might help someone else running into this issue that needs a temporary fix

the only thing that im worried about is that it was an intentional design decision for html-webpack-plugin and we may need to figure out a new solution. thanks for helping dig in on this

colbyfayock avatar Dec 30 '19 15:12 colbyfayock

Just a short update: the "magic" happens in ./lib/compiler.js --> [email protected].

We have to update the template to include the partials before the childCompiler runs compileTemplate. Not sure if there is a hook for this ootb...?!

Anyways, as said, require doesn't work in v4 at all, so we have to wait for Jan (jantimon) to give us advice on this one.

Or we/you implement the logic on our own, but this requires deeper knowledge of the webpack engine.

Legends avatar Dec 30 '19 17:12 Legends

I've closed the issue in the html-webpack-plugin repo and opened a feature request. Besides the require issue, I guess with this approach we also don't have watch support when developing, means: if I change a partial it doesn't trigger a recompile.

Let's discuss all things there as I have made some suggestions how it can be solved. I can open the former issue again if you wish, just ping me.

Legends avatar Jan 01 '20 01:01 Legends

yeah - getting into the webpack specifics was where i was getting lost when i dug deep into this last time. thanks for getting that request out. im sensing a little pushback on it, but hopefully we can figure something out in some way whether it's with some first class functionality or a way forward here

colbyfayock avatar Jan 02 '20 01:01 colbyfayock

Sounds good. In the meanwhile I moved to gulp with a Webpack bundler inside the streams. Doing the partials through gulp and fixing the rest by using Webpack. That was an option that I still had luckily.

So I no longer needed a fix for the issue here. Hope you guys can sort it out! Thanks for all the efforts. Really appreciated!

Wouter125 avatar Jan 02 '20 21:01 Wouter125

Just wanted to give a heads up - haven't been able to find some more time to look at this and I'll be unavailable for the next ~2 weeks. Hopefully after that I can try to spend some more time thinking through this and getting it through the html-webpack-plugin compilation train.

colbyfayock avatar Jan 13 '20 15:01 colbyfayock

One way might be to 'import' assets using js. Then integrate it by DOM manipulation.

shariult avatar May 14 '20 23:05 shariult

@shariult if you're interested in giving it a shot, id be open to a PR :)

colbyfayock avatar May 15 '20 01:05 colbyfayock

okay, I will. Though I am little bit busy at the moment. I really like this project, so I will try to solve both issues. For now @Wouter125 , you can use this sort of a hack I use as a work around. See the image I uploaded, Annotation 2020-05-15 154128

shariult avatar May 15 '20 09:05 shariult

The problem still persits.... is there any solution or workaround? Thank you!

toabm avatar Sep 28 '21 09:09 toabm

i haven't been actively working on this, but i'd happily accept a pull request to get it fixed!

colbyfayock avatar Sep 28 '21 13:09 colbyfayock

Same problem here. Images' paths inside partials do not get procesed. Any solutions?

toabm avatar Nov 04 '21 11:11 toabm

For anybody else coming here, it looks like using require() in any html-webpack-plugin plugins broke in v4. There is an alternative coding pattern to replace html-webpack-partials-plugin suggested in this comment: https://github.com/jantimon/html-webpack-plugin/issues/1330#issuecomment-570077275

Invincibear avatar Sep 25 '22 20:09 Invincibear