Search code examples
templateswebpacktwightml-webpack-plugin

How to include images with html-webpack-plugin + twig-loader?


I'm trying to include an image in my twig template just like simple tag, but it doesn't want to include. For build, I use HtmlWebpackPlugin and twig-loader; But if I do the same with html-loader and html template - it works fine. How to do it right with twig-loader?

my webpack-config:

const path              = require( 'path' );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );

const PATHS = {
    source: path.join( __dirname, './source' ),
    build:  path.join( __dirname, './build' )
};

module.exports = {
    entry:   `${ PATHS.source }/index.js`,
    output: {
        path:     PATHS.build,
        filename: 'webpack.bundle.js'
    },
    module:  {
        rules: [
            {
                test:   /\.twig/,
                loader: 'twig-loader'
            },
            {
                test: /.*\.(gif|png|jpe?g)$/i,
                use:  [
                    {
                        loader: 'file-loader?name=[name].[ext]'
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin( {
            filename: 'index.html',
            template: `${PATHS.source}/index.twig`,
        } )
    ],
};

my twig template:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <img src="./chuck-norris.jpg" alt="">
</body>
</html>

my package.json:

{
  "name": "htmlWebpackPlugin-twigLoader",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack"
  },
  "author": "evisotskiy",
  "license": "ISC",
  "devDependencies": {
    "file-loader": "^0.11.2",
    "html-loader": "^0.5.1",
    "html-webpack-plugin": "^2.30.1",
    "twig-loader": "^0.3.1",
    "webpack": "^3.6.0"
  }
}

my project's structure:

.
├── webpack.config.js
├── package.json
├── source
|   ├──index.twig
|   ├──index.js (empty)
|   ├──chuck-norris.jpg

and when I execute npm run build I get dir:

├── build
|   ├──index.html
|   ├──webpack.bundle.js

without chuck-norris.jpg

And when I use html-loader instead twig-loader and html-template instead twig-template - image builds fine. But for my project, I need to use twig templates. How to do it right with twig-loader?


Solution

  • I have found a solution. Instead of passing to HtmlWebpackPlugin as template the .twig-file directly, I passed as template a .js-file, inside of which I included a .twig file and image, and passed the image to the twig-template as a variable. Now the project looks like this:

    my webpack-config:

    const path              = require( 'path' );
    const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
    
    const PATHS = {
        source: path.join( __dirname, './source' ),
        build:  path.join( __dirname, './build' )
    };
    
    module.exports = {
        entry:   `${ PATHS.source }/index.js`,
        output: {
            path:     PATHS.build,
            filename: 'webpack.bundle.js'
        },
        module:  {
            rules: [
                {
                    test:   /\.twig$/,
                    loader: 'twig-loader'
                },
                {
                    test: /.*\.(gif|png|jpe?g)$/i,
                    use:  [
                        {
                            loader: 'file-loader?name=[name].[ext]'
                        }
                    ]
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin( {
                filename: 'index.html',
                template: `${PATHS.source}/index.twig.js`,
            } )
        ],
    };
    

    my twig template:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <img src="{{ image.src }}" alt="{{ image.alt }}">
    </body>
    </html>
    

    my index.twig.js:

    const template = require( './index.twig' );
    
    const image = {
        src: require( './chuck-norris.jpg' ),
        alt: "Chuck Norris"
    };
    
    module.exports = template( { image } );
    

    my package.json:

    {
      "name": "htmlWebpackPlugin-twigLoader",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "webpack"
      },
      "author": "evisotskiy",
      "license": "ISC",
      "devDependencies": {
        "file-loader": "^0.11.2",
        "html-webpack-plugin": "^2.30.1",
        "twig-loader": "^0.3.1",
        "webpack": "^3.6.0"
      }
    }
    

    my project's structure:

    .
    ├── webpack.config.js
    ├── package.json
    ├── source
    |   ├──index.twig
    |   ├──index.twig.js
    |   ├──index.js (empty)
    |   ├──chuck-norris.jpg
    

    and when I execute npm run build I get builded project I expected:

    ├── build
    |   ├──index.html
    |   ├──chuck-norris.jpg
    |   ├──webpack.bundle.js