5

I am a newbie to webpack. I am trying to write an AngularJS 2 website and have a requirement where I would like certain strings within my CSS / LESS / HTML / JS / TS files to be replaced with values taken from a properties file.

My properties file would look something like this:

example.properties

branding.title=My Awesome Website
support.telephoneNumber=+441111111111
...

And I would like to place tokens within my files in this format:

example.html

<html>
   <head>${branding.title}</head>
   ...
</html>

In the above I would like the loader to replace ${branding.title} with My Awesome Website.

Is there an existing webpack loader that will allow me to perform these substitutions as an initial step before building?

I just need a token replacement loader of some form - I don't mind if the file containing the tokens and their replacement text is in a different format to the one I gave as an example above. Similarly I don't mind if the way in which the tokens are defnied within the files (e.g. ${branding.title}) is different.

2 Answers 2

6

This is possible with the use of the html-webpack-plugin

Inside your webpack.config.js file perform an import of your properties file, hopefully it's in some well formed file type like JSON. If not you will need to parse the file within the webpack.config. Ideally, just make your .properties files all JSON if you can. Also import html-webpack-plugin. Add html-webpack-plugin to your plugins array. Then inside your template html file you will be able to access variables within the configuration.

The webpack.config.js would look something like this:

var config = require('../pathToProperties/example.properties.json');
var HtmlWebpackPlugin = require('html-webpack-plugin');
export.module = {
    // Your webpack config
    //...
    meta : config,
    plugins : [
         new HtmlWebpackPlugin({
             template : './src/index.html' // Where your index.html template exists
         })
    ]
};

Inside your HTML

<head><%= webpackConfig.metadata.branding.title%></head>

Webpack 2

webpack.config.js

var config = require('../pathToProperties/example.properties.json');

plugins: [
     ...
     new HtmlWebpackPlugin({
            template: 'src/index.html',
            metadata: config,
          })

index.html

<title><%= htmlWebpackPlugin.options.metadata.customValue%></title>
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for this - much appreciated. However, I would like to perform these substitutions across all my html, css, js, ts, etc files. So, I think, by using the above I would have to add a "new HtmlWebpackPlugin" line for each and every one of these files which will be very painful.
This sounds like a pre or post build process with your assets. Not a Webpack concern.
This was the right way of doing this in Webpack v1, but since they removed custom property inside the webpack config object, how would you do it in Webpack v2 ?
@RPDeshaies I'm spinning up a Webpack 2 project tomorrow. If you dont mind I'll get back to you then!
0

I managed to work out how to do this (although I'm not sure it's the best solution).

I am making use of the webpack starter kit from here: angular2-webpack-starter

  1. I first installed string-replace-webpack-plugin using npm
  2. I then created a properties.json file with contents like this:

    {
      "branding": {
        "title": "My awesome website",
        "colour": "#00cc00"
      }
    }
    
  3. I then added this at the top of my webpack.common.js file:

    const properties = require('./properties.json');
    const StringReplacePlugin = require('string-replace-webpack-plugin');
    const string_replacement_loader = StringReplacePlugin.replace({
      replacements: [
        {
          pattern: /\${(.*)}/g,
          replacement: function (match, p1, offset, string) {
            return eval('properties.' + p1);
          }
        }
      ]});
    
  4. I then added this in the loaders section of my webpack.common.js file:

    {
      test: /\.css$/,
      loaders: [
        'to-string-loader',
        'css-loader',
        string_replacement_loader
      ]
    },
    {
      test: /\.html$/,
      loaders: [
        'raw-loader',
        string_replacement_loader
      ],
      exclude: [helpers.root('src/index.html')]
    },
    
  5. I then added this to the plugins section of my webpack.common.js file:

    new StringReplacePlugin()

I was then able to insert tokens like ${branding.title} and ${branding.colour} into my html and css files and everything seems to come out as expected.

There is one downside to this solution in that (if you haven't already noticed) the above excludes src/index.html. I got around this by adjusting the definition of METADATA in webpack.common.js as follows:

const METADATA = {
  title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass',
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer(),
  properties: properties
};

I was then able to refer to my properties within src/index.html as follows:

<title><%= webpackConfig.metadata.properties.branding.title %></title>

Of course in this particular case I could just have replaced the title attribute within the definition of METADATA itself as follows:

const METADATA = {
  title: properties.branding.title,
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer()
};

And then refer to it within src/index.html as follows (which is how the starter kit defines it within this file by default):

<title><%= webpackConfig.metadata.title %></title>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.