reactjswebpackcreate-react-apphtml-webpack-pluginrtlcss

Generate two different index files for RTL and LTR support using Webpack


I am trying to have two different style files in my react application to support both RTL and LTR directions. Therefore, I am using RTLCSS and its Webpack plugin to generate two different files: (myfile.chunk.css and myfile.chunk.rtl.css).

However, in the index.html file generated by HtmlWebpackPlugin, one of them is injected. How can I have two index files like index.html and index.rtl.html? The second file should contain RTL style files including RTL chunks.


Solution

  • To accomplish what you are looking for, First read the plugin documentation for:

    1. Generating Multiple HTML Files.
    2. Writing Your Own Templates.

    Now, to have control over your generated HTML you need to be aware that any additional key you add to the HtmlWebpackPlugin config will be accessible through htmlWebpackPlugin.options.

    For example, adding dir key to the config:

    webpack.config.js

    plugins: [
      new HtmlWebpackPlugin({
        title: 'Custom template',
        // Load a custom template (lodash by default)
        template: 'index.template.html',
        // Extra Key
        dir:'rtl'
      })
    ]
    

    will be accessible in our template via htmlWebpackPlugin.options.dir:

    index.template.html

    <!DOCTYPE html>
    <html dir="<%=htmlWebpackPlugin.options.dir%>">
      <head>
        <meta charset="utf-8"/>
        <title><%= htmlWebpackPlugin.options.title %></title>
      </head>
      <body>
        <!-- print a list of all available keys -->
        <pre>
          <%=JSON.stringify(htmlWebpackPlugin)%>
        </pre>
      </body>
    </html>
    

    That being said, we can switch to manual assets injection to have more control over which CSS files to include in the page, for instance myproject.rtl.css instead of myproject.css

    webpack.config.js

    plugins: [
      new HtmlWebpackPlugin({
        .
        .
        .
        // disable automatic injection of assets
        inject: false,
      })
    ]
    

    index.template.html

    <!DOCTYPE html>
    <html dir="<%=htmlWebpackPlugin.options.dir%>">
      <head>
        <meta charset="utf-8"/>
        <title><%= htmlWebpackPlugin.options.title %></title>
        <!-- manually inject css -->
        <%=
           Object.keys(htmlWebpackPlugin.files.chunks).map(
             key => htmlWebpackPlugin.files.chunks[key].css.map(
               css=>`<link href="${htmlWebpackPlugin.options.dir == 'rtl' ?css.replace('.css','.rtl.css'):css}" rel="stylesheet">`)
               .join(''))
             .join('')
        %>
      </head>
      <body>
        <!-- print a list of all available keys -->
        <pre>
          <%=JSON.stringify(htmlWebpackPlugin)%>
        </pre>
        <!-- manually inject js -->
        <%=
          Object.keys(htmlWebpackPlugin.files.chunks).map(
            key=>`<script type="text/javascript" src="${htmlWebpackPlugin.files.chunks[key].entry}" defer></script>`)
            .join('')
        %>
      </body>
    </html>
    

    Applying the above will make it possible for you to generate index.ltr.html and index.rtl.html without hard coding bundle references.